Changeset Extraction v7.0 (was logical changeset generation)

Started by Andres Freundalmost 12 years ago155 messages
#1Andres Freund
andres@2ndquadrant.com
12 attachment(s)

Hello Everyone,

I am pleased to announce the next version of the the changeset
extraction feature.

There's more changes than I can remember, but that's what comes to my
tired mind:
* Initial userlevel docs (including an example session!).
* generalization of the "replication slot" system to also work for
streaming rep, although the user interface for that is mostly missing.
* don't remove WAL still required by a replication slot, be it a slot for
changeset extraction or streaming rep.
* New output plugin interface with one _PG_output_plugin_init dlsym()ed
function filling out the callbacks.
* Renaming of the init and _cleanup output plugins to startup and shutdown.
* Simplification of the prepare_write/write interface for output plugins
(no need to specify LSNs anymore).
* Renaming of the changeset extraction operations to
create_replication_slot/drop_replication_slot/start_replication
... logical.
* moving the SQL changeset functions from a contrib module into core
* Addition of peeking functions for changeset extraction.
* revised error messages
* revised comments
* ...

I've followed Robert's wishes with generalizing the replication slot
interface to not only work for changeset generation, but also streaming
rep - not sure whether that was the right choice, it's been more work
than I expected blocking things a bit but we're there now....
There's no clientside support included except as in the pg_receivexlog
hack attached as the last patch, but I also have tested it via streaming
rep and it mostly works (minus a hot_standby_feedback bug, will report
tomorrow).

What I think is missing:
* The user docs need more work, even though we're in a much better state
than before.
* Replication slots are stored in binary files. I think it might make
sense to store them as text files instead, for easier
extensibility. Especially since we want to use them for streaming rep,
I am pretty sure new attributes will soon come. I don't think it's
critical enough performancwise to store them in binary.
* Contrary to what Robert and I'd discussed I've named the SQL functions
outputting changes decoding_slot_(get|peek)_[binary_]changes instead of
decoding_stream_* - I can change that, but the SQL functions don't
actually support streaming, so I thought that might be
confusing. Opinions?
* Robert complained earlier about the way historical catalog snapshots
are forced in tqual.c - I don't really know yet what the better way
would be here.
* Some functionality probably needs to move between the patches - it's a
bit hard to see where the best boundaries are.

The sources are in my git tree at:
http://git.postgresql.org/gitweb/?p=users/andresfreund/postgres.git;a=summary
branch xlog-decoding-rebasing-remapping.

The last two patches are *not* indendet to be actually applied, but are
useful for testing.

If you want to test, you'll need a clean initdb, set wal_level=logical
and max_replication_slots>0. There's a example SQL session showing how
things can be used....

Testing, Review, Questions welcome!

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-wal_decoding-Log-xl_running_xact-s-at-a-higher-frequ.patch.gzapplication/x-patch-gzipDownload
0002-wal_decoding-Introduce-the-replication-slot-interfac.patch.gzapplication/x-patch-gzipDownload
0003-wal_decoding-Introduce-changeset-extraction.patch.gzapplication/x-patch-gzipDownload
����R0003-wal_decoding-Introduce-changeset-extraction.patch�[ys�F�������5)Q�Z{#���Z_�R^R/�b
�� �����_����!�NT�E�=}_3z�&S���������?V�������:�5P��~�(��=�.��������vO�?��v{��@s"�b?UZ�NU��_��� c���*�����+�����;bO�R�{�;8���V���6���o��N�/�n�/Ew����*�e4����a<>Wq�&~�)�Md<VZeB=d���0����I�E�i���Je$�	��IsS<KU��*�A��gb��������TI��tHcm�j����VLE�*�3��|Ga�����0�	�A�_��d&�d,h��$�K@��D��hC��be,FJ@�@�%������6O�X��$�fy&fQ>c�
R	�s/�Spf��Q4���n�M�#S�NG
0��0����4����X;�F��v���'u�{1��4?*HB���d��2n��b�&
�,U���J3q)�n^���6o�8����^����x'�L�g�I�[��w*N��k7�A~RE���=��:��?���n^g���Ex�<O|%^���96�?����E8��B�����S���q�Ew2M��JS�Ps{{�)t����T��J�w'J��9��������/��C���R����nOl�g���t�k����*8�_[�������q�d����M����0��e>�M���0#���EL����*���zQ�af���������T@�I/�W(�"��MS5�B�
&��N�� DhYC�zH��%L��S 9RT
������������<�c�eN�<0���ZP������?_�WDd��Hd�]�T4���Tx�`}k��:�c����Y�x2M�|���`�x����?Z\O�"���&���*����VAS��Eh	���,�*�1�����vW�~�W�K��C�Z��1�3d��B�����a����j���!���*���:�j�^	:���Qw�J�JH"u�b0�;X�����xHf�r��19��C�����ezq�U��h����� ]�Yd�{�Hw&�={G�A��ih
�
(A
��G���D���ed����.I�����U�`��D��,��j3���EPm��z��/nj\�0�[
�B�j���4��=������lLuM��f���U�w�Pg�@���@Pb��XF_st�w��[�������F�s��=R��v�)<xq���P�������k��ve�wE����5�w�X(�G%���,|}P���F�o][����	���M?��=F#%w�������-����=�����j��K�aO�������~�AlS9��!V��~_�!-�Ij%So24bj]!�~L��Y���"	Zq��#^�Ra :M�h��]���7}�������F������l�N�r����p��f�2���#&-/bFtL�C�h3E#`�u���"��{�,E�����h�HuG��Xff���J���N���&���3h��Y��X�@�'s]�B�7��_!e
[
c%�	P�fmz�y��H����y	(�2���D��#`��B��(��%��)��U�E���+j�VY��-R�
q���H����Fe/���}�OGP��"�&A���is�����@��3mH��f�(�q����m+l#����!4���sq��(���?%��
JK�)�9�(�vs��?K�q���4��g-��S1�%��k��6���1�u!���#hT�*?$�P�#�X1/I,n��9��`"�����J�]��<��Q���������u������(i��6R��,���;���L���v�\j�>0z!�2�dD���fxyq��?�t��������O���C��-h��v+#D��QV�<�Nx'�����W��Q�p"��6N�c������F�&y	�����m}��>����;������������w��������N�=����`���&�1Kt�	r�)�[�����f9����>�c��VoLC�IJ�r���|Sk
y�5�l��jA�9\��hW��gY"y�E�-��^f���sm����~ey��n���lI2�@��z��^�SE�`a*�L�>US���%B��������F�vC*���_���@������*�u������V�pB��d�|�������H��.5�G��N�78���J���0cx����}�5���h�z�D>"At��W'y�)q&DUW���\��l��"�����AkM�7KgxX�F�*��lz��?A��5N,��b����Q$������l7�XJp7�_�sw��\m�,B��{iy�������m:81����I7�B>$������!)J)��8��o�3�+_�C���C�y �i��9�P�O�Y��
�wJU���*�����T��j�)a������ �H��$�2�,C.,����dy,!wr1�<��"�j,a�j�.:(�yy�T����f�pJO������\f��d4��fj��s�6�z�x������I�'"�|hGgS��y����j;�u�Fje��vKg`C$q#/��b�{�c2������p}l��xys��!��d�12U�)����4��2�&���Q�H�On��g8��E������5�ft�����������s�z�gBu���D@^�w��)�^�L���b ;�Q�c��q�&���~go�j�z�������I���w=��	�5J��U�m�A����/��3�i8�d�����f�h`�X3V�=�HV�jK�k�l�w��
�]V�*"��V�6S�F��;��]`���B�|��+��x->�� 	dj�@8�0�Y�UV�j�AJ�)36����W(u��S
"{��F��h�$z��6��l�����?��xvs�+�K�:�(�����e�9��b�n���Lh<�@��m��)��cRt0�2����'����F37�k�]^#�U)a!��Tv���2 �3(6�S���!�**
��{��9]�OA�TM�o�d	��Y��G�Q4O2G���T"���K`���rcj����g��}m��%�e���A�T�s��DW���K�[S��
�(g�����L�j(�rY2��>��
��S����/��j��b�d$z��H�Rxsr��B��R���.��TIG>|)�� �
|Z� �E�CE%�pEW��B���(f*����bqH�z>M�SY�0����-�w����*6���������/<���X�p��&?�H+�( �!�
����/�����Is{�aZ�:�wD�������z��|eX�$�\� ����
����jV�R�,lQ��f����ui��?�3����
~�f|L1/ �Rxf������9C#��t�Y%Ak��h��c�o�([#�:��:t��6Dx������s����m	h�|{�������n�f���g4�t�6�����~NX�{{,�����_#��j�-�7�IZ�3�^+�Gbj%@5����`��A�Gd���O�x�F�;��{���3k-���C6F����bA�����@#��������
���}s����O`8U��J��`��s��#+����l1`�UM+��4%k�Yu*j�o<��,�"y�Ra����UP)"Bm�3���6U��I�;"���!J��b�O������WTTvhu\m�U���7%2����qg ������K����53�W������(����]a4�����~8a�](3u>��z��"��	���9��.��F��&4:��||�������~�SgG���f"#2R�G	���Hm��m�9��8��FE��tZ���YOuv&Ko���?�tY�����-�����J�����_����L��bwV��,C)�'<-$gN�$���W�5 �� Q��2-x���S��&�������w6���f���gk�����&�|0CR�5V��-�����j�^2pC����B���Q���)���b���s���z"9��[��1�(�.�
Wn�������� U�df��5d���� �B{s���������i���Q7����6�t��iA���-bh?���4����6��{���8G�I�F��l������6`�Z�
m������/9;O��l_�@e�3��w�}����R����5:S�xM4GF>cT`�St^��	��/(�El�TQ�9��I�����;u��F�����}(�����?=�������P���/��M�H��	��'ad��=��mk�� Q�O����]m3�%�0S��G(�-d��Y�o��#aw6Uh:���]�oG�������Wl�����h��<Q�L��:93a�x&�'J���$�-m��l2Ng��s&��(S��M�C�i5�TEN���������P[C���� ��J� ��Q����&�%P[%Z��DeS+e��bU�m��U������@=(�U$l$�T��aLI�p	���0�[���]��Of*v�(�3s�lVH�@SQj=�MQ���:��g�����"+�����dQ#.�?6����Er�#.��S6�!�����!���N���f-����
\{�@r+��}�)k������C�!�|����%4G-^��0��
�E�!��%��	<��� ��m{�Ue�>��u�B�6�\]%aG���t���)i��E`�0��f�(L��"��X�Rt��Y��p���]Kv�H����fr�Y^�����-�#�[M���/���1	���*����X(��_��C��K+4�5�	�����t�� �M��V��Ii��D��w�
i�y�)��gN��p�2Ul(i��[��B��2�)�����j1��^Qq3=�:�q�&L�!�1������c��!��,A�,��
l*�S��V�v�t'�=�zi�[��l-�[�6Q4����������#`zC/�N��j'f$Ps=��}���_��/����Ja��B��3��H#L�0X����xIl�T�c�<�-��f�
&���Ne���]���r���J�1to�*�	�����4qia��k�vh�f�`��i��^s���<���{����m'cbUj�O���Ds�.�d
�3sU�~Z���8�����!�f{�����C���i��)���S������.�k��~R�@� 3�l9R����8&���(����Q)����y�
&�qh���P#��ALz���=]���rz�"��k�N����X�d��iM�
��W@��]�:}sg�X�FeeYd�_[���U����m�M�t���rGt;���6ct�vn���]W�Gm-.�^>M��L���VW�M��d�#"����t�K^I��'������]����J��Q��	e:
�ZS��B*��	wK��(�fPl^��x'�������o�>�w��?������X�R�4���"���������xW+��,��_+���(D�x�^_��������k4���}�O����*��N���n�s��T~�?���>�,^�p�����PA�����-���/�!�K�����x���^Gl��?�uG��h�X�x|O�%���L���R�����eL��jA�4�_�
nZzs���Z�@\��8(�Ct3�����'�L�-�{�|Qa��!_��w���3@^�!���?J�jk�<u�=w�o�#0��j����z��@I��Lu�������I~��
��8W{�Xl��g�[��Mm��zQ$�������9Iu$����V,��:Yb���r)=R���� ����������x�����#�.b��f���%����f�9�rjL���_6���?{���D���~�E�l@Y
��z�m�����MAOM?:))m� )�J	��������-#u1Tu���g�.��������.$$��]��GjZ���#��x�d�9��o3��"���_��i��O-�[��@e��M����#���}[m(�W���5�C�	xn����}5�q���=��l�^d<B����
\
�M��2d�pj�@��J��$
{���WQ6��c�w
�F����(�M5�"��g-����l����Ho|����Aa�4*#��_��K��y���K��C����q��:��������K>�C�O��-u����t��ecq�����c�{�P�<�- k	!���CC,5�>?&$D�@������;��vq=*�����	�B��Q�(���jf��j��������J<�n%������p����
0F�nc����D��F6�`�>�l�}���FS[`(���h���Y��K|=���;��������!c������~��RX��&��������!�
�-�BL�f���#�����i��F/>��BN��p:��C�1�jh�}s��'o%)c���h%���o1��^�
\Kg&�	�F�31W�]���E�+K��R����J�+h��5h����G�8����.+��H&M�
>O��4�}Wf�n��Lb#���Te�m�m�?����7��S
�fD�~m6�������(������r����������A��fc���j����+Sb�"F�/������z���)%4��������S�o��t����Odu�Yw��F\�&"m����gj�B*�/��������ti!��bW�8sh�L�s�c9�Y��RH�+dJ$ZO� �8���I`��l�����h��\���;�]�}����b���1RH�:��q6����%dp�c�-���$���8d������L�h<��<��6C�5Mn�/:���%��������}��Z������3}�>F��fgb��>��j�aG�w$M��Y���I�V�������?�LlE�Wa�8�}��z����h����5|!���s��}���u�>���O������?�>����ig����	<����_V�3_����YI��0�5����,J���MZ�gK�sJ�&I�x�s�Wq�z
�i�`c����P�Qq��Q���s���5T;�H/<��C�y��#rG�� ��4��y�Z�e,�L�c����3�J�����e��;���Xje�x�O��YY�P@��Vb
��	$l&�.l|y&4��.u��0�^�.�X�=_���sc&��x��7��������s�����\H�4��>����Qx�S�&2���l���B�<hxk��Ja��;2|`�	���.#��iz�d]��3=�?����$_�jc���Rl$e��������!
\�fr�nr�{~�}�����$��Ik� ����H��i�c��������&��H:��(f�a���b������mX�
�(�����zp�H�������O{�������H�aZ~t��nnsH������jW2����v�"���.������5Y{�21	�Y	f�����T����n'������KYxZt"k�Wx���Mjp�+KJ&�i�N���?�^$\��K�&U��h>F�����)V��|��?�}4��d��������3� �sW.7��)����k�j:���Gi����p_&�/��/#|�m��mV�(b(&PR�9�r���XV����>���,�!rO4AP"L�e8J�xJ����}��#���������d��/aH.fp����2�8v������b8@�C>X�D�
L�_r>�Q�
�_��HK�N?$�J�m��D2T��9�t����g^yWl�U�GFz���lD���������-��uo������Ay�a��
����N(0bA��B��X0�}�;#�N�^���s�u�������F��R�hg�Nj�v����:@��QHi�'c������S��E�
~��`~2������N6^���O.���*���X�am\�q��-��"���#�T���
D��8��=t�EC��L�1qi)�PM	Qmt��`\���yY:s�A���b���Pu.Q�Y%�?�buL�_ky�c�����x�t��T|.����MG���T����1.��Gl �z''���R��V'�JN��~������_����]b{+��.���8p*'>y�����Q
���#����x�:
8�^��-��A�kM���Jq�����,����V2�gx����&�TBZ��H:p�(+���A���8Z4��Q��Z�z������4"v�����������V��T �!���}:)f]���S<�C�=���Z�:o�G��E�y4;��=�8�zy6Uc��	Y��XM(]�
����=z���D�E8z�l1t=����rN"���P���C�x�
z�~�j���v�tI�pg����C�������4�~����+�W"��&���I�F2�/�b�����4��0P+v[�����?����wD����'l�pD�OwX����=�o���t�0�gC���������Rh���'�}Pw(	s��(��kJWh2�f�E/�D5�{����z9����	��E�w������
G3����v��x6�����@��7X?�^�t2�����9v2|Az�e���7��GU������F�.jv�����I�"+��\�v��������VU����
M��O����<�����K����g����f�S������$Mz��3������si�nRxA����b3��6��������Ny��T�a \3�����0��OO�^7�I#c��P�)f*�O��z�V6�+u����jW�0�'�<�XB���.������x���-�K��]g��_v�i O�M��|w:�!���I���v���A����G�����Kr�IL����V��-�2h���#���,�[�	���E-�('*O���y��r'�]�09��g����)����� ���G.����N��&�G�� +�e�F������(�s6�|\���i���\f�N���&�������uw�25�����F��J�U	���?k�s_����J~Rt��g���A/�����im-z%��r0&?I�m��j�u\"����X.��j�b>��_M�,�Yr^+E��4 ����H���������v!p��Z$�Xc��zB�,��G-�3�h�N���?:/�C�JP��3��2�J88�Y{4�,b��?�^���L[aS�Q"��o3:�0;��,r���H(h������
��������$s��9��>|w��?|u��$m5�I-�
]K�����Mq!���{��Q�������������>~��?���r�v��
�0}CxV��TO�
�@��3����Ym�5�����Q��`���a�������Bb	/z�{A����R�o��`1:����}��Z��Ve6�W���t2��)�
=��6��-"��o�<<��&$��Lp�?�������a��(g@!��d+�J�5�59��|���*��C�R�F����'�'M&#1�X�L1q7�� s�l8CC-��iK�<8��a������v�W���JBj�"rUH�|���&/M ?c��4@��F��L._B���X���C������q;f~
�XI1�������g'���(�p&a"X���E'����%�����sl]����EF�����rY/���^��e'��i�r|6
2���D$�RM���,_"bM	I��F{�~�?$u�~KHt�?��)���|=�q�{KFh����Z���4������y���6s:�}t
��%��A��)��i�l�	hU�WJ������.AU�d�1��n&nI�Gz�<>�qDL��G��/0L��A}�!�]�@qY�_:]���>%r����]rSM����I��Q��sT��S��g%��H�gV�����OpYx����%�����dX�w�����f���N�DXf�#��L��$�0�)���A8
:h~��k��[��
H�^�S^����+��t����\]���`Y7���U�&!���^�����
,6(�+�i��?r���L��]�H��pN��pjQ�����x=�	x@;��-��yS������y��[��#9�*�f���l����L�^^O����c��t"6(���b��|>@�E6�^�*�p�<$z3��yuGhX��y�&���G��F�U�����8���=(�m�'�|Qm��5c
�Zjjj��372�����KM�D�1�����s����
����0��q���/� �'����B Z�V��;y�L"pC~B2���Ca�E����(�����JR��np@�S�}eW�7�a
���"����Z�0����T-
Y�=���n��y��7�*a�~U[0���$W���}|JrJ��td�xQ���T��X�������z�1W��cJ/T�m�������w��r�*�5{��_��P��FSMZ����F?zi��i
������:%\S���L�c=%T�{w4z��;�u�>m����q�$�c"�t!�j#..�=j���S��K��7('D�q��G&�`��<�7,��r�2r�����r���jN������0���e�>�$"?�~�Z�L@s���_D9_��C2<�c���}�bx�s! ��(��A�����>�uK����#�\�r7��"5�k��4Pzz���������~����=�.���mD���?��O��z���
l��7���<��=��������Y��obN-�h5�[�0�����7�������~R�kHwv���q~��4��S��J��#�iv��\Z�+����)s_73\����cT�:-U��Z�J�]���P�6B+O�O�<L�v������h	Z�z�C.^;�Jv��b��)GwC{�bs^���4����o���R�
'��RaV�=����~��x$S1�����%
�����)>�l���x;q���5�����h����d�fG$���o��O�!��3J����
���"cX���W�IdXt����n�@�I
��c��;2�<�������E���\�S�-�%��w�i�m6��Q��S�R��5�0�����Q/�*k�\������f8L6�o3
��k�b�]12�%����A(��%g� �c�
�����~��S0w��h������n�����w��n.�h�w�v�:G/�������a���^%�M���yi���U�w�����w��g�8y���	���K���D@�Y�v��T�D�2a���".r��F+o��N��K1m\����h���|b�OvE�H�AID\��m6b-��?�XS����p�o�<}�>��D��������Ms8�iC���������9E�_�����J\k�s�_��

^HYK1z9�S��L��>Zn��i�R���\�O:�J�1^�q2��M���oc�~Q/���v���Vh�K{�Omsze�D��4y>���bv������U5>�B8^T@��� -K�����������x�v��
>g����@!(�3)���9_M�����h��}\��vq�{�h�����?��.�6�e�@Xt���Q�5#�D0�mC@?����')�s��so�������������'�z�����?���������z�����:9��c7:h&�s|��`��i��y���0;�����'@?��O�H��E�x1j���!_�A�������8�A�b���T����o���t���{��rj�M���r��iL�qGZ�<p���Mf�*�#�,�@���
�Q-��2�ev:l��G���p>�h&�����7��O��h�7�����S��ns�C��[a�[��X7�_�z��������;���������wx��jg1O���'I}|�i�?(g]�]8|�?r�s�v{S����J����}1(�D�V:��^�"	DY������<M�5��x�LA���r�V:2�P���t��������,���0rN�w?P���Y�h�x��P���W���NQ����p�"�M(��}	�����I]����	���~��)�}��%2]x���jc.�8eW��4 ���!(�c0���S3��_M)����@
�T&D)����U��7��Gg{��%�K7��I����Q�	Z�UB�E��S�������M��lN���	*�e1�p���d�G���*���g=,#�Lq�8�*"��F�b)z�5	�W���G���Q[�*:�
�*ON.l��SZ��mO��1�@4�L
b�*o#�~Q��<ca���_/��R���Me��;t�!�C�)��<�F��<���o7?|�MZ�S����8H^[Lvq��1yI^O��xAOO�����g�n�S���5��2�k��%�BMp�P��lD{���c��)�yQ(��A$>M��V�����
�������<���re�M�yW�j@g�bPi���������y�;o@j���$�c0��>I�g�T+��9%CG���jba�����g7g��m�����Mw_���_�?���bw]s��n���`v��@n��W��P�wy��f�@<_�;)����#=�+�X�����5�U�#��|�AH�������!��y�G#���^BP��hk*��9t�%"����FB
8���'��A|��Xri��*V}?6�����2������\V��&t=cb����)���"3��Z�!��������������}��F3���$�H��
�t���ASj��
K���3��A2fT�{������~��W�I�Qg�ny�<�}�_���%�����~r�%`N��'��W���\��=�x-n��uR��� nD����f���u�����IY�Q$���J�&W)v;�zf�04P��g
[J���F����A�_nt&��_��:���T8Q9�M,�]k����x>����H����)�C�����i��>�S����}w�I��.,�G��1oo�o����e�>=�>�}���{{-���j�=���������R>1%��8��,�L����0'h�c�=�O�b����Ab1��7�w��_��v�OA��Y�o;���o�/�O���^�����}wp����>8�;xk�T}yv�W��@y��^�V:�|�������f�l������������c.�j��
wr����n%s�����PM,�R'��2�"��g�qh�/��������f�����#�+�������]8y��:{��n��}88��������I�6���N�x��+�w;G��xv�~�;���^��L��fo����������wg�G���-��x���O�	y2HD��l�n��'����
H)�������� 5MN���&.y��:�8X<�����N������BMGA��9�����Fwxtt�	R��{d�����g;o�_n����W1xp�}��v�l���}�z/x|�wzvt���e	��:~���~x`��y
r�����dz=����-:��������JB"Y�XzCKP��[Q���@����olr�9��3��es�6C�2TK>����Q�H����]��x
��8
3s�&�^=���z�}�����n����������Y3�p,��~��}���)������A��"���g�W-���Fs�R����E���}�����S�hm��t#U3�������6\��Y� ���e���1g���~�t�?��N��_�x����}b�`�`�����kF�}��eX<��L����6�����j#�@y�v���0dC�:�'{���v�PEG����cK7�����
j���^��n��;�ah��"��� Fo��������1����'�d�����	�9��#M��c �!��L�6��l�!�[a5���e��.�r�/�N�F��S�����1�SS7;���qLW���Qj���peWY�����>��`�7�'�K~�����y|-��l-
���&��I�����y���p�y�_����?=�}�v�����e~1��+w[9�9����1Zk�z]��C�i��|7U�~���_Lg(�7r���� W�+�>x �:����M�����p��-��c���g
�Z�,��.<�r&C�����m�;�a���<K��-��-H��i6
����4�hnZ��/�	��?��h�:ti����V�����+�o_�3��Y����J�@��l�9��Fh��H]��0��a-K5�?���>��P/.���V"}�q�F�$���>���[|�)����NL�@���:��o��	��(������*)�l����X�-��B���i���)�z9�����j�y{�X�-�e�Ula�����d��LUMUk�3o%����Y�
�r�f����tP���g�t��bS9��|���c��|>��G
V��Xl��Y}[�<Wc+�g�x����o���|��A��yO,� E��<����:�Ud
<6�������W�\�
�%=,9�
;`2�ji~x�]���9�Qb
�nS��!
{��.��\��X�����qk���L/��&�qEg#�����I�7�*�Hh��p'�1$�V�R�D^�����^�x�bv����\������/��"#��;��>�����eh?�	;���������6��������`��W���(�eK-s|�>���@�v��%��A*Z��0�T
��h��a��+���f`��$�@��_s�;�����t�|����9�|w�`�+~_b���>�O���*{$.7�:"��D���n���v���xa��S:�+�:��1.����S,���h3D�����p�4�Grb �#}U�"�j�����`{������>U��������r>^I(z���2uks.��q��|�)�8)���
wUy��9}���
���S^	,���T	�����8/�eO'�ErFrBH^��,��^����������@���/l��V�w&i����4��p�2�P�H]?���q0���!qB���[��Tu�U/�w�#;���lj��-r��6��t�w�tH�
9��H8B�I��A�E�d��!�+���L�j$i)���@�� ����G����;(���|�C����7����R4���n|L��k������FT���nu��wd��UN�+��x�=��bx6
��������P�/�rI@���]en�"
�961�t"�Ci���P�NYf���1�`y9%���c8p�����
'epg�A�#g/��$�+�rC�b��G�0{�F1�Y*���2������)gS��lPn�<X�9�!�^`6���G&�d� {�����SJ���1�U�������\�a�25������.���Z�0���qa�L�
�S��U�z�s�^�j�)=%�+�`���6.&)�6-��r����s ��{��3���:����Mr�qV�ve��"�`�,�,�{5"��F����������<K��PK	{@�7�b�7�")2�k�m�|!Gv�g���Xa��%/lf����j������i�+���dZD�F5��3�b�����_#7!��>[Om�)��+wO%qBE��"\����{J����X���>������Dp!����4�*L��{�����wc�����g����]��q�2�KZ��xq��g*���F��%0���oPL7^�����������0.��/���{G'�{'���^�2������0�������t�e:FT��nu�--By�
�`�!���2E��
����k;G�g��Y2V��;>�:��}�X������s�2�+�?qU{���3t�E�����f/U����$J��z���kG�Q�(2�f����Y6�"��"��������v�n�y�Len��Q&��C�o��t��B
+D���k�4'"F��1�!*�x�Q���]�a*7O�\���Y�2}pItH�/��@�
�Y�`�~0���/���a4�F��G��f��A����+�2��3l�.-��^�����E��A6�=9e~*���Nix��,�kT���"��������u���y�K���z������m������G��E���Zy��;>�}������	{�^�_�?�&cw��7�+�Vn��n��g��v���������h1�)����?��O	���W�dI~2��3U-)�����(��xH�A�:�����xBu9�����X�����0	k&t{ak��]�q>CK!+�a_������U`'�9=�$��h�D��Ee�6�*�~���:k�����vn�o���+	;������K�*P&
V�R1���Cg�l�	{@+.wY=_@�4���E��oY��{�to\aW����!�Bf�:��c;��+H^��v��XuGG)����2�<������ac�a�M`�U��c\q��O������nxr����J�t�)���F��LS��U_:x���x�p��@��k�v��;zn`�oIO�E[�����R��*�=�����G�&a���ZQ��W�d���H_���^
�*?J��P2�O�!��g��l*>��]j=�ys�)������$��H39}str�}�����+q������Q�0'�1���K��mO��L��6���y~�U�`cq�{��%��(�:�����c.�u t�#
���:���JK��.��f�-yr2++�Eng�T+`�h�p���n>�9�p��q��V����G:i�o#�����
.�%�d���
~���4��L��l�^��(�Q�����o<���8��%�q�����W����s*$V<mV��L	��t���Q`Lt��X�J\��A����\���'�0���j~�Nr6��1Q��Q$�p����QS���	U����+�7-;'��WtH�������-#17�w�#�v ��ql^��h�X�o��������g[b	��s6��/{��$9�����9.kE������e�K2J=U��eM��b�5F���A���T�m;��eI�wE�4j����|��+�����|�jW��s�}���m��9�g�
��m5�l�1]0��]
1��������b������S������R�T?(�����_��4�M��0F�gC���$�^X���?|�x5���#Wf�������8�����|��X^��\�������zPS�*� ���K����^��>���N&�u���j��i>(7�W��{�V����/���D�PMA[��V��&�� �{8�T����p�	�c}�W��15��`u�����RQ���k�P]�2{IE+�T@��q>:(z��fc�n����v�� ��C������v#3���gN�6*���R����o)h�YX�h�N��8�*�g��d��3�v�3���_�pZ#���3	��
(��2-�<z��<�Pw���Q��^�)�
��0�|�6�G��~5����,���SV���������s>�����]�Q��;������Z���B��q���|�MV�Mdam3�X����������I,�x[.�S:�t���s +Q�����s�'�F�ZJx�]���J���d���X���:��K.��
���Hv����w������1��;3M��a����-�I���O���&S��	����j��o�8������2�d��JLbZK�|���s"
���������0���^���zt���8�����
��IC�*�s�/i��9X�������D�(�c�XI�Q�n3�O��Y�e��.�I�p��,g���!�����	�F�������t�!r1�x	���;^�i������.����]fzW��
U�#��gm�l>v�����"R<R�`��������%��K�\�S�s(1�fW*��Lm��3��\�E�(P|Ye~���KHW���s����pY{���\NL���wS�M�O�>w�u�h��mA9!��BY�>!7)&��!�L���U���W�����K�9�|:�ax���r!:+/�G�������x�t��q��T����9g
�(0�@��9�ds�z�Z�x�������Z����Q�tt�R7�|�:X��>�]������W����W��X�����>���n�mD�X d�J��i7ar/
`�v�������i{INk�����_]��F'�<�CEjl	�c�?����������������5����<��Y�����5/�R�}T����!��we�N����	�W���'�J����o����c*�G��~�H[�G^���w���}�����v�{>`�/Rm!=���X~L�w3w��j�}p���0�k \!�o�Tz��+�1�`��s��R��dI��g>�[�x������Q����|xtNhj��)��4+��1������$8�L���=P�tDV���k���K"OQ{��V����D� 
Vn�g���7����@+s���^�������j�B���j�t�
�Wj�=�M*N���Y������f� 	[�{��sx�~3"�.�vk����jt�dk_�ro�����Hf
�������P������
N3������K�2~�5	���>�gD��z[0JI�
�npK��iH�/V��h������ e�#kU�������|�����g����F���+pe`���K����Z�C�*6/^�Ew�!��j8E��!�p����8���*���
�����_t�/�]�"�\
�P4:�@[�����0�8�2[���@S��;��'�ZFXPB�j�D��~;�&���Ro)m;C��kdY����U����M��q����~������bB�Uh�|�G3C�58,����y��H���s��vx�?>g�	������$��t�O[�������������C�D[���"|���@�C��$��/�_,�����A����B&�Tq�
��Un��{z&��kJ��{���!c7����O����o2	)8HJ�����Nd���^�5�3�;bn%�������1������36����q��Z%���V�	>WP�T�E[���F��I���)����k`���A�p�H@�o����	��'�'J��R[����I�v9������{��G��w�h%� ��@Q����&T�����������go��sxt��?D�����x�����g{&�^����i�"V:���s]��M7M�������6�#.]�4�br�+#5I2z�n*	%��t�%���^����#�@Rav9��a4�3��������/(���Y��tt����z&|8�oF
���[��Y���ki�,xU������S���#����b�|6��(a����ob���~���"
�!�?��h�������Y�Rr� 7����5��{�P����R�<�f��b�P	������U��^&%\!h�s����j!4�H�`g���?�������n�����TK��x�I|P��#*�{Lut�?v@����~O���Ir������c�����c���yK<d�Lw�y�f2��u�)R9��1np��u�_w�p���0�l��V����,n��&�WR�4�2��
Q�lR^�\(�i6��9�1�m��f���]yPx�d��H�SD�>�_�9��?$%���C��}���8Sr��R�	+�0�wQL���	��M�2	�0�K�xd��q��jm�� ���#���uo2)&z2��;�dN\&������y������V��2|��}����O'�������c�_�
�0�`��8|��'���'q��D�m�&E��n�)�N�_��M�����wJ����J��t��N'
$��M������5���B>��2B��gc��:W�[P�%��:��9�K��5~�i���E?F���< V�]C�A�D�c���q�g�0<���?iG�����\��L�����4r[����5��*��fr�L�md��'�O�C�����(��	�H�2&jZ��q������N����g� �*&��b��=��V"�u�Zw�nZ1��A����'N�R�ei2�W%L���R���������R����|���$+)�}��'g������:��C@�[��T!��������):?���p���w��l�S���I�	]&����v��B�_q�T������������C������a7>�*��E�$��]
�z���E�JW6����c���G&����1��91-��������MN�*'�@�����R����E3��S���
��Zs��bi�"(�n'FQ���j*�T������R�k��G��wr
��{����\������5WS=���R�B�FQM����`�)�;-1�����J�����|%��$������m�����-y���t������G^]����E������A�Ie����.����e������X����
�{�S�~gTJ��|�2��4���P���o�����l�Mg�kB�\�=�q���;u�1C��A~@�$V>C��O�3N/�V��5z]d������MT�<��{@9�kR�������~6�F0R,%�HL�F�`�/vl{���a8]���,��K-�z��|��V���
��g���^��#:I
�� /�;����8��G�����~�n�^:�T����e~K7YN�[
��%z��<(�����|��,&����#�����]��>lP�g�(���O@���F���v�j���w��I0~��9�;>��J5��ppzX�a���),��.	�����~0�o<��@w�]���X���fzT4�eGp��l�E|+�jR���1V4C�,!+�m������sf�X�Je�
A���-u{�,��]ix�m�}pp�s�w���{������v��t�?����m_����lCW�sq���O���Y���zB�q�������l�7���=�����wQ���{!e;��T��3@FAt�6���T���
���� 
�O���� ��bHD�SQ������{��g�{���_��/�;�F��/�$����=i��1�x�s5
Wrr�B���K������~W�G)p	��E���o���&L����N�j�>�`B������_;�`IF\�o���D���kO]��:����?��c�����i	��:a�@�|M�	�C���b��T^�Z��?A��~z����|��6�w'|["����$��
1H<��M��n����\��7.3M02�F�[��<���(�6�kJ�@�`��������puO3��6��3)�J���z��G�����tD��_`����8��|�j�\��"���.7�����������W�z�6b�PxQ�"0nX1�?P������
���+�O�w�1��C�������L������"�ZP�rD����^+������"���n���x]�X���n$A��Tv9
���7��
����8^jQ���^�������������6��D�
��	N.C�BM�_�h7�/�������L\����@����5�eC)�����E�����z�\��o
��j�
G�w���o�4�C�������s�]X�-yN�+
�x���h�.��
���~�9I���;K�;�<�
�-p��f����l|z�T�[����1��	��\���'UO�3y�+���	��>�Q�����o���p��y��1X�`��,79��6�&/��e����((�rc$(�����gZ������N,9�LH����:�1R��AN^	��s(����L�K��VxLqL�����O=$�~<]��7PWQw�R�F����=(��4�t������z��4g�������R�4E����2z�We��V�%�4'L?����ph��8��(�P��d6�@<�� ����n%KzJo�(�e��n�����,�|"Z����
�J1q��0-�eA���'�p��IjF	K'x��t�{����v+�v���_2����jR��R	�g4-�{���������d�k��t��(��<.�8��D�B\SL
��-������A������\v�j��e���������1;�S��%���|t=���(��������X�
7�yh4>�$y����Vu�_�wx�Sk+z��)V����R�k�0��s�s]�����\5U0OBW#����B�R��u���?g]���5K����������v�����������Mq��x^�>,/,�@|�����o{_�@��s`������
C�_u��OgcLs�����g.j:ek�(��W����$�|����?�g�X��h�`���8_�X����E��+���K��2,=���'t�11��j�G���)h��#���gu���.LQr��B�U,�Le� +B�k�{�����	�^%@��n�����!��V��-����t6��l�F����5�_w^�;�Ar�l��>E���;��.qMVz�?)����#�K�"��fV��R7�����,�x����d%��Ek_##U/��������KV�'g<Na���QdU
S�$�"2�:���}��%u���d�_���LA���T!�e�;;�����C����	o����/��^�&�|��l:�F�K�i3R",��.h�6���5�37���O�����g��� �T�J����������g}c�����VZ�IGX�[��F�s,�����/a�n�^����.�2��.<D7�V�B����#w�����[��SK��az�%�:E(�:%}��m�@�����DL�E��;gP�`h���f=�-�X"�W�D:��C�ah��"-��bN�z��[����|$�q2��8S)�b�H�tM�)qY���8ic���j���
��J�x��f�����s�����v�Y��1��s� X|B���c��a>H	���2���T)�"'Dog�0;�e��M���U�!���	�&��6���Uv(����5|;n�X�d,���c��u�����3��4�8,l�q��`���GT���=�0�-b�=�����l�0
~�S��HR����_����l�2��9�O��9�4o$����W����u�1y��Q�>����G������R�Q���tz����������h�;qJ2�Y�����B/
>0(��<1�J�Y�mU\�k�0����Um�P�����q6��[G������?'�&p���?�>�s�9UG����H�?�����#P,drQ�8��������#��mc02�~�eA�V��z��j.���^����2h<���:C��]�
��H��y���;��q�f��.�Tu(.��2�%�����;��o�����-W~������M:��igo�����Y���s�~��Y����D�XW}� �J���eOxhfy���c?v�W��_'���	_
���HCp�������@��#�/_(����Z�
ls��[~H���x[�[�Fk�4�%���{����)���"���ew�%hrg����:o/�r����
��E�.L�l�;��+
64c��/�w
	��RN6�������3Q��GP�&��&%���Sf�t"`�A�[�;�b�(�
���A��~��\�h�����W�;���;�'�?�����E
��!B�#��$�E�V,M�E���A�B,�������
��;�u��0 F���2�?f��`�b���g�2�aV��D,��R���ea�5���d��6���^���J!,�d����$L���r��2x�!���``��=���6<�F�v��g��&�w$������~�A�qN��0��u�=r$9�S�q%dH[V�{�����/KdlV?.
q	���6y��&
O�� � ��.���3��P�'�&I|�����+����}��p
�j����������}����*��Fh��+����Bw�]s�p� 58�Z�D���e~k�%�#��&:�-��t���z��} Erzs,��(�1���<9� ���ghp��+t�����{\���z��\������y���S���	0�3�;���Ne5@����,7=|��@��X/���K�JdI�"��G�)"�Q�=��`�������A=w���M3�D2�2��_�$~@��!������n�B
� �����c34��?c�a.lY�CG���y���?�e�'��j��U(����L� ����h<R7�������`���e�d*��pe�/�8m������f�z��v0l��ej����mi8IH��E��+|v�w(2�1g�Ys��)_��U��Vg �������|����p�:�:�;�="b���R��7Q'8����Hg����BV�n�]%z���I?�d��"�FJ;�����Q�(��n`lZ��5v<A�XB1:�>��F#Te�������B������*dB-������6'�v4�u6��[��kB��v�N��L����9���^���"F��^��gw���]�����4�����f!LL|%��`0O�Q*t��p-y��H[��U�0������'K��K�-�TQ���1��#1���5&[�G���U��i���
�8�g��7LA�$��S�ohl�oL};�g;o���A�|�wA�	���~O�:goN��7����r__l���La?��c���-k�_1�EE�����_�6a��k�1Xs�t�d�]Z^����w'�����wo|8Tt]���L0?7K�������--sq���\��\���������A���+�	�2N�z���
�^L}��N�������7���.�9�9&�����������
2qj� �u��3X������N�}��R*y|��X�X�R!��fS����$$��I#x��Q���\��?�V���Y�a��[I��r����
�V���uf��y~f0��,f�^v��3�u��4H����Q��[��t}f�|����lr��tx�)�����e3=���[r(X	jt�\�Y��VZ5U7��ArM����s+�vl���=8pk#����������
�8���=�@ ��D���,�CSLH�q6���7^`��U���W��������[X�	G��9m�j����2�3�����^�g1�9�q����=�������T�}8�Q���{��o��a���`R��>�RE,swY��?���RL�eL�''���u���\��a���I�pw�m#5���A���T&[�}�H%m�e��S��j����Y���"�&��y�8��(MVRs g���@�
>9G����1M#{E+v��C7)����A������L�g�%�3:f����*�iy����","��_������-/��g�`�-�M{?��pv���Z(�m�a�Z4l��V�d�����s"����#�#um��Kr'y�g�u����-GB���Rr���4��{�_VX@��~�<yz�p�E�0�!a"06�j���E<��=�y������?��g� 0�7�,/�����Cj%�C�� ��L4l�LX&����LjC�8�E������3�CX-UB>��t�^n�=."�:��P��s'�W�_����|��#�^�
(\�c���1M���0c��d�����V��_`��WBM��E���z�� B)^���f���5m�E��T�0�[���
3n��gm���iW�Z���BRa���B?�p�>��M=�6�j�������w�Yr������3��[n�V���	����/R|�j�_�"r�[x^*q���n]LQ�\g��>���%�)��Fq�l�EB�
���������IR9��M���r�
wa��q��m�)�i�����9*l�
�x��T�������)�^��7��$�q(���
%z-��8�!u�����g�Y�w���b@�f`���r��O��H{������OvF��u�E���ge]�t�+mU��l������O�*Y>�����`��;��y�������x^z&���4� �\=p��i������I�
�;d�g�/�������:&Qi���M��O��t�X�BI���L������!��9�`\�u�d�������4��B��X������a>��N���F�������_�c�
la��x�V)?�l[�M#4MZ
���[����Z�O���7H^nR�g�S���l�n�P8���P�`�B�X!��)�o#p�|��&T�)k87*`�y���iId=��?w^���n<1cM���!X%X�h��f�l�3��l��6�U��g����6��!.0U
���^'�\�������������n����o�gWL�\�.IKe�o,�:�����<�������sr�����K��)�N���e��	7t��}�$���#s�N���N�]�����^ �!��>�t��S��|3.�F�o6���L��t����{Pr�D��1m"9�X�q�!oRI�,�!��2�p��c��|���Z�-yIXqnr`�IO�#}��/F\}m�sp�n7��$b�p�����N���k�������&G$I�U��Yd�I��$O�������[�tu���Bw�3��b�KJ!�&����E���u���,A�')�6Y����.D>�:g��A>��O�N�"���aS�$g�Z��vrD����&)I��x�X)��K�::�/e�(Nz����\�7R��0KG��s%H<�\�q��I:��hJ����Z�������l�;��_��rO�K2>��������*A��Pt�����v�v���#Z�|t�q!^������U��� �"c �V�0�lC^����H��������."�\�����O&<$�u�D.\I���G<�,9���F���kCN
���&�L�D�"��o�C8�1�����[�i���
uN��h��qNvu0i*-dF�6����3]c�;u������z�B�6Q��Ss�[���G�E8y���=B�"1��fO99 -��4{cr�!����� ����$�g^����a�lz*�;�]P��Q(�K���zi���/}eC���&��Wf���3�����C�L����\�tX�fq��.��nH��t2���0^*-xJ��{��=v�Zx����	��lW�i��m���8���MS6�K���H�_%S���f����.E�U2���N�{F�[}7IL�G�<��Mf���W�z����v 8����/o'�����@$f�A��f����������H��>�L�Ai!uV������<���������&X=��T�������	N�:3�U,8Xk��{�,Ia��0%��$�+!��=�%�pie+A�������vpiv���KT1X�B���R�>�,C�����m�;��>����;�;�c�9(�kT�c����0@�xl����7}���9J�i�x�IzDl�yT����l����<�
���&��%.z���Y���Doh�Y�� ��f�����t��g
�rR�H�����8�[�v�+RrJ�~���y<�GK���h��bF�LG�d7�%�O�����$p�wt��w�y���+�������{�/u�}���j-n�[�DC��%"�����e>�s�����ngw��g���v�w�f��������C24ITW��@'c �\%�h*y�Va������=T�qo*H=�������L�����k�?;C��8�(y��<� �k'�a��"�J�p�(��	u"�l�I��27�o��z�
�e��h^��mg4�e>l���'`e�e8�ZO���_���/�����i�+b��05�w����B��
�I��b�t?g��8�$��Rg%������
8��$$���q����0���[�@n�4>�u�������u�g'��� �>^'b��$�)�#Q��/��>��<��P�����/�N�R;
��$���YacH�5�x�����qG����i��]1\
�p��2��V}���=0�7��B��'T3�����
������b���
�W�=*���'��h��"�3Z?`�0I
�cm�g��'	w��$&��
��S:���c^��2YA�'�}�d��N,efxcS�Pf����]����wW��� �)�C�t�C��ni\�����8(�y����*a��rq�����7K.����@i� c�z��SHd�;���L��V]S�KA�������}9����<y���]��1���a��-'����*���Q�n�/����0��:��K������x��{u����]��tF��Ps���$
���������q���I������6K�0��rt�������^FqlaXr5����������%k5�x����U����������e�|������]�^��W M��	HB!���^�D��`@�����%�v������Q^^�S6W5����}�z3\���]��dFE^��w�&YJ��/���9�Tg�^X��!�v�;��T�t�F<���W��C�5`�d�
z7�m�X0��$/�!�����D+VfX��A��f����W������ ������>������I~����u_!kzJzy�Fw����
p���G����Q����	�$HF�V��2{����m����:a�4hfJO:�Gd��`����p���MB�"r:�v����������E�n>���������NG����;���{�Fo�p!��sl�j�A����>��N-���[�P�)�eU��p����'�����rH�1?�r[�\������>}�sv����No��� SF�1�������n&K<1�k~s2�&�����]2�r��~�m���-����m6�.��o����������e
}u�e�&����h��y�n>@����7���Q�_&�ZL�T-.<�M?�����9��
�H��z\X�����-���m���]����v���DS�-Y���5fg�=��#��E����hp�p�9t�����S����9�na4��]!��,�r:�_�o
���b�f3������_[O1�����h������p+��vj����������v����%�\���OT��6!��}���=i�A�E����"�����
5+�t�k�G���%R-+v�1jj��T�02��=��w:�����8ef�R]�.��];����7��gA���L��|�fkFKV��d-^g�0���Au����@3����^d����s�X�&�tk���_�lc����V�pk� L�"7��0h�J��f�
�c�|w�a�.�{���tv��E������n�eo���#8�����U�(=�jZ�c4�}�Q<���8��X����+#�u1e����(66�&@�@'r�o`�e�����T�.>��l����W]��4�:�$ln:8-��M�<���L��%��o�Js�:: �Qw���v����t�b��Iqi��c�S������������������
?&5��%x��49�3X<��A�p�x�y�?o�>}������yw����.����6���l?d����������?�����g
�!��3��X�{�jeJ������M9�F�CK0~n�*��1F�e�A���s�/��uW���b��,��B�#�^��X2��8,i�&�5e�/�`w4��Y�!-e[x�lsV��n��95�X�t���������Nc76��z������#�	��p���E�0�W����a�9�t�ZE�:�����������q���A���_:b���ok4\�n�E�J�w�.�r��9�%\��H�����1�y���E��7�9w����k�K4(!��M���:���)����%'�8�G�\�(9��\uI������Q��hp��-?��w�{��Sd�B��?|�=�r��������P���F��!q������T2�]��/������S�H�g�^$}���Q-��P���SS����|Y��R����-c��f,B;��k�\n�h%sg�dss����P�e�L��I2��?ej�j9�n���C������DazC��T��
��Y���
�}��n��y�0������C����~j����0��Yb�H�$�1�][�e�D�Se�0W51���ZQ��Ni/�j�������1�'�3�A���b6�3w`Bo�����	S5O��� �������=1�u��0�,&���
y�L������+��D�X:��t�<q�l��-�,,"�q1�XC�\+ ���l���]�"�?�&��tA��|c�S�k]������~Eg!M��1��`1��v�O�=�����"�qDj�p�)���tGb�C�"��!#�3�'��b>�Y���o���s�)o�UJ��2��|�:��v�m<�0Z��m��dqW�S�.�db,��q�����k
�:Eg��L��HnP24q79�K����r�2���$>o�g��������A���Y����:�o�E���]6A�=�k��D
��hD3!�cFpZ&��$o��N\�`!l�4��U��ki��M0y�Y!������xl$%��xu�����q�a��� :">fr�U������j���Y!���8&�5>�x���#�s)��B�<g\����J��*+��z��X�r����|����jM��1�f���L`������+��&�z66Hs�9���t���\�K�Y�xp"o�j}Z��L.�SKGu4��e��H_��'��!S���A�`%���N�'�����Wc6qfB�����]������2�&k�?8Z';A4;.o����!2��L�<�X�j��e�o�"+-�P���6���@vV�q�������]�+�}���I����`Y~!h�cR��vox��N�qT\����.f��U�������
.��=�����B�e'���������au���!6���q%�Z��~�g�s�X-I�a�����-%G����������~Z���0�>�M5;��`I�H�5�#\��=����g��U�0h	����|����;d�?8�����$��p���V���h@a	i��#W�{2T���L�����Q8��H�j �!7�l��#|N/�5)U�``�
�&���g=R���v�F������:�X���c��J�I(/�#�<E�*;�y6��3�b�	��z5;���D���_�����|-{�n�+���{4���>d���|�XS��r�H�T�.�Ga�6*;]z��sPNe���D��~�e���#�*r1��TyJ��I�%�����[����`y�^��1x%���N��pq�>��l�^���lB�6���ED*?�R"X>���Ph��tfG�^s��qs.�����}��J6�|�@���D�0�j�Kd$����Cd?�4�+�yIN�#���������jLz��<�Vr��.�#���#3J
���u����
af[N�E��N�����[�����.��]p�����=�FM=��^9/���W��Z`
���c�rb)��*b�X���"L������2X����t[j�8b� ��i�#����P���RG�����iv���(�u��1��R;}���a�b��=�����8���8~�����t�%3���S(/p�h��x&���{#b'i���%�,���N.b<6��Z�^�m�XO%T�����O���gX
�f��������0�����W��Ua��z�U�y�M��j����B���[Z�;���PL4��D����d*����Z4�
�1���3�#�r�4S�?�!��H�Z���"jw''k3�z����%�f�	��L��?��U�u��V�	��R����>���4^f�dZ����9{��%�����>������W���r:�1`"e?����b����2��d�J
������'��T1U���!��P��m����r�p|�����H�%���Q������M_�U-�Xf����[9XBnjm)��s�-�g6)��#�<����6�K6'��&����Q�9�=�, �&�vH�'x+8n\���1���_<����c��_���	 N���~�l	cm�����x���
pn�YA�3���H��+ ���>�%��,�:}�2����:�����4M��4��������{_�`D,����f�H��rp�i��-�.Uap����H�$��5��y`<8���T%wo��m��20����;����u�k-�����������
dk.���Ci
�H��dLYf>�M�P�+���Wf�F����_���{��j	y%J^H�2&���d������{��Y���W$��h|��������4�Ma����};�#Y����W���A�����3M�F�Dj@n���;�H4������X�B$���,����=������c��
?���fg|7�H�#��[�V�w���l6�hA����*!� ��.9v�m'SO�K�F'�!�����/T�n
��_�n8~}�}��/DUn��76��������������/��pcs��' 9�7�������� ����r�s���3�@�;���1�]���L��!U�i�7-$l+��"������F&H��r���W6��l��;<�;<c>8�p.^���s7��r{����&�����w����,�3��Jh��}�	�QB��X0@l�1j�)�Z`���+%_q�Y��M��y
uM����-��5��~&��=���1�}:�&)���W�x���p���S���YN
,���I�8-m4�K>���f���-I�h���lr��Ft��[�qc`�O5��h�5��N��
����])�m-���E��U����,���p,1
+���J���:�E7$��FX��u����{�L���x ��	0�O�:n"��x����[(�j�lh�}�����b`���2� ����F��.r#�R=b�	�!����H=���.���2�B���Q2���.-<���E4��K�!�U-c��L�����v��F+���F��"�����H�&���J���U(���]��a�).�i>��x�@��e��+��0�EX�AzRg�L2�8�lL?��o��G)w/$`4Uo�zu��T��T�p���^������cy���/gt���	!�Rj6t�C�v3M&I��i5�������3d�wf�wf�!��e��:�[����T���.m��_���r�����S�C�+`�G2���{�EK]��"�?G�O��O��-v�3e��5�U%I+��V7�:rWhN���T��wE�Q�Z�V@�K�!hy1�@��T�Z�A�?G�r�\�?X������^�x��*P��dV�Rd�vS)�&q�u>�����@>�?�JX�pF)+��K$|z����<CK�]�L>�c���~~~�A�K� �8�s��iO�8
���x�C�jV_a3=�,!��@�]�+�?�v ���{�3�B������Z�p�D4�_������0��$����2D��]�$�k�
�^&����$<jjqR|Jpb����Z�
������ThaiV��9��n0�p7EL��(�H�2S��`�
E�]��g����Y;��\T�?��-����� �-���"����i�u�D��TWj-��d��b.a�!VD8zLb�8�S�b�����i,�)W��N8$:G�hUU�(���4�S���s2V7'{��u���
��/v�B�n�&8����.J��'{o�~V R'�Q(�������FZ�s�!,�;����n�y�'�I������@$J��4�����F�Um���B>�J3�N�^�^��i���OA�(�azo�������+�k��A��2O��U�����!��J��F$a����_�P��_%~v�z��*W�"j\0�V��_\1�ES�,���!
V��X[�gZlt�
�w�m���{"�sj���-�������o��cd>��]�6�����)�o�"���$�|�KU.�.f��
�2<N�}��f�c����Cc:4�=C����C��T�^���t��a�k]3��N"p���04�c�a��L�pM�������N&���Lz��ae����F����c+���L��s����fR�/�T���%����p�AKGU3,/���8�m�_��H��k���<����X�B�E1_. (��l�BH_{����d���&s7�����*��reN\8�-�7W�$��yv�m�xR|�1����b�:��5�������S�|*�VHMW��d���#����b��;��nt��Y?��z���h�c�O������eL$�X�Y��!���&c���N)>���nY�klJ0f������0����� y��#
m\"���H��lx�����98����edS\�g�����,?�d����s�?M��4&gv�H����j�se�����d����b,��BY�D��lPP��J=YvcR�G����!�|�S:��x,� ��3]]^���E�q�/�|�j=��$��f"�~��|�Lr+h�K���_�c��EM39�	���� w.�2��62�X���D�i16����E"�R�8'�K�uc,��2I��Tk�,��s��qiWn�f�	�j�5�O�����4:3F7�U�,
YH1u9Z���<�+[w_����E��5�ap�'u��I�j����u.�!�FL�R�����m���h����0v���Y����$�'�r�j=;�@����)6)ah�u�y���.L�])76��}���!��g�70�w��X����Q�#���P��T`�$���
��W�������-�
���?: �y-X��~���I�&���[�I~l5�W�|���4��l���X*m��;/�6��8�m_�Y���:�������t��2����n	��A����\��5�_�X�V���\v�H��
�b;!.�F����G��.%!��u�������4e��k����F��`}q��w��g����P.������g�]�bW�|6��C�Ppyj|�V<=oe��Xa*��������?7h6�6u'�:��[DV��6(������<h�4+]�����,�t}������y\�z�(��JC�����0��u�T��+h��d@a 	�/J�B��_`�	���!��1\-h%M�Od�c)�d
�C�3���e��H2�e^MrLO�R2������Z�\��%�"}�G	�*�G54�~���w����+X�����w+S/���|������1"9��9������i�tn�������o
7��ev��>�t�u7n�}[
!'����g��X�����F��c��7�����0D�������kf��f����iI�l�B`l9��8o����)���K�?_:_�11<t��FLj��,jS�=�	���F��Kk���5���9-����=l���OAO�B����S�����Xa�*��A���0f8]
Zm����'���.�n��+IIk����C'����A�
Xl�SP��tI�����Y��w'r������E��2sL`�{7����4oe�*8b�U7	����������P�I!(��j��N�F�3*��d��V�v{��������wo����!�����(k�����_�
f{1�l������I>F���3����� ��x�]�hSG�w��&��l��
-m��%o�/&��md����P9�	��O��������Y�����(���\�.�?D�v���UuM^�-I������M� ��t��b�D'�����m����Xc��G������x����yn*d��52<c������������3]�&��n�T���l�����xn�b��N�OG���[���/>�D+y�Q����E����
[��&5^h���pp�����(������Uj��OK|Ol,�7�B�`l����VW�����U�
�%����b�������X|���#V�&������>��~��y&����\��q��Z�/f@�����f��N#b�
��T�@%��?����q��}�� (4��S���N�q�{X9��,���.���QT�����f�?IE2�j���fE�@�����6,tT	p�p������9�L�=T��3�U����m�!�X���$=��g�n:�����;ZOO�N�\���������c�^���})���Y������H���Y/��G�	������y�����Nv��s����e0p^��dm�`�.��){����RE��k����Kx��. F�2��&C �����v����p�d��z����L6���]4E����\F0�v`���%IF�H�	��ca%�i��6����LVI��~���,a,����*�,�
�b0�9��+��.��dkK�����%G�o��� ����.�A������,� ��p�J���l�������,�o�1����)�G���p�f�MC�p_)H�/�`tmM�l����^
�W	�,�����iZ�<�@�L����	o����1�O���nhi���5����by)�B:5Fz<���;;�g;oC7������do����N��$��}�v@�H���v--O�Na	�2��#w���>�s�r�&5{O��e��O���,UEz!�>�G��a�s��A�c~��9{sr���R�Hd�4�P"����B[��:�W;9$?
�TM��|��P�d�V��Uc_I02v���Q���T���nW'U���������.�4"�:�\ig~�$��lDI`*�v�^*B.��e�����h�����.�D�	�������E�l*���N��U���9z���5�p����M�~�
�����8L��E�pF��w�x/W;9�t����@S=%{�SN3ot����S&!e��D��J���4�7~�~8�����Z�:�P�Bj��%V�����|�0g��s-�P+]QT��E*�O$���P3��=:�d�H�a�o�$�9�d�G A�	
@.�C��������O����v/��B��.3J���nn�����H}6P�/�*	3�K�,V~-�1�a�)���n!��c*�y&\��� C���1�N�y��2��������}�;V�V�����	K��39��SB��on9�*I�Q#��[[�l+M��z��!sc��oF��KB.Hf'�G�0�/X�!��\�h"$YN'�����sJV[�/������r�>`�/a�7#����Ac\�n��(o���_8����9�G�>	����gDp���F��_��=�����S�sC���6����5�#(<��*�H������0�2��������['9t��G�Z��p{�Y���9/ys�O[�b��n	�|<�����������8n��}�~�Jb��o�RH�KVC��Y�>��M}b�2��%�+�4D�9w�6����&��
��oL�j:u������Y��	����\���	k �yQ
�(P���������d&wk����)+���-�1��ayQ��N/A����X{���M����6���i�������.	� A�i\g,6�����}���Yt�s��!��6�V���9+U��������>�>�F���j%f3W����1<�KzxS���vr�:�U�w4������/��5O*���9EmL���i�Q�������e��8E/���M���Z;(��F� k+�{���/�J�M'���R��\Y�z���7W(��D�C�G����u�8l��|�te.w���N���W�3����X�0%R�a30��[���y����t�z��0o5��N[�&e��	��R}��l�R5�O�Vreu�l��iQ����{f��y��h+V�:���Qs�O���$�s�n�eU����9e���������&	&^_�D�M=6�o�#'��I6N����e�D�4�gXz.�Yo�S�n^~������4���o(5���r���ou�o9'�X]�����rw�>���c,{�9r*��������N��Cr�a0��]��� ������B��<��4��T3�q4���|t�_U�6�r�� ;Qz�*��D���#H&{�s���U��o���/�N=�O��}�o	:�
/�A6��|��(��?�7��	N��*�QA
�p-/���L,��$��h}�ig`"��6l�C
���y$�N7�Z�p�q�_6��p���2\8x�'��[�O<P��g�����q���j+P�?b|�9f���&",d	:8����Q��;i���"������:���+��L�Y�dyM��9\uU/�F	��������-�t��;p��%��"���F��-�F^��`���06m��&�Ry=l�Z=J5�����`1�{��Y��:iQ�4��01.���DY������|������\*�j��c����V�����hf���ONz�r^�o��
���j�J��!���Au��zh�W��o�@k�h'�qQ�j�rW�q_��X�4#����-���nR�lG�N���W��os�$�6-�"��
���"`�H�5/n�Y.9�Ryd���9���@�hHT�[���:���4���s�">�����TN�?���� ������)8w

�V��5�_�/YE8���0G��FL}f�9���W��h�����������ld�pkz0u9�<�����S`+uTkyx�Db9(l�i!��{�!ZSW�����Y��4]�0/�'�\����Z��F��@��*���L�t�|+ �3����.�r<�XNz�����'��(����s���x�@�\�pI����wH��n���=;�<����L�����jMeB�4R����<,,(�����~)�6�K�<��

��n0h�����!�&t������>��L>b�L\�b�J%U��u���b&���q,7*�!����o0MN/l�:;'{�g���������?�����{������������?���v�O��"�,���j����`�Wp\��cL�%�Tp�#sJ9F3�B��jB���k^�J��:��/�:.��\�}�o���������OPC\���;�X�,g��}�t2���c�Ct��R��a�W�d��: �z�����xF ��b��gk*��;���~�\rX`����\_�����/s���D���4�w=\-���BZ���)���o�������v%K.���	���qp ��
'�_0�0u�e�����p���-xA��~��,�����;J�R���]���7����.�)��P�@TX��K���d`�n�)��
�)��6�y����r"��������z9���_	��$���d
NvEz�"��"��������,�r���p�B#|{��HFle2������B��3����r�6r<@�\La�z�P,��Eb%������
�75N��h#��������cbm	��zi�Q6������:���W��O�����k����f�������'"��W�X@[!iy�e�x�s���^arZe����2tY�a��1��\�����3�|�+�c*������L/��'��������0�E�1�q3W���iO�Z�h0��:�u�q-:1��=��y6��e�����8�����+N��0Ja�X
W�7Q�+�As��gb����5��=��*[#�/��k��*����b�f����%�M���b�P���N]�6�l�����rO	1�|]��d�|{�L��H����9��h&��6aG��V��K1�<_:M	1J��,I�������J���(���8?dl��%Q����?CYe
��b���l�-�\��M+G0=h�)a5#�L�F2E��Q���V����������Y���	c��liTs���/�
G�f�`��mC<
*��0�j�~�Vu�G��L����H2�(����\X�iN'���T[����
9��K���e/��n����J5����`�y+W�W[�Ie3����=E���bc�c|,u1;���=Wj[�U�^�cE*)��3� 2f��� ,%�A)�Q}��c7�dP�r��T�B+?#40d�A���M�����Om�;�!e?W��J�/�3���m�k�3L���L�������r�`��'tp�������H�&�{�<���F3�yI��+��L�%�n7�4\+��)���,1������|!�K����L�o5���c�C/��B���M��h���m�q34���i�,���1�iU����t���;�C��CHwt�R���#B�p�D7eF9@W`���$��b�>}����h����As-��[Iu2�O0BdF$��t���P�yy.
�}���v5g���4��9\~���5�r_+��T������5���g*��M��O�o%�Yv�����CK�h��7�&;������Ga_lJ���3����#�|��!��G���O��1��md�%����������tI�����n��m�}�)~����s8�?o�l��u�>�u�z��s|D�S��3dChf:i�����~��=���}�Zvp�t;���'�x��f�����5��������5����������D�������f���?�;��� o������o��_��~��
������Tp|�wz���~lJ; �I�]��$�������>�q�c�!5�I�#�)"�)m�q�P�����e�)����y�\�����.�>������-_AG�����*SK��4�f����F����J)s��#�6zXC���
�c�2bW@|Zn�����kh�3" �m&�3�
>!��~��l��������	��n�\i��8E-VL�T�0���dF�����5�
���GZ�/���feo
k�8�U@���'~�.<Do3b��K��������F�qV�j}55^��`���0����$��o�����jM6��#���Ad��5� �[����L���>����z�����hyxC�����f��/������'�4��b���V�r�$hy����?O�oq����l�a�4I��;�����<�����uR�M!,���
\w�p����n�+�yp1X������"���5c�3�;3�[��=4���-	�\v���{7�[,TMS�����a�F����s�"��<��<�3�|����,��T4���[����en�d"W_�;������>�!af"��cG��r���w��������!(���a ��_f�%�a���~A�@�m��##������QU�c6�>���)�cR���mY��rZ���J�����]u#�s
#6"?������1��>:	����|�Ei�\�w�����z9L��.���}����t�J����qr���`���y��m�bv�'�3����-��~�3E�pEd�*�.�E=����0�������n�\����K"]@w#8��/bd�BPQ����	�N��jX��f?�:�;F��%����A���
�������n��uU#��(�����}J~�3��m���;#������J�]�t�.?``�w�u�!]BHC�_�r^��j�8zm����k�>�I�
;w�8���&sP7�o���8"���[6D"�B�~���!��Y�=:/�5*�������7]kr�2O��.4B�/0�����a����H�z��_t�|A�j�/�V���#��;����v�V�O�d������aM��:�0����=�{c��M������w3��,��b�4�������6=��V�!����|���i������@�/l����|�*O����9d���XL��k�P����T|U�=w���C=��y��  ����x��f*8>��#�D�������+N�K&�ZC<qc��L+���j&�yk:��d����Y�mz�xj�w���sG�g�,CMv.�"�;A3:����O�5�y��k8�^1-#&�0���_B�[F�s�8o�h���Pxi�w�/j��e�!�eQ�Us=�l��V������Y������������J��U&&,J��������<� w�(�hZ\�N��1F����k�v��Z��Ih\	9�	��j��*�.RH��}�+�Gz���M1��d�^�3�(b��?F���Bu�<�I�!�p�|7��C�a��a'j%�����
���r��=��h��� �'����,���0�|D���2�d%���80R��5G�\�Z�g�X���NSo�Z�3�`5L�	��e����&^��m<|��O����������_[J3,�|&�H9����{M,��#���c�*�1�1Ca{v�a(��������Z�,�qJ�e�k�r8���(��\���9�3N���Y1��g�d<����e���b��	}�,�6�_����������WV���h���UlS_H�������=�c*��=��U�����g�6�j����Z0'V�o�@������!m���i���`�y�I/#��+�8�M��B��I�NU<���8�����Y�D7�^���=%om�=5x��d����)������y��1�rSz���������Uw���f)t�S��]y��U��Z����}'&�n���m��;M.�#l9����h���m*��S��U:�H�t��U�!�t���bDr����i|Z��|��_Z '�G����H��J`*����#�Rm�g����E�9��K�*4-���,�K:|G�JcE�Iq�
��<�.��95?�e����@�&��`��M������yP���uT�b�
Q�*T�Gx�y����[��%\��%ZH��L"i����D�U��=P�&yQ>3&����\���Q���v�����#���S]�-�E�]�a@�f��	�u����H��R0�����)wT�R;/���4g����8����~��'8*�����9��C�u�K,���=��%��j�f.=��W�O�b�HS��P��m)�%A���L���hp���k�B�O);�2�-5�v)V$R���
�WwF�
�|���(��������IlhX:���7�u�3T�K����j9b��]����A��U��uS�9'������0�J��t��	�PJ�_����bp�|8\S'��@Zz�&����_�����s'c�����J6�K��x��^��W�dE��0R\;�����b�����v��9���P���r	ke��qvr�t����GZ!��{x���~��-.f�|U>��������%��\��l�������S�������h�&n��X�hA�I���z�T2;?�{9�Y��T��i�o���fy��%y&kk��G��d�'s��u��zHE�y�U��������d!���N��r���E�����B���y����}�Jn�=�;�Yrg�I�K-�����|v��TP��Kh3�������kU}Z�{����/��3����C���-�l��Nw�XO��<��������N?�?U����o��(Gv��2zI�DM,��5��R�T��-�-�,��`�����K����>�f�����|cXET���pX�sbT�J���&�Z+!QS�>�\	����HC����"C�O#:Re>hR����bS��qt���=�	��`|�A�.��x�rX�X�z�PN�O�5^�'Y�Y�k�Fm���Dc���G�'��l W�8��mt�Z�`(���n�.�gg����P0^�U#���oU��.�m>[K"tvmd�����h�g��U�w.������SlEs�����U����]����A��'%K�-���A�)0][L��]��^f���^q`y�O���+<�k��j��)l��xZ��U�E�)8v��������-���e�
y�~����/tL����M���\eRf�2#��G���u�^�
6��HdU?g���T��1k_��_z��,�aZ���q���Y�������*�S,����[>�~J�)
��-������@����UFRY�7p:E�:������d��,����<���
SIM�w��V�����w|M���B�<����{���=yDOO�
T5P��L�kl0��A\�����mc�F��\P��>��K���P$ A����M�QChc�~�Lh*�;G��b��) .
i���d�R��WU�r� H�}t=`��5��5X����v�*����-�~����o���oBW[5�u������I8���?&]��-2��W�*��/"-����p+Z-rtmy�&WN2_e���	�|��)"��M��9n��Qq�9_/
�^�mJ r�e�5���)]"0c�y�	���;�p��n��� �w@�/���gZ������x�}h$���0�����5�X&n_$Wg6��cO)����D�|S���VK=�i��wh&[�O4��;��{����5���h;6x(f��z�;W����y.Nz��]������gN��U
��5�r�����'?�yT�5�q��'nVj$�,{��<�����������������������g�����j�_rh���zm��c�%4����+7#�C�gB�hu�^��0�jm���p�<l�:�Q���4>�������Y��#r��`���������<R�e�#�6��5(v�+u����oV�HLR-�2/lV#��"�8�j�:�%��87�]
��'Q��s�nO-�4���9�k�4�]������J�+y�����]��`IG�N����}P(���f;r�
�����?����s����\��4�_n��7�R��4��N�Km�0!O��fx��v��.<���VR�Ck�$�!yl�sC��C gT?@O���(cF"�+���������Qe�����51���: �_����������S~W�����XM��-��v@��~���]qFF���'U��}hBb�K���H0c
�
�"s��C����2M�v��f�W�Dl�H���,']��&[�8;�|��%n�jlk�MCy��%��n�5��_�9��&��e=��9����
��5�6��A��X��*rt�Nt���J/��]���%��!�d����@��)�f���>����pO(~���?�����wo��)�i���:.%,��u���H�F&{�3��"-g%Yh$��H*F$��d���\�����_cRD7&��UZ�Ib��o�;b���K��-r��Q��L��FPN�ju���.�����-e�_7��"�DL��Y�
"�1��Vp���+G��
�����<�9�d�p��E[]�fa�����WO���(���=�MmT�0L�Z
;g:=���pbu��jX���Z`������qG;�,'�M���bsb�7E���"���K���^R`[������}�dH3��<��k���������766��~�iC��<x�������������G�G�=}������R��o�op���')��h�D:�FH
��7@N	���>�R4�� 2Hg�+��k��x6�c}�7��><<:�;��;�3�($��}<�t#�$���:p�������4*���r�����s��6�0�|H�W�
�f�J�b)d���b��%Jy)@����[M�JR�?YHv�����������]d#B��{�-<��]AS��sS�=k#od��SX��5O�&�z��W
O]F6�D�����+�My�mF`ym+��x#��5A&��&�u�`t��\�&��^I[�(��_����5{ �S`��	�Ar��L�b���d�c�K
��qH���a{�w�Z��
�0�����]�%�S�x�4P��H�|$�8����`L���m�5��7:7�������3q0N���1Nu�@��x-�e����z;�1?�]:>��9��/��|��#�&=h�^p��;�4�Av��
��
i>�(�G�KN��J��1��U�="�%&�e��
�#s,�E�H�m;"�6�9J�3	��)��qb��V���9G)�F������9��80$OI�@���^cf"Ak� <�{zC��:�'G}}�E�9�K�)i��-�f�+����;ywhd<�Q5��r��YZ(M3.YL��r����p��8r/�	E6N��.A�K+*�D�v���S�*�YJ������@Dd��S����&�P��Oc��91�����,�a>H'���F��e�1���I���~���1GL r��
i�`s��Ahf��#�sj8uRf_i������	�>�2�p�;7�4aXi��S�����a_)�"w�]4�r���"���T	��Q�:kr�`qm�I#�z��R:�&��#>iL�5*��������5��)�z
���8G�+�ji0���0��'�J,�9x��)��$�*�^"���T
,K=��l6	�@�\�5�J��=���r�T�[����Up���b�y������J[�������$*��2�iA@<2Y�1H*T��>j�=`��j�W�������p�����v�^c������-9�7H�6�CF	�W�!;L���`k��)3�D�_���a�g�2����=���<Gh�!h�E�H��r��G5B���(
z��m��c�7����l���X�e��@��6���|�O��������s
; �p�v��L?|�x���Vr\�S����q��]�.�<(�D���"���������W�;�.'���5��B�����y�D��?����~�����g��-��g#������0/{i�_��m��M�HN���������y�0��3P���������H};�/�����M�@�	����2���C#��=^��g���dj�Hk���Sv�d���3J�$�������Au�����G�|�y^�.�S4�G�.55����<!6J0,�������H�}1�l4��Sb�T��X!��������8���z�#��>xO��C��+����T���6E��n�@��������).�ld��hod!r���W?� vQ�
L����s��7J)y��?�����Z�5w����IR)*�?� \�:"Yf���`��� ?G�v�7�X����v��!p��\�6��"P�������r���#:FYHy;(G:a��)8�KYU��(I~����Ye#�����N��[��9�oE�"k|$(����XJ�Uk�T|O�2�|�L��3:S�A�?r����Hj		�xIHX��
X�@uS9��H����:���R��?����.���D�������Hw�	�f��D�}���k�\�f�:+�ZE�"haL~����9���{9Z�A������Ue��#�'�2G���������E���w�F����aD�Q}�������3�M�/�MbN�6v��]�J�fNX+����.27��0����O�6��&�H��j����9*s /��du�r�����L�u����23�z��!��y�C��V��WR�S
_��
��[�_ �aO|������o�����N!s�&���1�J�/F�W6�]������L|��:�qvS]3IaGZF�C��F�>�-zG$OF[,<[��?$K��elX�������g��3����n�N���x�Z��.\�)9j��a��Q��<� B��44-�;,����� �%0�0��������;9��=�"7`�h3�p�<Z�m�,M�������,���G�N
���|�bq���q(������N��>>�����R�����P8�EQ����
^�dmj�&���i��!���������ta����A��OX9W&�d���b���9���S�F������a9+�����\ade�)���������4�	���Y��	c1����-'��T�~x�-��3���+�L���)I������'b��/2���x�}��Y���1��j��|�J$[X���=��#l��B����u�����h����G�rG{!�~.q����j�r���7��}5����D�8#+�$T��=��al�����|�n?
_�/O�����}�r����3<F������5�Z�#��~d����5���+p��*������L<������Q�$;��v��{�:��0��a�;w&>��UE����^f�DaWoU�[�t���UKA�@�Ya$ �:���O��"�/}tL�%�":�T��j��~��S�_	��D8��?�wt�^r�
�
����UeVU�Lg���t89��sL�����#1��Z<���h�6�l��/��GD�����#LKr�Me;\�c��To�n����r����@�G;����j���Y���!���m����������*����C� ��Eo�-7^���<�
�/���"c��6v�>��BS���0n��Mb<�
a�T=����u��lR�C%�!��D+�;c6���D��<f=z�=�;�����
4%jK�u-M�+8����Q����J�N��4���F�l��y��(G�Z��F���_���z�{�����"w�6����!�2���������	��:�%����0�Ap���e?U��.���^��W9����g6���Pa��&c-x�����^U�1�tYLu�F�l4��e�FT�H���������K�r�f�-#�uK�!t�
v#&(��o}��\��j����P�S��||��
v�����(�����f6����B�q�{;L�Y�yNi<@�P����d�Q� ?@"������A�����X�	
�9�]��H�����L���U+�h�j�m'��2l7)�����l��R{4��T�uIv_]�|�a��P)�����P�"/��o�"��z���9�k�1�rbZ%��Q��������{�F����� �8>����w�1/�?�K���U�0���b�T��-f`d�rM%E�#OH�&s�����3q�[��*?C�1|�Dw��o���C&9�����x]����;w	,�����fd+����]�=���h������kP#�������tOB4���9���J�UP���J�_���7��-���������C���P�[5|;~����K��vU���J�9�^�a�:+!u�(��6�
�(�G�fu	]Ba�����E����N��{��k����7"\
kM���������}A#����R�%��,]?�|�����6�W�B������/\=��������3%���~k������5���+�������kZ���
��}3�D+2�'��U�?��6B�N��3��{�i)�����c�g�Q�&��W��;O�E�u=
<%�2�}v1"��|4d	��P�K��c�o�>���M�%�T�g��S�M��vW$�J
oQ&ENh�i���0��������8:��H�������E=q��������c��J����F����RJ����+���1���xu��y���#[3t���E������������-�``�n�Jfv���:q����>���L���!��%1�����u�Iq�cF�S{�>�����	��%/�d�rd�������=������J(�%5��]���_E�Hq#�dUu}��U�a��u�YH��q.��,02��oJ���na�Q��w��)�"C�#r9��h1��U�n.1��Wx����`��.�0()���J<`^Y������
G��y�^�[A����b��J�Y��\�k�%���9��8JX�����M������f�V��k
�JoZ� n��?7���n�,��@��I�����
��$����lE6O���
|��
����]�<UN���/� y���Qi>�;�j�}X��-����	5����fbr� ��.|�d�X���$�8�
K�?E&�c�F�x^��UMl�6�82�+��UCHP)qb/]h���"�P�>�;K�N�O�w4�<Q!�J����2;T��q~$�d�i��[�tN�j8�|q���}.����[��RE��l5E�#�fs�cL,�IMtR��d�$Ya�?��Kp*F����Sr
>��BHq�h���W�-.�&���"�B�:Z��5"�3 �t.�k����?V4�����*�R���s	�7���q��:lPU�6[
p��22����	������[�8n�GtU�-����bbq�o�<��V�GxK��Kr6�Q��;�g��m��>�@�����/	z��&�4�0`w��KgG�y�X��N�������~M��&�YK��|h�`aT����&H��[��"������T����;���	�a�Y��r�<����=��8�����������������m��n�nI3�;�%r��k����
�{�{D�1`�KT"�9�	��
��pUa�t8�=��2j����a�a�y9�TG/wh�KcC�+[�zk5O��sx����sg���_c4��V�ba�"b��n���K�6��K�e-4����c3���2�G���������(��M�U�����.����Y�p���'�����{�#_S�>b��}���/��[C��������?9�F��>�X��W�������Jg���M��-��E�8�u�����!����x���a���
��8��c
�Uu�&���Hx�2P�E8_��
b���+��8�/4sz�7����d����#���F����Y�Ezf���Nw=�f��!�s��N�+��^e�F~���)1|x�'E�H��t�e�V���tN-R�R�*���<	�+�~C#�@?8z��fP��O���()����;32.��$��K���"���<�I����:�y���<Y)�K;��d�2��%��?�d����R\b|rv2�J�X���T9t�m�3�S�'Kh�m�U���1���$�����%���%^��F�<����1)�~�����IZ�\�4pv�4���^�&m�^�x�P�������\�gk�H�R�9���QH���'yZ��jH��Z��N	*e���G�9��tL(�n�U5Wb��	��or��*��:�������J���1�P�Q
!��
�\�����JHV|p1�+v�T��[N��)/���(F��uha?��~���Q�c���7��
��U�������a�q)/-����hK�����K�f��v���~�$��)K�J���X�+�.!�F4pO�$s.
#�ZX���k�����~	W�Op����5����3�����kr��:y��/��2~����0�l$����+�����)1��t-�n$��"��b�)&*>�@�Q��g�!�jCFj��~3�fy%>F�UE^�+�����x����!���G�
������b�l*4�&����e��0J��cQ�^��-X�WC� �����q��DAA��bb;h����_1��5���h�v��K�h+OGr������'<�,���p8�V�#<,~������GHq��"^����-'��Q������
�8���|w�54c!����}XP������5M�����T������on5������cm�~����/Pz��YS��)����p�G�c�@	_��c��O�U��F��������tZ�{��=�������m��]�/������FO��N
DHL'����|���n;%B@�3�8v�<H��C���B�����&n����k''1�6L2(@���i�Q6���X�'K,���O�{'�oMj����M,L"IY('\���W^eeR�%A���~���G���@,�A2s�x�O\z��
f���S'���5�K��/��h���� �/��c��7�M�P`�c�
��}+N�4�D�����V���nU�(Y3�������n�@����U�;uD������~,fU�K���OB-�����!��CHXR��^�|��R:�������i��iFA�C��X��x��vDt��Fu��a����A��%�"M����4��`1��Cv�j�u��7_k�u���Of
\��c��N������}x�L	�f8!
�HB#��c���z$ �a����V`q4v+p(�%����8�����	�V�v����e�eJRH�\.���z�W��A��P���E2MOK6({����������Z���wK����T?�T��N�_������l������bT��s�*����v�
�������{a�L�����������~f�#�_0(�9+�F�]R`�?���~�����;i����v��e\lU��XUCs<]����Qw>l������V��I���{�����VZ�C�O`�K�JE�U?���'�W�������$�Yv?�;�� 	,��G�9����������o�����E���Q���A'g<�x�d����'��9V���g;��RY>%c}!3�n-��!�V�6d;d�u���N�9�sk��o^��o��F�?�m6��Z������
�Jld&�sg�H�����#��U��vq#[\��Z�x��� �������"��T���-_�_j������%\�����o�y�5ZY�T�#�3�v
��]5���K\�b0��Jj�j�8-V8K(.6����h���i������&K!�0��8(�:�W���bMI�r6��"��	7qSR��m����)JV�k-��?"�C��	\��g(����X���XT�+��I+����9r���Nv��P�cfx6 (�U�T������,��Y�"���EO6���S���]�_�M��6��.��%���>�1b�;p���$��P��F"�8��}�
V��#���!Hq�n�E�<����������p�"����+-?���A"�����c�JS���B�|l��� ��f�7�g��G�F�M]U<it�5�42�D��x����'Wdd1�S:������������
V�u���}�.�%�ww4����E��5���������>D����+�?qe�g	�li/pa0�S��V��Q��t������'��*�Q�1��l%T��
�e�m�����9Rf� ��a��%�9��S����v�O���[���-2/\%)��C�K�1�����e����������& U��>���������o��'������)�����/�_�z��i�D��/:r����6��Y���g�"�]Da�&�G�����-�{���O�~�|�1��a7k�0�	t��I�m��9�*��$@}�l����
����IHAv��(�j��*hX��B��H'^��Y���8�����
3+J����MV;cTq	+���;��(;��&��� W��_�!���FJ�@��zB!]��~�^ce��l8N��"V
q�@��4�T�*�k*9w
		��_�QY�7#�J?&Z�}���]�v>%�$%D��VE�� #��d��$���lC�DC>���X�&�.`������v�[c��x|����[�!���������a��dp}����fy/~���������0��K�=V�B+p.��P�� ��)��d����fVoY_�����=��]|*bPb���fd���C��BN�������Tkj3�v.�Z�K�x�V�WI�0M~����	_�v��]kp���}����xD���p��l9wW�x�#���!�����269�z\f��\�������/�[��w�vV����y�������<�Gn�(Y���Q��-���������X\�YQ�I���
)�D��=�)�,R$��5���R��3���\����m����8T9�����(�u�j�D�`�et�������xA�1��WZ���;��aY���-CSG,�REP	3�����L���C�)�\H<W���{��E:��,1/���35�c!����/
:�]e�0P�r�9��(u��RL|c�cps����!�uN='(6��J��:)=��M������r��~��h����s#)�{��J��"N����*�A]�8���(C�&9W�h�j@a������8�*�
�l�*�H�Tb��\��[<TWt��,��u�9a*7R5���dC�C���<��	j��;���l�'�E������?�e�M�,+f���1��#WIE���\o
!�$�<��&�BU�b��H)�D�0����E�y6)��')=�aj���FD�KC�T~�9���P�V���)����/����*������"����b�t���2+Do
@�u����QY<yO�,�~_����m�b�@�����de>��Y�����m6N���BW����X��m�����^��s�E�����3��zyZ	o�����������dMk&�L���+{��>���lH$��r3���8f#�rZu3<5c�:�%�W�
,����?��_���v��/5�0O�c�%��-/s���z��pp�9[���_���KbL���J�6��*�J������U���M��A�+������������@���#�>�d��[��nA<���Vy����F�\��aEe�
o��L��T�C�/d��ePRBj���i
�x&����r-J'u�<Y�W^~T|�\�8�,5������&e|�ig����P� Dr�E���A�+�0s�
�4U�2���L=��#�k�u6=�
���"\$/;[�.
Q�E�&k��O���5�V�)�s_�}�4������fc���T'w�r|�lIGO~:�Vb��Q^p�o)���j�
�����=���*eF�w_.*\�b�dS��6�L���j�������W]�/[���?W�Pk�<|hg�-�5�M�l\�W����������boS�Z9���w}�o��V,�������T��<JR�������MRg�WTDk�����|�J>&����5�)*9U�5\��@��W��-����n������E�BG1�	<�����)��2�2k�.�5+�}����"���7����N*P>f}L�\�mY�yN�_�Ch�28��*�
vl�I�d3�j&�S�kc�U���0��1��@�gQX�Q�4zS���X�/��LG,}��b��?�/�J���
��,��S��x�G�Cao��zQ�@��LW�&0�\K����pd��8�=�� ��aU;�!�S�'��[�F_�`���o#PL7�(�<K�#u��V�C���a�&xG����7�L�p���^�M2�a�� �t�F��&��������R�Is��^�}�
�*Xg����A�Pv�8���W���_5|����!�V���4�+���c�+\,�=2�G��d�V���u�8c�|��h�U8\����XA%�(wT~��c�YK��t�c+5��%�JOrr7�N�Q}>�i:w&��/	Z
��|;
�������h8�rq?~Ki]x�#�j����_o��?D��A��X�r��������� ���f�A�z���q	1�N_9�a�N��aZ��:b����Q_�/��XP��U�|�d��/Ge����a/�Q_#Oy�d�����@+W�����������7������5�{��I+�VYEm�b�Q���6��������Ct�8A�Fu22�������i�%w�m�h����k��w<>#��Y#����o%�U��z�2�X�Z�(Z`�L���\88�������po#�s�:o!s�[��]��� �CU%1-k��zP�K��Qo��<����tF�����m<���a�1�$`�=4������ N�,�&�B��8�!��#����=^5'�E�qr���C�K&�jH'<~�>��2��$|���R�7W%W�Z��'f���u������z�d
�t���i�X�+%���p^>[%��C!�#�d	/qg���]�����T��G�g�:�%C��G���lH��k0��_�e�M}��6�G6������"	a�J���J?�(��Hc�#��T,��=�����[eI��24NI��K�����H�|���K��0�c���O�-���S$S��m��ck��|�@��c�7�Up}rd�x��D��� �N\��c���1��� ��6�] 'N�I�*yP�>������Y�$�0�C1+�J|��1r��tR/��{ �u��?����`38�-k=��k�n)~����0�H�c���%E�^��*V13��x����bID��n���8/gc<�+�a��{-�!kR�L��l��*���sN�f�4-�����7�F������S3���ofn6�v[b�Blm�<�nz=�@B��10��<;?W��7���O�=I�'��8��M�9s�P��c�s�������\��E�C"_tz��������:�&2������X}!L���/&����@����.��X3�idfq�$��aF������ll�f^��lt1��
���%����Pn���d�0���Bt,�����F�y>��	`�����s���l��K��F�h��uXLwdg��/���F�����n���I~~�h������bm~�;9�?:L9G����A�zp*d���gy��\WI����N��JcA��<��'+w#)*�M3�3�]B��i�N��=�M����qD��9)������}]�#������o��P�e���B�����{�-��e��tr��|j
���(����3�`�*r���5_z1��$����1�-���~1�����d���CN�;��k��C�~y�����������g��\��a�8I��NwFh����1����g��^����R�1���T��?>O�^~7�P_"���G��C
���9�G��`���a�|�8������l��K��7G�PD����xO.�#��2��O"bN!�N�Qu"z�Mvpz���
�` ��B(L�
��%,;�&{�G0=���p�������N�O%C�a=���� ��H���y��.:pm]l��K��6�|h��E�Y�	Sg`\��]%s'���
�U`h@J�/�b�U��3P�Xj'?%�-��������v��
��Aq40�y`4-�T��Lm	�K�z���R��h�A��P���+��@.2��DH�"T�@��N|�4*b��&����4����B�ip@U���cZ#��!:�}.�c���1b��E�I�� �wI���8J�F����I^`������j�E�Y�=M$:O��u�i*L?�|��>�-�<*/�B=[����E����iU��q+�����7%�Y�#��#o�(b�i!8�N�����Y��;���L9M�7I~��k�A�1����\�MK�b�2�I�I�0�cf�]2�����k���
����Z�/+B�C��%�H�b0
Q;A�;W�(��TRep>#Tg��4�g�8�����;W�Y6�V�SAr��k �i>J�-nL�����O.���}g���K3�V'y��$�n��GY1Ac#o.�Lz2��lY��MHW��U�&iy�IL��U����}�����i�f�g9U��b6��6�H�`�BV�@�n&'�V�t+�97���@W�y�%y���X:\+���������^k�%�	�~�pGTl&�X�
����{�R��6EW)�M�X'��%�*�/����.������)��@������z���,jE�?�?����|������@��9z{\��xlM\n{�X6o�S�7��,-l��Z����]���^�������X\�368j�9����V{��o��X�D�g��p�D��BpD[�v�����>������
����f��*�w�n�nv`v������>��GA��a}�+O���sd�����B���"������U�/��	�%���sD�8��4O�(z����.� �#���Y�+���a���xrtx�g���u��������WN;�'�NO�1����yP�t����"4�����Y�tCvM����j,;�����8���u_9�:��c��ycdVS���kSQ��@�"��R���K,G
2
�L;�5H<���P}�v��=
�o��<ZnJ��������^*�����(z��.QYcA+W���'��]N����S�1�G�*[���Ml�����������g�s�
���0�yH��K\����j��&X^��*�A�J��� Y	����=�Y-<��)'�G�G_���RX�UwM�/&i�~1��
m��D� �T&&#H��
U�\���H��B�z�(���T�%���a�N�{an�-I~�����
�Fk��d1���T���<��L�Gzu�����JrK9#jB^%��d�������/o��wk����#�h����l��i���4+���\k���JZ~��*�\�7��t��~Gke�x�_:���V���i���>�t�0z��"��.V�V����2��K�t,�����8�<���rW��9���l���}��i��j�/w(��N�g�L
f-���6�N��p
x���R������L��t��Nb�CAa������f&�L���*Cq%Ui�j������C��$*���KKN��T���p,u��9��� ��sT�{a�yl/0#TNc�����N����/�R��,O�v7ms�*���,�5"c�2q��G���w�^�0��/G	[����������E_���7�]�=n���q��+�P���	��&�
��J������j���Q�K�+�~���N��r��@�=X��$v���z��k�}�����nJ�.�6�{��(���"�&6�U���)]�M��`����"�F�'�@�.:�jnAVF�nW���qPQ�aO�C<�A�N9p�[�����>�2�����}|���-�X!�������^���K^>����M�j�r0�.f)��4�Lb7�s}J����$����`Z�Qm>�*��B/�TK7��!��I?G����lL�r_H�))���������B�-���U������-���<���l��(I���-+)1
�����W���:�6���S�*n���+��A��jv�'���~��SL?	��jeu����x����I�E�7QM/&�i������wm�}���������������G��}�U�����
����o;���uC��5b����3H���r�f���h�X���`Si���.�M��7�P�e�?W3�:v�x�:3�D��yR7J���N#i��a�e3�<N)���l����rx�P]jtK	���ol���Gwa�UV4�� R
�jyi���L,�Z�a��u��SWLsx8�KJx����]+������[*q�a-�F��#�A����r[j�l �
��tj6	*�L�;��q�G����#l�S9�>�:e�N�N"���
�G�����2����������9�
|"vskL_���R�������v�O��s7���'N�6���k�Q6���K����R�G���������!t�C��!�s��+�\Oh2UG+�/+m'FX�����]:�(Sm7��}�y�9Q���hX�E|���A��O'R�b�4vL�x��cLx�M`R������
��WM�'e��r���1���!5��]�-����ED��'1_�_�6k4dk	0���Q��p�������������Q�Kq{�d���pB>!����7��6^�;�{�}�I��
gR�P[FK�#��b�8�gA�c��B� ���o�������������<��3UW@�)(�U��6����b6H'�����*��6��U��	�F�H�&6)
�6��q�~d����E9=�?����yC)A�qt�3X-�e�������p�����b�$eb���L*�t�`�6�@�9hO|�:(e	��G���%w/�r�� �~�k�}�t���xcjv�����p��<|���\����AfH~M��� ����	��������	`��u���S2���_v,���<"[[sX9�@=xq;�����U��5'p��%Y{B����9��q��q������������y��^�B�&�.�n�M?'���?�>I���~�>~�%�>��������e������������l<z��w����_�	7�=�.�O�����W@+�W}��p�\O�cmR=��/f�65�����Fq}7��u�\�l�o`y��
^,'7P��������K�;qL��~CQ�O/��|����k�/\���V���o������v;}�}�eO�7����V����|���m��7q=�7�����l���}y;�dzU�a����0N��z�����KO"�o�0q�s�����1�I����G�"�>����{$��e��e�|3W �3��fB�
�)U��r6#m�!���EW�y��u;j������N�4��.W�s1��g��Js�I�@0=������1+b��������@�c}�'�_��f�)�.�)�R�t}",
��~{����s��M��VQ�����@�Oy��
,#V/2�
�	�61Q�y���u"��G���@��8x����#��aVl%�;�o�O�v�bz+X;`$K��cV�>S�^�x�����HU�� ���U���A���J�����I��~�z��y5
J��J�����a,
�2��	�<������x�
��0��qt��1��b"���t��B�-;b�^�@x���k���1�<�����F�����T���[# .x�6�����I6@|i������/"����Q�'�[�;�QK�-� ����H8�p������f������lH�c�]_O�><��j�����>6�5�#��mX�H\��������H�� B�g��F:p��d1��i|
���FT����
S�#��[�ye�[`p	���,,g�U�j%�t����_��p.(b�����l� ~��W��FN��x�\��e�����~���������E��������<b	��m�Y���T[p���l�����Q�L�V���y���N�������A��*���.���
lH�g��0I{XP�"���P�l��qP�l������w��{�l'
8��A���GD�S! b214�I��o��v���%!)���f��LH�����M�X���2-�7�yVer1r�4�Qo�o������@�E4�O9U9W0��o}C'����JP2����a���[`�KF����
�WS����v*m}��$�N����������<z���eH��W2;�����
���o���N�z9p��o����=Ol��/C�>����)���o�^��I���C��6j����y�\v�S�|������8���.A+����U]�����A��e�Cd���������]�*C,��v�[��`����I��#�qC�^:�9��XbX�=���4~�o���
���)	��;�C����e�&L������������R�g���C���f�c)d���O���l���	������w\H��8�qfW���������m���J�/��(�J`����f����6`K/����N�f��D(*���V��\��@�[8;������5C�����������|5k��; �C�c������������M{���w�2��R����#vSo��D�6�����5�KK*��\Aj��NN��jQP%����,w�wO�����o,O�b���;���k����	4�a������OZ~,���&�N0�0B�L���,Y�PF�J%�c;�"*��Tr���!���	�b�2A���'���5�l�^���^����',�l$*�l���B���RM�~G~���P�C������}��~E�WY��I�������y��j?�n��T�Z��s��|�H�����������Nt2x"�6��M������F.�%���p���l�\i��/2��2��wa����3�y������v;{�M�������m/��������CC���cbj��)�0QRz:,�"B�`x`�x9�W\�L��TB����0Q��j����� (yNC�|+�-�a�-��0����j)J-�H���	nF�����7������+�R��=�ZJW�U��V8�~zT�m_�*9Y]e^G��_�j.�6�(���`)G�)�Y�o��"����+�V����8�����{��G��w��t����Go<�� ����.�hJgr�S�G�8�:F��cc|�����\�j\�3 qI���}�9�m7Y���a��M��^����<y��y���~��i���XU.k�n:2z�������'���j��#D���x��"���q��
:Hz\��[��Yy���T��������@�!F�_��1-|H�R�\n(�/����=.k���-��8�2��'��ay!�+2%�/`F/(�����oiY�?���Sh�b�	>��`@E�8�d@�z���7h�ta`����_sT���T���\� �t|��H��k�����r��[���r�
�@��p�H�'���{�v����o��/G�N7���i�{������G��fC�#��C�j�b�]����e��x�B�N�C��Pz^�;(�Ki�!W��'4���<E�|����������z
B�N8�O$yH�Art��hV�"��J&A�.��XPYj����t��*��W�Ad���E~��]����?Kvh���d��kY'�p�_����L|z��D�HG?!+���_��D,jB��aI����!�vq	qn8��TE\2�UZnm~�!S���1)�
���s�>U�������
��Q�5���=!��i�8�����y��?J�1�Syq�.�"�`�&s���i�v����J;���K�������nU���E�8��>���K������y��x�W=I�%E�!���Gy�Qjd��"�7�hIQT6[���OmS �)F�a��_�����^�eC� �a+����1��C�����7�V�����q202�K@[b�x�n�C�S��e6["�N���L`��7 b��?����
���m�;x��7[?���n�h�4��-
����+��u)�C���*b���De*�p����,j �d���Su]����cYe�HT�uX6��"G�����zq�WV/�o<�?��[N��3
��Q�U��#�BM������������o~poX���u����O"������6^L��Q�����aA��o�w%���s�4�`���%0����{�e\V��Hih��4w�:�/�o���'l������L9��2�D�2��K�1U�S��G��M�qr���@@m#Kj��P�M���@]����#[j5�R�e(��&��l4Y�Mq=|*��6��!C��J*P$���)��w
,g��p�v�Y#���Ma������

�����������#�LX�.���D��������M�N��0@��a$8�L��
/�����G�T�om:����[����y�=�$�i\=��%��A�|����V�]��;�y����1�P�]S#�����
;���� d'�=���A����5k&���N�N����#�%�r&I����[�o�����?���,���`E��"�o��9������an0D��v���B����o�@>�o1(�����������'��'}���������h4�O���^i�*�0�IF	���q&��[��Y���cLr�$�M����l,�)�6�K�U��O����1���_����9M��D+X���#��nt�w����|�[�r�F�E��z�����
w��������9������b�.��v_�7����xaZY����$z��K���,��`�c
��K�&j�=���v��������Yd-	:�����������-%���E�����y�w���Jy�g���wv~��wr�a��tr�t7���U�t'��m�m��s>'�^R����F�,\/"@�)�8~�����Z�;6a��3;�Vhjh�@U��P��b1c�!%�EP�@�Ii-vA���Hk^yC6�?��&{��=3�X��+A��bL^�eN����	i���o������?|�����:�������4��
�����,�s��j����T������F}bn����E�B�N�{��E�=n="��O���PO���>������MxX��Y��s�=��� <HX�i:I?e�i��Y6H�j%@{�f��E��QxT�������d}LM'.�������}�����>O�>�
����;b]�(��$aw`_���z����R���U�j%�3�|n6y2GiV�a-��0�H��*�r��X����{S��-����+���P�l�V�e���w|����O�>m=�����c����%��8,�<s��-�������������&������CAP�����Q2t%�PA���(���0"Wdl7�����C��#��������r���]z������0�
�F�n���2���F���2@	��&\���_����r�JFW�I��Z6X�e^y���Z�o���;o�~���4�=z����_&��J0��R���A���1���.��%6#N��J��qC�J��A���B�/�ts��(�����aIv��X��r�l���=��B(z���]B����Y�}�Zk�%C6	�5�8-`��&�	V���a�b�2�4,]T���m�q���-GPP ��a$G?K�����f��4i������]��1h��QB��G%�
��l���F%�0���A��|�K�o�W�����<�/Z�p�
EDTU������M�X��@���<r�M�a*v�I�eFeB(�������5��I����9����[����xD�X	�
\#�!<����������2���.|�A���P�n����7�
�:N�@���SF��k88@���^���6�Vx��*��C�
����0��z�n�IN,�	G��	����������^�������H~��k�����3VGs���.&�Y�.`����|98��@���Q<�|�������,v��1V��b.,�4r����'8����P4��������6/�;���Mz��#x{�P �|9��imxZP=^V�Ex��pb�����?�e���T H����IY��gMT��u������%?�h>��,n���\P��V�n�N���X�o�0������J
4��������!��h�s��+.�}4�C�*��@�f��GA�R�pY��/�=u��j9��E�)���R��E���b������������,a�-������H��uK���N�r��������� 	��E�}�p�p�h��
���DIx�bR�0-?&wY���v�Cg������]���������������PW��[@6N�������@`���14�\W01b)�!��/Y���x�CO=�(�J�)v{�w��sFq���NB�|w��}���a����[�,�r������
��������C�^�f��Lb�#,��o ,$qY�n��O�R`D|^y�7�������_�&Q��'�T�a��_h����SB`r$1����{"7��*�q��M���U��[�e���7�C�]�>u�\���������gg{��\�x9U�l��vn�%?�s�/���DM����*�:
nkp-������i�	�t��;"�y�>�A�e���I���;[���r���\���t������Zr��:�z�v0s�j4E&VA%������CTZy/A�	6��A�"�=*0�#'��q	�F���TduH��XJ� ����a�l��"S�F��x�4�j��1B��]c7�m���!`$��?f�2��
lP ,Z%0�����S�T�	r��IV+�}��]�U$�g����i������o��r��o`���!��}���q��TP2���A�$����b3tN��z��J$[~���A4�K��I��^CY��Ls4)��z��	�p��cp����W�bX=�o�Pr�u������������V����Nh�r,U[�t�:2H��"���r�1��$�Qv�����n���^��Z��v;�B��#��)Z��Q��p�}������$��F�� @��v[�`�9���w9r���c8V�6w��;N���v�������oa�:VQ4��q0��7[P]J$a�r��%#������$R�������AK�+���_��3!�����Pb�:����7��sG�G��l��[��Bp4'�������� F�����fk]���)�*"� ���C���e��v��#%�\}@

�h�
�0{HB���i3���}�'�	0��0Q/��:Zy-<��0�wE��`������}���,��up��h�J���{��q���r��2��A]
����XK�����
��u|�1�����P�������p�]���v�>Q����'��{�n?}��Ov#a.�w����S�"z��Ww�Mm�i�o�*�v�����L�$�p
6�=;���-�1�����|�}��=��6tg�:��{���{�E$~����*�-�b���gl[�	`��
��i6���L��}�%��;bt��U~���3����6����L����&0o�$.��1|'��UIx����q+�j���v���8�+�#�2��1�<�$;	��1,N�t4A%,�������y-~���@_�o.�����)Y�i*
�5U������*��T1���m��_]�����d��oo�?����-(c;���\t���}����o�>tE���B�D��_�����7�"����_�E��a��i�F���k8B~�+'�q��]
z��=10I������0*%�r���(�i����v�q�$��RkdIH+�,X��H�E{=��8���s��I��u�H���&PK�7;X�C~�M�z���1[:���s�r���M�hA���zq��c�(#!lm���r<�S0��ZBr$�f���P�bqc��	� Z�!�O��{�r#��'�XNd�V6ha-��\����J�v�0T�����,�*/��r
�5z���k���(����P`�(��,�W��d����,���;V��kto1��������9\a�O!��j�t�R��r�Jh�����kSh?��P����n��qAfJQ)q�&l;� �-b��u1p�����x;'>7���J"/���qTPRo��h�dRz��������2k�m�g=]/a<�@9f�
dBt������I���v�GJ��6!Ei��=It�Fh������z45�3���:��9�3���]-�������9��1��el�g�<
���BH�_@���^��L��k���@��`*X��k4u7,x�:
6:���w^=�I�Uw+y�bA��T,���O��]w@��@��s%��3*��a���v��g+�}�M�r�yH���	�R|�H��Yl*&������.0D����.!��� �b0S>�}� ��V��Sb�����0x0"�p���n���2��b��A��miW��� Zgy��������t
�BR���%�W�&�=�n�"������[�%�J���;#5Y���T�T&�R&�	�R&U
���i��
'�����01�A>3X��������g�`GT��oO�o��w5h��z�C2�������	��$+D���+���J�������Ho�XvC��|;����8�������d���(��tt�@��aP��P!��%Y��M�X�!8����n5�o(�B���K��C��7����4�Y.������Q�J~��#�G�{��BY��,�!��� ���w�������o�}��\������M�;*������DtI�N�_B�\���j[ �[���������5�����8j�]YV���J�T���(���o�Ao�g��[�xL�T?5��x$]�l�)W�� ��F�����,��Z�~Rm�	���[�nU�
Q�����i�$&���aXuf�;�(f��=�@� �}#h9x�y�v�0���/r<���LC�]��SS�$t�9�dr/��S��8���@��[!�K#�o�����Rp���bQ7�$�FJI+DS�y;�)��f���;<J�y[���qst�A�,/��3�iPut�B��D��n�s[�������!���/�A� ��?ytp~68���l ��/A���Tq.���.���`������u����|��[���w�E��$h�'�v��l7�����t�����	�D_���7���@���$�V��`M����~�yp�4��{����8�������
�O��jZM�3������H��;�M�4Cv�����,�7<^���">Kcb�0��a�3��+��a��9@���p\�[����2^00
�x���h�h,Vm����s�t�w����j���p]�B����+:qh���[��Mhg�8|��?6w�X��f�����2�G�����+���k�I$dbt��|��6���������w7��
�y�(GQP������j�������r�K����|��x7^�HU�E`.�{01��3���6�� U0}��C8�Ao�"[�mH$a�J������h5�U���;��	�����(?D��+[��hC�H���A����e�~L�g=�:���
�-��97���xg#�/�Y%��Z�h�S�/���+���F��V;7���	���"
^LC�?b�t�%L���\�Z*
t�b���TlV2[>���>�
�"�7����w}~�]��7��yU���eY�E9�I$�}��,���W�������K9Q��dFt���&��d[�A�q9E4�u�S�5�Q�:9��9������#o0M�*���������W�!K%YJ��M��������eF7O��Pp�b�(����Tm�����a��v�p�{�V�,�B�`����>��"]���t
�{D`y��l����3<�D��h�l�f����5��w;�������'%)*�!�H��H����~�B[�JH�����-E������Ig9����O��(�5���iI����Qm[��U�������:l�/�7�c�4�G�e���^�u�u.6K�e;�{.t�M�XT08K�� Hx}�
/_�K�e>_
z
�%����1y,{���`�V�9��t���Ze�S_cCn�?��d�?w��i��)�*	������c�����"�K!	�-e�����~C�Y�eu'�_�,@���S�`��K���F8#���dL�F��	�]bb9P#cV�%~��tp��$I��I�-�S����������(���F��D�H��mC���b^��H0�������������m6OF`.�k(g�An����
!'+��H�L�hU��EXb���&*#A������M�8!�Zh���Q��j��vRRi-��f<[�qv�6�@=����,��	��P�����6(^�a�!vcQ^:���N��n�.��-� >.��H���;�n�d� ��"�������4($[���w�e2����6��rU~��$�,�h,G�V�fT�_��������,oQ���12�$=��E����t-,XnQy��]	�D����Zn� O��-���<�*��5JX<�FL�x�x��b0�n���bv��;swK����e3g+��:(�v��NF��������:�al��l��s��Ps
1��p��sc�F���C�l���+N)�k8��{A����xr�����p�4���
�cC@M������"�A�Z�c�'���o�D������?������T���I|�?������0��fL+/�	���v��*M1�1*� ��_��=R�t��d�J���}���#;5]���C�n.DG{��@O=�2/�0��b);)7�2�v��j��?v�1��q��������3�E���~e��?�&����
�����+s�^l.Z���b1N
�����$������p����q(����Ch��p��������\db1�3(<��l����5[-��!��ne%��7����o��bSg�C}r�h��!�A n����vB����1&8�@X���hG�&uv(�����;����\���}�F��E��BF�s��7�^���!��thY��n=/wV�+m%$C�����db�`��<)Qpg��x���J�\�����n��+������h���hh}����B���u�����~�
�������s��63��t�^����;t��_27f�����by�o�*�d�	�������������n������2��x�=7������u�sf��:�����G�=pIx�?S��}9G�S7�KvL�$�K�w�7	��nO=Tj�)��W"�����
+��#_�1/��J�D&��;�J#��
��I�������E��[�A|��r�����Z��(=�,zf�a������~G�1��K6Ux���=����{�-��h�7��G'.oa��������Dj��x�r�}M^o��
� .��`�����P��q�����D���0`0����p�r�s.��3">j,��� ���T��� �|D��-vq��v����%��(�&���.|*���W�/�r-���b��e��&�$�sJ���H$t]�����GGP��?��?ki>
%���pO��N`��B^n��gW�a����TK�pg����Ew��2���o���!�Z��`p9�R�`�	��
���T�i\��]������Z
�v5%>P�3�����t��Rx6���/b�$��,!�cq3�Z��mU����t�->*���L��Y���j�1K��L��3�
:��i
�P�G�d�7M����d��p��Q��1�6��G��o��B^W�k�X�U������-vB�T�	���
�����N�Z�a����\yO�]��_�=^���j��%���f[�.|/I���?Dc��HH�-�M;��Px�������c����=��������$�C��-���
F�F�S`[6^�L��Q7��ZE	�!�p��}���7���S8��D����,K�0s����p�QvSu�������3��!�$J�gC��0�����)���W&f�b�9'��C�h�^�#��0:��[�7��q���;|zy����'5c���������[C$���r��}�u��
&<���@���j{
� �c�����=���������,j���?�[�e(
�$va�P+]����A��3:�,�AY�����w��Ke�%�H(�:#r��8�Q�D�saQ�.fc���v$�6/�/��BY4&D������$l��n�M����xHx�7
Eq�P|lx-��Fp����D?����B�m6U���xU%�pbh�������ok�Rv��*�B_fL(S���>�CJ/���V�\���aE��"��$]g�:x4������`A��}���Zk�	\�=G��T�Tn+)�!o��`���u�-�8H�G�����R��,�}!�Q��K����~���v��0��9l��#���/[,(�"���6�1��f���0
��T�=B&��+N���7��{b��/w  _�����`�*&ua<�@QT4�Q������f��s	�i6�9/��",+��j�g���k���syBQ��^��~�"����"�gX�@+h�IX���^-xQk[(�������r&uM����M����;RF�����p?�08��FS�T>%���Q4������G�
q�!:�<�QR��v}]5�z�8 ���j�'H�adG��������>�W����h��s!����D�V�i��h�
��]�WXV���>���Rz����:@�8]�b�pH��k_+�(Og�l�a�,@�������
	4\�Eu�Al9*�9K�tg.���u<��dX�L?�6��pCR�g0����/��%��Gw��8JN��&R�5v/6�J
����g<�L�,&�M�(
�������/�����j�&C���]���Sonv5�2{Z�Q����(�}��oQ�.����	^��t%e9��e�-b���������t�C������c���DpZEh+��>X%�����2E���{�a��x}���^�zZ�wR&{���N��
]E��{kT��JyE��Z��U�����lV����Y�JF� ���<|ES��nP8w)���g���!TF�w.�&�Y���ID��Ppd�Y�fhRqf��-����<���N��@�9^��x�����-�PA�\� �����e���UA�@{����0������6RH���f�i��;��?h��a+�ZI�cf���8a������Y�.��+
K���k���o�m��"V�P(X���4��0�����6V�
����Y��^=U���a0D'U^�"�U�?`b9������Y����&��G�����9Vt?��@���*����El�%��+ ��%��cFW>]�5��9&���4��_��X�����tL�Q��	�p�X�*�I���bH��0^����_�K
&7�h���_������.���.sD\�m��px�J�`�[����%��4�MeobDr
�+�D<m=������O}��^����1�R�H/�������E�,U/w��)���d��e]��*�������]��B^��jK�tC������!��y�L���.�h)��k�1h%���(�,��/��UE]��
P<�k��� ����;��M�!���6����+p�hm����I�&PW��O��$�^_�����&k�<�-C�����J����L�oh?"����>�+���B
��^��$�������D	bes&&6(���<-��������B���L�{�d�x����'����+��"�[W����3���^��]fWZ��6�L�G�����,��:L�����AeF���}��"��t�19��k���F~O����������i&g=,�
��4^{��{�Ja���b
�;�@@$��&���s��<
�U�"��������~Ld�K�bA$(Q[���Tr�G!G�x�@�`X��I,�b��V�d��!�i��S1�W��F�5Cj�k�����c�z<��Ja2S���8��b�]�|MP���b9�)�����v%�e�����"������`�G�?;`�<L(�%�3B�R*uT�
�i�hb{��<��t@��P�
�������t���t<FYy�<�������U��t� 0V���K�C�> d=,�)*�P|L'qM��L��z�dND%�pd��-�Q�lp����X���6n��d��Q���'Y<�:,�e��U�Q60$�*��w�P�
���C�$��<T������v]m����auE�l=���y2�M�#���!`%������Tv�)!�"Q0.����4�T@�����&�K��$���b��Y���77������t�
�J�U��Cn��w�x�'@�Z��)"Fr�43���Hc�	G���P���{2M��!7��F��M��d���"���E�v����u����C��~{=��t�����V5���,��ES��=����������B�)�_�� �}}�E��Z�KR�������L�����x8�����F|�*.,�P���i���F�B��������{��S@
�Xu�C �	2P|B�4���j�� �
�

�3����xm���J���m[&�fT��f����@?���!:���MQFf���22���<s�=@��Z�	��������v��c��N���@���h4:��F���A��~�e�/3,��:4��:0oMK�(X��cX����?N���Ll{A�dY������ai}�d(�������a��|�����~�.���r�h�/�q���L��N�L��^����L��E��/ ��y2������y�W8���_���8���Z
FQr���j��px�*�A���5��P�3�U��n�*yMJ#Z��L\%�ei+o��I�x�q����"R5sZ���	<A(���:$8��S2Z���kX���]�x�+/b��si���5�'��Z��8l'�f�D����h��h@0����;����B9,�hK�����=C��d�)k:�?gV�W?>�9"�,<��0�8Wj�>�-�*`'k6�%4���z+g�]o�-��'�����_6:��-������p���1�\FFw�Fh�1�1��a���9���"�Jo�t!��W����K�0gVLj�&������'�yY�K���o�:5��Z��9j&�������fF���|�����F�������������_��tL!�6�r6{~a���r��uyX�o>�L���omU����n1�h����;�K�W��biW������5�R�d�D"[����[m�������Y4Nl������i �����~���LF*�;�r0�|ip|�b�����wit��/���:'�I��3q�������l������)�n"6�?��^^�r����F��c�}�kv���)����1c��e\��oD
R��*\�)�<���(�j��������J��MD!�l}��	�bV<:4]���#��m���S,X���O�1��S���<�L|7�4����R1/`�[��4�]�B���pfYd!�
����|�T2[w,����Nu��lv�6�����#x��c���
���	�-��,�������z���{�b|=;"h���R"(��pu���,N�jde�6��r�����V���v�	���}��L����C�
�(@=�8���:����UMA�_���y���c~���7>�����tSP��s6�tS�>D�O���e���|�M����j�����lDs��8������GK<�`��z���_��Z�
����.��Y���SO���~��Zp�I,j7��(0��"
�s��`���[�H�$(;8:� {�SG�6�f0Y���F�b\^X#�9��M�pl���=��N-*/<B	�A�A�jmY�!����^��42�W��1�b��1%�#���I\�A��I.�p��{�a!�K���E��*��-d�d+�Uz���k���7e��?l�q�����������nx��n�o��^���_Hw��2�|`\[7$�\w>�������@���^\P�
���:�a�X��W���E��o�4��*�h����,�E�zgq��O��~�{�(�M�usrxL������T��o*��7����V��U���b��}]���r�� �n��k����Y�'A�n�?���>vy
0004-wal_decoding-Only-peg-the-xmin-horizon-for-catalog-t.patch.gzapplication/x-patch-gzipDownload
0005-wal_decoding-Allow-walsenders-to-connect-to-a-specif.patch.gzapplication/x-patch-gzipDownload
0006-wal_decoding-logical-changeset-extraction-walsender-.patch.gzapplication/x-patch-gzipDownload
0007-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gzapplication/x-patch-gzipDownload
0008-wal_decoding-test_decoding-Add-a-simple-decoding-mod.patch.gzapplication/x-patch-gzipDownload
����R0008-wal_decoding-test_decoding-Add-a-simple-decoding-mod.patch��}s�F���?���:QE� %Y�:Z�m]����M\�$�� ��%����u� ��&)�o��Tb���g���1����E�f�F}�vxXk���q��y�����i���ao���3�Wr"��Vk���Q��K�IMK���'}���Sg �f���������vu .��l����"��X�I����V���x.�k�Z�t5����-��]�����=���[��d�X��%�����@����[��pI����X���N�Y�R��>���+
~����S��������"��|���b{&��h�&�= �����nB- ���]u�AFz��g�<��I������^0�(�d
��r����2�����JU�Hol���:~����7�b5�=y�Y�L�O��C��x��~���{�mwd�M�Jg��.`�w�J�s-�G��q�LV7x(�*�Y_�a���r�[�{
cO��3�%�g)m���E���Q���`�i.��VP��k.�~���N�ZKhY�g�o�~��F��J�e��5��0_������Dud�=�3�T���g��umw2���t���~"r�Wm�����e�������85�L�������[T3OR��*i�����%�n
�lx{�h>�=DM�"�	iQ��j����������p���Y\[Gt����D�5�QlM�8��!W����NF�Ri`
�bggd���%J�����;1���j�f�����l��
��(������W�P�A��z�������x)�Y?��=[�N�����~��LL���D������o�m���>ER�����N��K�
[`N��[rA���*�&;$l���Z}�����C�V4�>�:S��4���`�
�R�\uj�������vi�����i���F����J����;�W'��S���*{�����������/o�M�.�	�d���R�R��:����n����xR���s/<9��
�:��.��1?�������S7.)��v�u1m�o����e�{t�is�v<�Sy2����JEWIm����fU����}�������7�����'oH��8�Z#>���h�$]�
W��r|�9�dt��,�oO�����Wt@�>��?�
,�vUi;p'������ju�ZM*K���-H,��%������N���?�e����c��a6���:����f�sjQ�l�
�-?K�e8�lT�����a���!�2���7��I�*�����.,��U��24�1��E#��R��I�^h�^Q:O��O}���$���|2S|��������f�����r��'�eI�m�l29���������2& �^XCUWRB-1���i;C���k������s��]]X�I���bJCF��"�S'����(��T>k��!w;*�	��nx9W3�%����X �)}g�X�w/m_v�\v����v�~�zI���a�&U�����dS�� �v3�#
�S�%?k�<ap��CW�';z��:n3j��~Y�
�]T�yxf|M����������A��Zm��_o=��'W��k�R��U�����*���>��3\X�������k�L+l�+���'���tk����^�h��s��HE����M���X�B��[i��a��YWI����^���F"�+&����gtG���uG���
��4��V��c���y�:����V�\���p�cj��4�������k�i9V�)^_^���
�Vr���#���7g��:�Y�)C6�H��{���c�������\Ti�\�{�|�������2>ry�cp/��ZpQ������������x�&L�����9�T`#�wcV���"�M��r>��5toB���}����RqmXqw$��^��k����'L�v���������gz�����=Py��G�6����
A(a�FR%����kr?���!�A�;��4��#��v����}��>E(u\Fq��9�����<U�pn��c:��;����,����Kl�X�5����D���w��o�4��)�����/�x4/�*:^�
U)H��ZQ {�=�����<!�{����I�����<A�L}��3�x����l�W�=����/��R�r|�l7���l����[*�/v��i�,+�W�/��9h�wG�����Z��4hk�}�:��e��p���h�z q59�+���9�(S�k��������.?�d6���Z���e����U�L�]���E���V�����GM@u��l�P�",�P���#��F�hI{J����tj�E�5Wn=��=�(8��2>H�=G��3s�j
�>x!��z�Y����<'S����N�Z����������u��i'9������e�����I�T��<9k_~�v>TT;s���
U�.�(��-^�n��x`���99��'���Z��__���j��?���;W�\������
�?�8;;�������������8�8}v.h���]z�%g&T��h>�5���P�c�4�HO�"����������-��>n�>�X_k�����ZMp�9o�u�FP���d��t��!����f�&4Q��cSPw�a����<z�.����t=�
k27{yJ�&��������L�s�\�l������)~4�h��P���FK���Jc�J���G���-�����rx�������32���~o������/S�L�/����_�gY+���2�/+�X[��2�������l��(��W�Q��L?E[�Z��a�����:�e4�����7��h��`��*D���}�+|�x�����2����NwVNP�Jl=}lW�g�WG����O1o�=x.���U�����������Y_Xv%R�2�x��c�0Rv4�N�V����y�����{�1�n|��cY6�fP�e{qP�x����G�
YSg.���4"�|x�#[F#S�������s�G��f�`#Sf.c(��"�7�@��>/��4!>[�����S����=������N��)/PK�2m����(����h
 ]f�z2���\�e�a|atK��'��}�J>��T����g�M�^h�o7�����������
�iK����h*mS}�cTf���L,b���f�������K��c#h>D���eF<hR�H���!o�O7yr��tURy�`6(�u��l������'�k����}��5�(�G��x���B�_8#���BU-�"#�H�W�Y-9����FsK����x`l�oo;��{�Z��|����N^�Og�m/��������D���&%���p4��'�S������l�"���kJ�;�1\�~��P�~sy���x����?�)���W�t���1E/��>_'�%[���SeW���e'�:�F���:/j�x$G
��y��H��5y�=��?F���V�����=s�d��J��� ����*�L�j+�������9c�>��|�*��7'jFO�n�W�$���3�T����c������t*M��I�\�Q����$}sc��$-j�7�/w'j7hEYq�T
����w���2���[m�wH���u5�^���ywAWs
�z$����.�)�W�.w�����_�c}��Ev�WvXr^M/9�|��iY����i�2�x�k������K���y�����BQc�f^�X���9�+��_$�cj��^K��%���������$�9c�>h�B���$�y-/~rP�!w�"9�W���5��4��7i~�L��{yz����z�\h�HZ�VwV��SB�C�sf�0N��/������h�c��s��w�]������+�z�s�+e��|z��OM������tTo����-��I~�N� �I��lq����Mt�i��
f����������"�Pe�������5ke���������E�����fa��5�����>����jK�^����2���#����w�*b��k~R�f����^C
�����f��h	�$����t�	�[�?^������F1��H�'#s"M����p]N�x;wgmzK��#����-�k�:��F��J�rKG�����,�r�:��/^�[[�Cj%X=����e�4�20�e=�W/��xED��������5_�����M������(�[��h��6�%Ud*�
j��
Z�9��<�i�TU�4n��#�Qj��w/[=��Z��"��������M��
Lo�vK��Y���R���G��ftl�=�Guqd5o��_}Q��
�{M~/��~�l��������������|���r�tLlS�>�����:�1����`��y��R�����W-��I�2��RO�-7������T��[�)���i`���}qr����J��-�K/y$-�8�X�:�5
����RXj_^�?|�49B�6�X��$��~:S0��0�1�1����]~9�aCw����g�_�_���`r������5��RF��*�� N�W��-P���t=�p�mt���~��
�-�;4�������WJ����@��8(��yT@����M���,���!�}/.���s��o��c_/�eh�����E����V����[�W6q��������
����~\P7D�����-���z�cW/���Y���C_�YT��-�_��Z�7r�S��-}���kO3k�H�e�������|;W��a:!���V�)Q�0�7p����?ad����Fw���F��D����&��b,���M�����k��}�{��6�q�uC�.o��Ul��	e�yW�FnmV&�n���\�V%��F�TE������)H��m��/������k\�_���WY5�z������(nfv��^v������q������xM!{�_��k�V#�a;�^��_w�vF<�Nb�?�%��)�_�Uz4��D�X��gB�Z�����(��"�
?/H�77�g��D��s�_\�=9�8�$���SZ5��MZ����~�F�j
���k�3i�,�NVI��R�j�u����F�5�� �LG�g%��H\:���������l]�'�J��L�W�"���"���e��Cj���pnY��s^�_a>9?���@�o���K��'��0V�_����-��M���rPV��E���t4�T>;X�����,z�L(9��][�<���GiZ]m���������ku���
5�y�������w���S?lH�1�����Q�gUMV!~eJ���5G���j�Z�Wq67���He�j��=*��,�������)���0*p��W��82�����.eaE�������R'���U���z7���c�t��#�z��(?A��F��m1=����y�����om�N)m�������m#I�~m
�gw,��
 H�����JF�8�������<�(	��D"5$��;����j��H&e)q���:����wU�U�@��/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x����/^�x��V�}/���7;/����o����}1�����g�}w��>����x�Q���������{�}�7����uF��k��N������{����^���������m�y��^?��,�S��g�������r����}���:Q�|���G�x��+\��.=��k����+����^A;��Zcc���C)���L��K�>}���/v����@���.\Kes������8/�{��~��������Y��I����Yr�kQ�N{%�������^�D��"Q��J��s��Nv��/��l�M����_~�����Zb��G�y�!�������I��Q�a��I�5�V�h��F#i����l��V��(�8i$I�&Y�L�����"��F��i���4O[i;-�8kdI�fY��������7���6�f��7[�v�����'y�gy3��V���V�j��V��Z�V�j����������v���[�v�(��\��D�
�����N�.�8!�����A1*���#ch�����%a�i#�I������H���h��J���5�f#�i���i��b�/K�����,od�F�ndE��R���LM�����V��n4�F�y���F�5rf�Yi5�v#/�Xl%�V�he�V�����h�v����F;m��F��h��6X1_LO����F�6��Q4E�(Z�(�2���$��$�����y�����k24����{�H?�X��0I�da@��H�$�5���"Y�6�4O�V����H�X��Ar��4�,O�V����H��&��5����!2y�l%�v�,�<&\*O�<Kr��i%y;���.z�J�V���I!E��I�H������4igI������#YR���J�,)�I�'E+)qd<�+N�8K�f�i�J�v3��DCr�p ��*�.��h������=]�E�36RS �:��E�QZ�Y,Yc
�%C��i��Y+��iV��Xb��rP�C����J���Y�y,	e�9_��9��������E��%�`��ZY�j�-��k��"m��k���,m7�v���mt��y����_Z4�"O�VZ���~,md�gY���<�[Y��b�0��H���> �H6�����!��F8�`K�J��K����h�����"��(�;�<�l�'+�f,�D��B~ib��������Ydy,}E�]��Z��V�����Z�T	e�9_���0j�v�*�v,-Gx��K��Y;���<��)� ��E/�UY�gE++0���X��I:7�q��[����Q�XfC�(U�e8����eQ�{��%UAz$HbI[�K8�`K:�i~SM���130z_4���4O��\�`c�1������^(%���K��n5�v3/��X�
}E�]ja�1��f�h�c�<T	e�9_;o���:f<���/�p){�h5���e)1�5p��8��V������d�BR3��� ������T*�eS0XL���J-S�/-BU���bYe	b*��� H0��X[S�Jj4SLcf`E�.6d�t�,7��Aty��b�y�J��1������y�������"��.��H��!l���2���(���C��.�Zq�C�(E��J�EEtR�90y��F�<�����G�(�%�ED�_��A���c8��u,����R)#CU���E_��T:$�b�@�c1�PI�^��\��\����l�.�I��9�{�*Z�X|���z���S�/m|\���0l�+b��r.C�������6UFB�x���1L�`���rqv�K�b��X�+�Ke�R�z!R���e�T�Av9WeF��X�-���l���������,�t/���*`��%�����-��%�*� �R�!�o���tm
�!�S?2i��O�W�.b�3��B)�5��_���8�OU�6�1dv9(��U�#U�KT�sS��R��Q��P�P�F��QladY�F`�QQa�R=f�3�����ha�0�V��*��f8
3�)sajY���*�	}a�[� &R�	Ga0XaS_�$6�
��.v��+����Rq����!�G*�T>���X~�9�
��r2�J�a�[(�O.�9�kr��z���%gI.��7rb���!��!�B.��"}Q�\4-2��XE�"IQ�O�&�E��D7"Q�B4 c/�.�-�,#,S+�*�)�((C's&�%�$$3#c"�!� ���K���RK)�TL�$u�RH�%�c	�D��{9�r��d�<E
2vR�B
��$j�4x
L�V�t��1,P��/�^��t9�r��X��5I�)�<��� �V���B;M��C�"��CD%,�"�Qa�y�����b3YiYi��	�x���%�@�'S.%�S`a]�����?�e�e���
1lX�!�U�����HA�NJ�`���l�����9d��
;4=
<y(�P���C��������*�|?*�x�AT�.x$��X<��}�[$���<��(��N�	�f(�P���@���|�0�R�zr�i�T��&
8�)x�rR���<�E*���-��[T�r�h��v�a��T���2���<���N�<�Y*��b���iV1��b��H���U�%s�bx��L%�v��q�*���������I����Z��2q64R��jRiP�v�a"o1����/+M��8U\��Jja���!�)�Q�� E���0���b����v��'�<�}�
��C�<�a*���T<���������x�A�h�<�y����|(���CPe�������L�|qcl�Ri��v��P�S��Ib��%U���������
���Y���J;��<1+q0-�B�T	*����J;� �
�G����S"�Z�!��<�(�l��P�E;�R
�)�3c�A BU�D
����J;�0S8�T�������x����8�C����<p�rhi�r�d���v���DUnF����*.	�v��A�x@�Teq�`z��x��,+�x�T�C�h{[�fZ�44��E����<��	O��<����|?*����|���:���v���
��
��Q��k�)��/�U^�BN���G���R�G;o
����Q
xQi�+w���v������v��h�J;���*��x�Wj<a*�����l��ky����!�v��GG�x��Q�7���1!�K*�>2�0/�h�#5��
����8�T���Qe�P�v�A��%�v��	���NS��8�<���\M�6���T����*���2��RlJ)%b�>��)��+��W��PV��R�*����E��a��fT���U���� '��AXB�xHP�T�#>67g�J;�����<p���T����N*�<=���m�h��0�N�B�L3�F�2����#qpI����Qj�1�v�AH��TIR��S*����&�
x�R��<�(��������*UiW���)*���\$�E��SK��;�Nq����r�V+xV��@��
ji�<��bD*���������N�S��cDNT����v�AtBUn8.x�Ra� ��2�J��G�"r����M������h��%
yiD�T��%�v�a�a���`���/�v�A8��<���
�i��T���pp3��h��D��c��,�v�a�(xSi�+#�P�v�A���wU�l%i�|TRM�"K��NA��ri�+�W���\����F+����%���<<��B���&��k��TX<��H<x���E{H��s�-d��B��V���NV�<����k-�����
O�� �v�A�M�x�����U�l�Bn���6�v�A��y� ��jiA8�����J;�0�<�������p�v�A�LH��<����q��s���x����2���*����ed��
/�Si���J(��������;j||����?0�4�D`��@�TdZ���#���J�#���A�KW�VZ�K�-���Y�mK���Y����!	k������8+���2_��X���b�=����������F��D�G�#DR�Z9Y��CSn�.��!�L����JH*���uGI\S��h�@Ypew��T6NY&��'�LZz���R�J+����RQ6,%W�r��h�A�t����T^O�*�0P�q�8�����J�*����M��4�>��hC�ye��IU�P�/M�9��J�EZQr_Ik%c�d�X�O��i��QzE��E��(��H��>����q��fGB��X���Z��
Gj*�T�XH-lSH�pK���$�@
o�v'*(��/�]���n��E
ss���=��)�R.��A�zEs��Z�m�K$wG���� E1sD��sQ�hX+�5A��DE����A�_f]&�2�q0�2�22m2[2I272%EgCC���G	x$���GA�-o�Xl�XL�4�31�m6��B�9[���:���uK�Nj
R+�R%�����<�H�#�<L����<�L�j��<�H��TP�@�H�#���e%��G	x��*Y	x$���F�J;�H��TY	E�H�#�<�HZZV�x��+�	x$���G	x$m��-]l��D7�G	x$���G	x��0����<R�H�#,^0-��K,O�Z|�� 5��m�j�GIP[����$���5$��(��\�L��Z��Y�iuUk�Z)�z�V=e��L�<�Lk���<R�H��L������@���#�<�*))x����G�k��v�����L%n�#�<R�H�#mi��v�afU�]�H�#�<R�H�#mk��r��N�#�
���G
)x������g�R�!�������GY\n���rF��*��e���13�ds�u^��Gxd���GFJH��[p��H���--�hBt������:lk���z�Vm�6�XQ�����GYS���<2�0�Q�<2���#�,��#��#�&%��#�<2���#ki��v�a��$:xd���Gxd�����d)�h��#�L7��Gxd����h���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������W�����;J�?>�wF��?�����A��6n��������=>�a�����;�����Q�3��;���^?���(�}�����?jD�{y��?i|?*?�����[m�R�V,z+,]�x�a@�Eia$K�:\Ht)�X 0f��,0�&��D1��f�l5�M��C9J�7�<o����� ��j��V��f�Prs�f*�y��n����\��D�
���-���i��\p�������b`����"T~d���	�B�0*�*J� L��A@�Qc4�C�D���`�{��>aO�S4����&��d"rH��2E��"�Y0f�����`J�R�O[pf�j��$�=�)��m���5�EhV��.0���4��M�2�����P�%��:�)(����4����������Fv����4 ����5����M��a�0R�ZC���1���W�� 
k�|M�6b���|��T��K�tlR���`1HLt\����G5���wA]"b���mH�����,�E#����HM�
������HJ���6�#�X`P�B4"�b��`	`�R�`4���Dcf`��.�������I��!�-B���"����_0wX2������44��D�P���k���s�;�v�i-��!�`��ZX�&���+����.z���6��6�LD�(8�����E 8
��@��C����b/1��L�t/���*�B�d#�����-��%H0�%�2���D���`��������!�2�#�����`|��2�
�S�/M�P����}E�]��Z����/ZA��P&����X}�>6�/�A�^0�R�&�S������0H=`�������c�1��g�Z�AQ�@>�
����2�D��.��u���h,�"�K5,�
���#�@��H�R�X��3X��XvH��j24�������~4�y:L�Z���n��J��1���c�[�����U�
}E�]ja�1��f��te�Pe$���|�������q":,"���W��E�Y@��d)���'P/���P+v-���N��,,f[�AD�c�W�T ��`8��d7���Z��_Z���=h����T�!�A8�`����>��h������\]l�D��Yn,'�����Bf��R"kL!�� �v�*p<�6�1dv9�
G��Q-���C�R��S��
U�)��W/�I�(�O��bQ��-�\����s`�b���y*������Ql%J��d�Ri��
��p`�X%�M�(R0F�����$��tH"��$���b6��J�4����h��
�r],�@�s ��U�|�1�X/�Yc
�����k@d[B�6TId�9�Bq�XT��|LI���W
��E�rRi�8;��D�pC,���2b�\��`
c��}*� ����2��,��iKe6d�r�]���E�R�TE��kXR0����T�F��k�F�`����7�dh:������4O������5�q�1�X/�Yc
����
��R�a�C�M8N�Wa�Ta.Qa�ManJaGa�CaN@at^1F���ea�W�FE��Ja�P��/�df|3����L[aF�0sS��(�����ea
V��&���oa�X�H&��\`�M}a�X�t6���X��
;�0_4n�[��1M�i)_�\��LE�Y�Gy�l��Q�Ey�H��(B�rr��KP�@9�����!�d���`9'�_�*�TL�x��(����_9+fR<�XGqL�U��F�"�A�d�e�e�-�����A���q�	���9����HfF�D&C�A�/%�*Ka-3��I��HR)�D_.1��J$����*gLN��S� c'%.��a��Na�4x
L�V�t��1,P��/�^��t9�r��X+S�&�<e����Z$�*�!]�l�N�*���H;�Q���Ha,��K���HyGb}�����������x���%�@�'S.%������G�g�/����I?-��a���V9cr2D�";)�e 5t��g+�M��V�!�(MW���Q���C��b�>~�5!�i	���:�%pw��bv�����Fb�h"�Qn��^4&�,��p�"8�&�S��`B!���r��5\�B=���\*��2��<p9�r[i�"�v�a�W��[T�r�h��Z�x�jPi�+���B;��"�,��<�Y*��b���i�����C�x@
T�������C/�v�����<0n�"d�-��X�-���'x��T8<,�l�!4R��jRiP��g����J�N��|4��Tq�B+���
�h��F����"
8������?U1��O�J;��,��<�}�
��C�<�aj2�RA�����.W\/�v��l��<�y����|(���e�����Si04U���e���� �v�oQi0
��y[H,�iI���������f�C"��h8cT���e�eZ�X�4T����Hx"�"���(����v
@�X�a�#$�W�'����
�h�PJ��"?ZM��$
hh8>�"�8���N8�v�2)r�i�~X��9P*����*��v�a+2����E�x�.Q���CW����*.	�v��A�x@��"����Lb���%<	�����w�Jb���V4
��e�p��[I�	O��<����|?jV[d�S%���<8����"#*P�FY��i�hH^��Wye
9E
$ZJJ��)DS ��Q
xQi�+w���v���VD;�A4@�x��S]�<l�H�x�T���+U�0y���"�����<:*���Z��&[ Kl ��3���"x�#S��e�����M3�FnyMijV�D��BE�����T��^dX���J�)p�x�Qi��a�K���T����*���V�D�J�)u������Sh��C���_Q�BY�
K-[��v
j�M��fT���U����V���a	�v�A AU�Q�Na�urp����k*����Z�=[�LlA�eH<xXR<�����yR��E��T��h��[�K�(�x�Rs%���[=���*I���v�A`J�x���F�6�A|JU�J;� ���<lR�x�R�vU�J;� ��a�R.�����)�����h�8Q��Bq�Q
�<+DV l�\��S��O�Z�A�H�x�Q��U�Y����1"'*���X�J;� :�a���[k���<�o�T[]5�61�nc4M+����+�
�\�D!/�����J;� ��a�V�a���`���/�v�A8Vr�B�10U�0���8�J;���^���A4LU�[�1����Z�a���A\L�]���Be���[X5���d���J>*��d�%Ah��Ui��
��+\WP���r�
�[}��KK�xxRi��
�M�
�-�k�X��Z �	����,kQ��=��E����P�
!�P+[����(��xUSi�Z 	��r�S-(��x`Si�a�\�:xgSr�<����[U�;D�T--(�xvS���.�<�������p�v�A�V��Q8�v�A NUpN;��|�Z�Pf]ceB��S��22
�����vJ*(u���
�m�C�ai�Q[Z3�4�D`��@�Td������E9%��~e� ���(���
��������������^��r�U4]�����mFo�_l?����A��v�������G�����������W�Fo�^9����a9�����V�AmFo7���o��?:?;�A�?���a�wq����Vt�G�_�y��]���<�}/,�z�@(o��f�"zm\C'�������v�=�������e4<���2:��G%���������E��h��=��:���m�Gw���z�=����(8s�]��zf�V��'����r�fa�qwP���a����2�^�����O�����GC���LG^�x����/^�x���U,8����/^�x����/����D/^�x����/^�x����/^�x����/^��d����������Q�{����G��Q�{����G��Q�{����G��Q�{����G��Q�{����G��Q�{����G��Q�{����(������
�5�(U��;
<��}q��d���������t�*[����������������������������������������������������������������������V{��d�n�j�������GG�^��2:���vN�Ayv��Q����*�~��u��&����_w�?����N�x�p�em/�������z��a�x�Ut��<�!����������E?v�]-}vzO��2b��W'��*���4�����������}��(b�O�t�����*�\a��C0y��r;JE+_l����_������m�|���e4*���qG��������Q�yx������3m����Qy���q|,�������A�|\�����}t�ejO�&G���n�����<xPeGI�}#N��C-`��w���.�������^c+mG����������G4���}w�.J�a��D������rpz>2E���}4L�=�m�8��5���������t��L-M�v��z�tO@��������y�b������'�����
o
=���tGe�|�����������w�o&���Y�����:�z�D���;��L��b��:j��}�k������O�x��2J���������I	Z������>����=������l�&#Y�b-��u�9�ff�^�$�'�i���l#��}U�2��g����B���i	�����\��%z9���W[�>N?tG�����JT������U�bz�A��%��Bq �xB��.�Vc������Ig8DB��������#��i��0��F-�:&9��5�&�2.S�Q��I������W����F����@���n���Ow�7������E���v'����iG>4�b��M�7F����
Fn}=���x��/�wNF����Z�~nv��i����*���� a���/��w�=�YS;����(�)
�Q������������,�+&��������il�:�lS7�&��Ys��l)��Wq��/Ws�i�|�g��O��/NW(�u6(��� �=��>*�
?��
����p�2�O�~/0,G�g�s��B�O�����s�x���9�<b��|�z{�;�a�Q=�������3i�
���R�0a����U�&�8��"���Lf.�j�K�'�����������&�X����.5�1���j����[���ur��
�/*�����oZ|6��������G&���M��l���X����%}u�������q�vj���^����?�&u����O����I�[��W����W����.�����==G��96`�OG�h��(�
�R)���sz���k�����/�)�54�S���k�td�`�/�pg��I;��Y���S �������������2�sR�o�r��6�����[�s�.������69B���Wx��5�
g��$�2�g��/w8����	�xxRvz����d���;�m]f~��-�i&�[o=}PZ�a�X��x�8���>>������K�c�����6�;_s��7{o�p����r��3!��nnt��U������Ow����V4�����u{�-KD?v��F#�7���;����SlVNf�������ry�=_n�e�Kn����������x���@@��m�����iX6N�i�i�gk�f��g�^|�m�� �
�����;�@�E&W�L���^y0����G2�M�������������6���/����e����=����Y�~�����r�[���_kD�a9	hB�R��a�Y���=�����wo4��e������f��~�{4��:ma�x��O�vex~xX�G7�����!��vH|]��(���
�?=\@�D�_��5�"S�u�����[Qve�K�K��i�Z[Qs^����C�O���Fo�Q�}g�������+.��P�5s�������+si2���E\��y����K�[����� dW��G���`���:^6��/���|~���N]�d�<�+��5��|�^e��j�N��;�Z��;Q'�%���6���5�������:[-0i�R���G�f�]%��^����2��p6����W{;��Ec�����JW��=;�4�������x#��������Y
4�b�=��A�s��vO;�������[}�=S��{�b/
OMn��������c��c����}������[�5q���A��9��� �x��������v�!�	J��o7�>�>zd�����������J6k?����r �5ax�\ETmFo7�U�?���~�`b���Q�R9t�}���P���7��{������/>��������]��R���dr���s��$mF�����m	����x��A��-Id�|��s�@s��3��2m��^���_/������Fs��&�����.���	ZQ���g��#����7{�v�~,����/�=�����e�v����5����x�����5)A��?�V��n��*��%��w����[�Ev�I�e<+����Y~2��O_ik�K��'3���Dww�zVN��v~��m�X8����^T�0n�:_nl�~Y!:1�e�]����X^al��������mi��B{�j���{���bqTkOmO�m�������o��6�Jl���6�i�f�m����4��,������F��L��s��7�l��KN��C����y�q��L,���K5���	�V�%�0�E8�!3K�c�E��i���O�����/�t���5�����/!�9��jg��z|a���h�dN���[k��1s�Z'�,�����I�cy��[��}���a�"d��[�v^��f/�����4'��v�9\cN.�`}�Z6E�C#��fi�:~j�q��Tvj��\�L�?�G�5�}dkci>H�O{�����{��~y���`�P�cIUB��{�k���i����q�������)�'�������Rpp��+�P?���Y�y��A�:�Z���'�N���mr��n�!���L��W������j��V�����7L��W��.���m���F'<�����6\m[m���k��ejf%k�j���]�i����O���O�����#�\o�g~�s��!�L;����\����C���;v���8�~��g��|����g(�F�y+Z����y��IJnl��\��IJ�N�oBb���
�?B#�N�����|��~��cd�6���J���pt�q���1?�5�	S� `�Y^�����L:?����>3X���.�6�U�'��N����8m��c��p��;�+�7zKnj��&W���n��������F/��p�������d7����s���~���1�u��R���y9\��kY9t~8��O��5z���g�7��?����.M5��
��ay�|H�U�Y������]9z��n0p�����wp+��|���Vd��/������^�Y�w�\xj���-�[������k_�����N�o�?�v{�}���8z�f��}��:F��b����=.>m
�}�IN����pnJ3���;������*����N�����+s��\�G.�U�l�[i%z��4�4!M�T�<);?���`���i���,W������XKu��g���o�����fu��=����G9lI8jp�9Y<cR��s��^�y����w/^�9�N��3�N+Y�|�K+�����5�aw���o�����K\T����)��Q3��4&d�=�.���������WP��-U��������e�������]&8f��y��X��]������}�2^W��I�?������p��:����:g��G�?6V]{k|��N$W���O|��#��G�6�\:�l�R���C"u�r��G�=��C��H�d�r��h�Z.?�4s�`�������='��7�-��oEc��������6��-p��c>wO��<����4��gP��os�
V��?*OJsb����v������>��N:rt��'������rk[�����Y�o�������1�<�7'6���?=?|-�_*4�c�����A���R�>�lrk��dN�2���w��6���Zo�p���$�>L�����^/��s>
�w���w�M�?��}
�qfl+"Pc�c�C�Xy����{�����u���V��q����
^�>G�h�X��q8��=�$�� k�D�7���$����s�u�e�H;)\(+g�2�/�z��V���z[K�	�.��p�
�xj��6�s���iTz��������������	�8 �v���o������q�����I��WrY���vu����j������;B)$�:��mR
�I���hs"ek�q%W�:�����*�gE������/�hm�e�!R~�@�E��A�O�$X��_����\���s[����W���4�����|Pj3������yo���^�|��u8>���u9>�g�Y.[�SR���P�s��UR�S�dk�c������������H���[1*�,�"�Vt�����R�Z�8���j��;\�OO��5�G����������(~��;�}.w?p���sVv�}G��kIq}��Y�n������\z�H�0�z\��d�nQ}e��%/��}*�Z�:6��/�����$9~Kf�����o�#�����?F���xi%t�	9/i�X�vtoi�.����l�{�5���ve�=�������O�����f����/OENf#�[����7�e�^��tx<�7�����������o�s��E���0�Z��:�i�������OP�'��������[���f'7�g��'L��U,n[�{�K�Z��������Ntfy/�?�E�C~:9�I��3,k�(��	�������a�,��%)a�_k��N��8��p�\2o+l�6�a�?�JUI��	��&�2���H7�L�O'������%�?q��A����.��5��L�%��O�� s9��V�5�v�o�������z���t\�����#Bzw�|����]&Q!��L��XA�&%�c��t�|/m��eQ1������3����c�TB��/��?�������O:�x���H��vie�/���lbw�����p�_f�r���O2��vc������=��lX��l[�ftk�d���}���������z�2?��Y�e��uud�����'����sP���h/�qXK�y�|�/����n�p^/�u{e����t���
�73�kmLb�,h�.��$Zmk������OnT��D��T���$���������o��V@������]���g���������TF�������;����L�k_���	��K��%[|�^�
�A�C��^��rf3��8~�D�`re9~y��3w��H/�r�����<�*a=��G�"X.\�%`�H��{���[�<�3��}������=�^v�k>�1����������������z����9���_�[�~}������7�������;�'��}��M�6lq�?����:p�/������.��y��WS}���o5~U����Z��������l�����R�������5���I5���F�_���~�o7���o�E��������7���k{����7����/-��i��!"�z�S����J�L��q���/3�F��i���L��������O_��(~�������K|%��/���k)Vz1�����/�?�[&~�����M?��&��'|���u�~�A|����J�@�(�$O�p.������1�Tx�8�g����>8D^���#��N�������m;o��[y��}7,�;�{w��z<�l\J����H������
T���4����L[�����R��-K�����w����/�w�nE�8x����2����-��W���M6���:�����A���Q�q���6���/��^��#4���y}s�?�L��<M�L�F���KV'	7q}]-6����V���Y{x��o*��9>x�?���!X?;��`��������,�Yy���{���Yg0,��B���z ��]��n�k����G�������	��|O��'���s��\��iyj��8(O.���3^z9fl���{�������b{�����<3�����~����}Z(���������ah���zm�<������W����Qy,���pd;���<�>>Ct��i}���?�u���i���V����h���+A���o��{Wb6O�!��2������m/�I������X�ctm����@3�~�E��%�}��p�a+R�0�6��zw>��������m+����K�a���[�G��������e�^|�~�z�h�����p�ny�z4����&w�\�\�.x��v����K�>�+p*�7��:q����a|Xm^Q���|vV������<���4a�g%^���{�q�����~���&���P�"��C$���_��H�]~������iw*��l��_I�������?�Zq�k3��q�0������6A��LDn�n���\����Kl���2x:������{��������������Y������:�[�}�g��?��������XS�P�����yS��^=���]�4+a�����r�Xl3�����vO_�x���c����K����?�l����*��}�5�
�n��g�����t��j���}6�����I4�h4S��lX��>NwK`�z^o������*��Itb7uV'���R�
5�����m���=�mg�t��V�����#���w9<=�AzaU�N=����S��X�����nL�ly6���}�:aO�-����`���a�NA�����V��B�7��bs�V	�����/�/}�h��9�����������P��[7�ww_�N�f���������a�����Ow�~K���oi���G��n�9��l.��j���o���1|��p��.�K�>��f��[���&��~�]q�����g09�����.�����R���O������oP��,�s_��=��������S�����N[w��X���K)l2��r~b���`�j=�CW��M��S���<������7����!����i/�;J��z5�w�����Qw�^#��A���~����z��%Q�w����Q����qc|I�I��;���>����C�&0l��p�;vP��K�8�������\���5oyT�E�R���Nq�r
�15���L��E�6����KZ�G�}%���c�����u�T0��@���+�u����5��}=�[��DY��+]��B���hO-���C]����?��3�:\�r��
o{hnX�]`��������������
]Wh�]������{���h�;��f���F��}&����M9�Rv����
*��	�Nx��+�I-�7n��{���U��[����m�\mh��u���;����Fzd������g�����0|}���7_���.��������8������8���q�5��}<cj�U�FSZ��S;.0�0��h����w��v�p��{�����g�4����!��� �$d�������I���	�������������P��|�,�X��4U{k��p�"���G����z�"A����\���^u��p��I1�^��{�3�#'H������U�=8P���=S��h��?����/�;��'�jO�w���I�*]}~x8Wtu�CwX]!x���n������Z�����i��M��H��	�w������.W��J7�����h���U��|gLR��I� ���Fo�EI�mW�?�U�}S���7���mlhS�W;���W�y8�9�
�v���3�|"�;�?�lLO\���I�m��*}h����t�``�{�g�
�'}����h��.��7�{o�v�{�W�^m��bA\�������W:aq�pDCM�Fe/������:�6�q=�
�D�����^&(c�6�5���3���������_��4y�Y��&!�)�-�l��\x��W�����������wk���9�y�A��]��@L9?���.n����_a��3,���DB� ��Fl�<�	����&�����y�?^�������?mT������_}���I�����;K&�������{������t��o�W���v��
& ��]����J�O���!�����e������F
*�l^>����T>��TN�1�+�Y��i����L�j���`�|_��:A��?������,?YL�!�Ma�	6��:�&�����=�Hu��L~������4!T'&�u��W�m��f����-���?���X��ct>�]izG!�������8�6��]�O����y����/�+GJ4�tL����o~���jNg����������v��8�� �� +����k���n��������������F�!����d����^r�[%����=���+�a&���y7z��!��Xb|�����,���`L������.����Mv���>��?1a����'�j~��!�a���>a����q�������4�{�d�&I�����8'=���J�	7��,1U��j��>F������=z�'�n��oJ��g.:���K���jk����&�����Wo�S0���r�!�y<yi�����5���O����48��Y���>�'KJ��gV=��}`��j��gi�I>����Z�{�������%f�j���<�rpJ�<	����p������s~2������ ��q�@hWb���_O�G��l�h
������]gg}88|�m���n�{k��=�����i+��8h�GY��1�T��E��&��5oY�n��=��f����v��~���yr6Qy������������T#X�8=��v{L+�nG��������X����ZF��Th���/�����[?�V���T~���������C.;���'���A:�/G����j:�<x8��~���_���e�Fm��	����Va����:�W��
�������a���H�$�����^�������d�JC��ar�d�2?8��h��'������5I�nJm����f���S6m�uK1���?���My������#5=r�����F�m9�O�e���������a��Fo��,�/��|
0009-wal_decoding-design-document-v2.4-and-snapshot-build.patch.gzapplication/x-patch-gzipDownload
0010-wal_decoding-Initial-cut-at-sgml-docs-section.patch.gzapplication/x-patch-gzipDownload
0011-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gzapplication/x-patch-gzipDownload
0012-slot-hack-up-pg_receivexlog-support.patch.gzapplication/x-patch-gzipDownload
#2Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#1)
Re: Changeset Extraction v7.0 (was logical changeset generation)

This 0001 patch, to log running transactions more frequently, has been
pending for a long time now, and I haven't heard any objections, so
I've gone ahead and committed that part.

...Robert

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#1)
Re: Changeset Extraction v7.0 (was logical changeset generation)

Review of patch 0002:

- I think you should just regard ReplicationSlotCtlLock as protecting
the "name" and "active" flags of every slot. ReplicationSlotCreate()
would then not need to mess with the spinlocks at all, and
ReplicationSlotAcquire and ReplicationSlotDrop get a bit simpler too I
think. Functions like ReplicationSlotsComputeRequiredXmin() can
acquire this lock in shared mode and only lock the slots that are
actually active, instead of all of them.

- If you address /* FIXME: apply sanity checking to slot name */, then
I think that also addresses /* XXX: do we want to use truncate
identifier instead? */. In other words, let's just error out if the
name is too long. I'm not sure what other sanity checking is needed
here; maybe just restrict it to 7-bit characters to avoid problems
with encodings for individual databases varying.

- ReplicationSlotAcquire probably needs to ignore slots that are not active.

- ReplicationSlotAcquire should be tweaked so that the code that holds
the spinlock is more self-contained. If you adopt the above-proposed
recasting of ReplicationSlotCtlLock, then the part that holds the
spinlock can probably look like this: SpinLockAcquire(&slot->mutex);
was_active = slot->active; slot->active = true;
SpinLockRelease(&slot->mutex), which looks quite a bit safer.

- If there's a coding rule that slot->database can't be changed while
the slot is active, then the check to make sure that the user isn't
trying to bind to a slot with a mis-matching database could be done
before the code described in the previous point, avoiding the need to
go back and release the resource.

- I think the critical section in ReplicationSlotDrop is bogus. If
DeleteSlot() fails, we scarcely need to PANIC. The slot just isn't
gone.

- cancel_before_shmem_exit is only guaranteed to remove the
most-recently-added callback.

- Why does ReplicationSlotsComputeRequiredXmin() need to hold
ProcArrayLock at all?

- ReplicationSlotsComputeRequiredXmin scarcely needs to hold the
spinlock while it does all of those gyrations. It can just acquire
the spinlock, copy the three fields needed into local variables, and
release the spinlock. The rest can be worked out afterwards.
Similarly in ReplicationSlotsComputeRequiredXmin.

- A comment in KillSlot wonders whether locking is required. I say
yes. It's safe to take lwlocks and spinlocks during shmem exit, and
failing to do so seems like a recipe for subtle corner-case bugs.

- pg_get_replication_slots() wonders what permissions we require. I
don't know that any special permissions are needed here; the data
we're exposing doesn't appear to be sensitive. Unless I'm missing
something?

- PG_STAT_GET_LOGICAL_DECODING_SLOTS_COLS has a leftover "logical" in its name.

- There seems to be no interface to acquire or release slots from
either SQL or the replication protocol, nor any way for a client of
this code to update its slot details. The value of
catalog_xmin/data_xmin vs. effective_catalog_xmin/effective_data_xmin
is left to the imagination.

...Robert

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#4Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#3)
Re: Changeset Extraction v7.0 (was logical changeset generation)

Hi,

On 2014-01-15 13:28:25 -0500, Robert Haas wrote:

- I think you should just regard ReplicationSlotCtlLock as protecting
the "name" and "active" flags of every slot. ReplicationSlotCreate()
would then not need to mess with the spinlocks at all, and
ReplicationSlotAcquire and ReplicationSlotDrop get a bit simpler too I
think. Functions like ReplicationSlotsComputeRequiredXmin() can
acquire this lock in shared mode and only lock the slots that are
actually active, instead of all of them.

I first thought you meant that we should get rid of the spinlock, but
after rereading I think you just mean that ->name, ->active, ->in_use
are only allowed to change while holding the lwlock exclusively so we
don't need to spinlock in those cases? If so, yes, that works for me.

- If you address /* FIXME: apply sanity checking to slot name */, then
I think that also addresses /* XXX: do we want to use truncate
identifier instead? */. In other words, let's just error out if the
name is too long. I'm not sure what other sanity checking is needed
here; maybe just restrict it to 7-bit characters to avoid problems
with encodings for individual databases varying.

Yea, erroring out seems like a good idea. But I think we need to
restrict slot names a bit more than that, given they are used as
filenames... We could instead name the files using the slot's offset,
but I'd prefer to not go that route.

- ReplicationSlotAcquire probably needs to ignore slots that are not active.

Not sure what you mean? If the slot isn't in_use we'll skip it in the loop.

- If there's a coding rule that slot->database can't be changed while
the slot is active, then the check to make sure that the user isn't
trying to bind to a slot with a mis-matching database could be done
before the code described in the previous point, avoiding the need to
go back and release the resource.

I don't think slot->database should be allowed to change at all...

- I think the critical section in ReplicationSlotDrop is bogus. If
DeleteSlot() fails, we scarcely need to PANIC. The slot just isn't
gone.

Well, if delete slot fails, we don't really know at which point it
failed which means that the on-disk state might not correspond to the
in-memory state. I don't see a point in adding code trying to handle
that case correctly...

- cancel_before_shmem_exit is only guaranteed to remove the
most-recently-added callback.

Yea :(. I think that's safe for the current usages but seems mighty
fragile... Not sure what to do about it. Just register KillSlot once and
keep it registered?

- Why does ReplicationSlotsComputeRequiredXmin() need to hold
ProcArrayLock at all?

There's reasoning, but I just noticed that it's basis might be flawed
anyway :(.
When starting changeset extraction in a new slot we need to guarantee
that we only start decoding records we know the catalog tuples haven't
been removed for.
So, when creating the slot I've so far done a GetOldestXmin() and used
that to check against xl_running_xact->oldestRunningXid. But
GetOldestXmin() can go backwards...

I'll think a bit and try to simplify this.

- ReplicationSlotsComputeRequiredXmin scarcely needs to hold the
spinlock while it does all of those gyrations. It can just acquire
the spinlock, copy the three fields needed into local variables, and
release the spinlock. The rest can be worked out afterwards.
Similarly in ReplicationSlotsComputeRequiredXmin.

Yea, will change.

- A comment in KillSlot wonders whether locking is required. I say
yes. It's safe to take lwlocks and spinlocks during shmem exit, and
failing to do so seems like a recipe for subtle corner-case bugs.

I agree that it's safe to use spinlocks, but lwlocks? What if we are
erroring out while holding an lwlock? Code that runs inside a
TransactionCommand is protected against that, but if not ProcKill()
which invokes LWLockReleaseAll() runs pretty late in the teardown
process...

- pg_get_replication_slots() wonders what permissions we require. I
don't know that any special permissions are needed here; the data
we're exposing doesn't appear to be sensitive. Unless I'm missing
something?

I don't see a problem either, but it seems others have -
pg_stat_replication only displays minor amounts of information if one
doesn't have the replication privilege... Not sure what the reasoning
there is, and whether it applies here as well.

- There seems to be no interface to acquire or release slots from
either SQL or the replication protocol, nor any way for a client of
this code to update its slot details.

I don't think either ever needs to do that - START_TRANSACTION SLOT slot
...; and decoding_slot_*changes will acquire/release for them while
active. What would the usecase be to allow them to be acquired from SQL?

The slot details get updates by the respective replication code. For
streaming rep, that should happen via reply and feedback messages. For
changeset extraction it happens when LogicalConfirmReceivedLocation() is
called; the walsender interface does that using reply messages, the SQL
interface calls it when finished (unless you use the _peek_ functions).

The value of
catalog_xmin/data_xmin vs. effective_catalog_xmin/effective_data_xmin
is left to the imagination.

There's a comment about them in a following patch. Basically the reason
is that for changeset extraction we cannot adjust the in-memory value
before we know the changed slot status is safely synced to
disk. Otherwise a client could restart streaming at a LSN where the
corresponding catalog details are gone since it's not prevented by the
slot anymore.

That could be done by just holding some lock forbidding the global xmin
value to be recomputing while writing to disk, but that seems awfully
heavy-handed. So the protocol is:
1) update ->catalog_xmin to the new xmin,
2) sync slot to disk
3) set ->effective_catalog_xmin = ->catalog_xmin
4) ReplicationSlotsComputeRequiredXmin()

Since ComputeRequiredXmin() only looks at effective_catalog_xmin that
guarantees that the global xmin horizon doesn't increase before the the
slot has been synced to disk. If we crash after 2,
StartupReplicationSlots() simply sets effective_catalog_xmin =
catalog_xmin, we know it's safely on disk now since we've just read it
from there.

Thanks for committing 0001!

Regards,

Andres

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#4)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On Wed, Jan 15, 2014 at 3:39 PM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-01-15 13:28:25 -0500, Robert Haas wrote:

- I think you should just regard ReplicationSlotCtlLock as protecting
the "name" and "active" flags of every slot. ReplicationSlotCreate()
would then not need to mess with the spinlocks at all, and
ReplicationSlotAcquire and ReplicationSlotDrop get a bit simpler too I
think. Functions like ReplicationSlotsComputeRequiredXmin() can
acquire this lock in shared mode and only lock the slots that are
actually active, instead of all of them.

I first thought you meant that we should get rid of the spinlock, but
after rereading I think you just mean that ->name, ->active, ->in_use
are only allowed to change while holding the lwlock exclusively so we
don't need to spinlock in those cases? If so, yes, that works for me.

Yeah, that's about what I had in mind.

- If you address /* FIXME: apply sanity checking to slot name */, then
I think that also addresses /* XXX: do we want to use truncate
identifier instead? */. In other words, let's just error out if the
name is too long. I'm not sure what other sanity checking is needed
here; maybe just restrict it to 7-bit characters to avoid problems
with encodings for individual databases varying.

Yea, erroring out seems like a good idea. But I think we need to
restrict slot names a bit more than that, given they are used as
filenames... We could instead name the files using the slot's offset,
but I'd prefer to not go that route.

OK. Well, add some code, then. :-)

- ReplicationSlotAcquire probably needs to ignore slots that are not active.

Not sure what you mean? If the slot isn't in_use we'll skip it in the loop.

active != in_use.

I suppose your point is that the slot can't be in_use if it's not also
active. Maybe it would be better to get rid of active/in_use and have
three states: REPLSLOT_CONNECTED, REPLSLOT_NOT_CONNECTED,
REPLSLOT_FREE. Or something like that.

- If there's a coding rule that slot->database can't be changed while
the slot is active, then the check to make sure that the user isn't
trying to bind to a slot with a mis-matching database could be done
before the code described in the previous point, avoiding the need to
go back and release the resource.

I don't think slot->database should be allowed to change at all...

Well, it can if the slot is dropped and a new one created.

- I think the critical section in ReplicationSlotDrop is bogus. If
DeleteSlot() fails, we scarcely need to PANIC. The slot just isn't
gone.

Well, if delete slot fails, we don't really know at which point it
failed which means that the on-disk state might not correspond to the
in-memory state. I don't see a point in adding code trying to handle
that case correctly...

Deleting the slot should be an atomic operation. There's some
critical point before which the slot will be picked up by recovery and
after which it won't. You either did that operation, or not, and can
adjust the in-memory state accordingly.

- cancel_before_shmem_exit is only guaranteed to remove the
most-recently-added callback.

Yea :(. I think that's safe for the current usages but seems mighty
fragile... Not sure what to do about it. Just register KillSlot once and
keep it registered?

Yep. Use a module-private flag to decide whether it needs to do anything.

- A comment in KillSlot wonders whether locking is required. I say
yes. It's safe to take lwlocks and spinlocks during shmem exit, and
failing to do so seems like a recipe for subtle corner-case bugs.

I agree that it's safe to use spinlocks, but lwlocks? What if we are
erroring out while holding an lwlock? Code that runs inside a
TransactionCommand is protected against that, but if not ProcKill()
which invokes LWLockReleaseAll() runs pretty late in the teardown
process...

Hmm. I guess it'd be fine to decide that a connected slot can be
marked not-connected without the lock. I think you'd want a rule that
a slot can't be freed except when it's not-connected; otherwise, you
might end up marking the slot not-connected after someone else had
already recycled it for an unrelated purpose (drop slot, create new
slot).

- There seems to be no interface to acquire or release slots from
either SQL or the replication protocol, nor any way for a client of
this code to update its slot details.

I don't think either ever needs to do that - START_TRANSACTION SLOT slot
...; and decoding_slot_*changes will acquire/release for them while
active. What would the usecase be to allow them to be acquired from SQL?

My point isn't so much about SQL as that with just this patch I don't
see any way for anyone to ever acquire a slot for anything, ever. So
I think there's a piece missing, or three.

The slot details get updates by the respective replication code. For
streaming rep, that should happen via reply and feedback messages. For
changeset extraction it happens when LogicalConfirmReceivedLocation() is
called; the walsender interface does that using reply messages, the SQL
interface calls it when finished (unless you use the _peek_ functions).

Right, but where is this code? I don't see this updating the reply
and feedback message processing code to touch slots. Did I miss that?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#5)
Re: Changeset Extraction v7.0 (was logical changeset generation)

Hi,

On 2014-01-16 09:34:51 -0500, Robert Haas wrote:

- ReplicationSlotAcquire probably needs to ignore slots that are not active.

Not sure what you mean? If the slot isn't in_use we'll skip it in the loop.

active != in_use.

I suppose your point is that the slot can't be in_use if it's not also
active.

Yes. There's asserts to that end...

Maybe it would be better to get rid of active/in_use and have
three states: REPLSLOT_CONNECTED, REPLSLOT_NOT_CONNECTED,
REPLSLOT_FREE. Or something like that.

Hm. Color me unenthusiastic. If you feel strongly I can change it, but
otherwise not.

- If there's a coding rule that slot->database can't be changed while
the slot is active, then the check to make sure that the user isn't
trying to bind to a slot with a mis-matching database could be done
before the code described in the previous point, avoiding the need to
go back and release the resource.

I don't think slot->database should be allowed to change at all...

Well, it can if the slot is dropped and a new one created.

Well. That obviously requires the lwlock to be acquired...

- I think the critical section in ReplicationSlotDrop is bogus. If
DeleteSlot() fails, we scarcely need to PANIC. The slot just isn't
gone.

Well, if delete slot fails, we don't really know at which point it
failed which means that the on-disk state might not correspond to the
in-memory state. I don't see a point in adding code trying to handle
that case correctly...

Deleting the slot should be an atomic operation. There's some
critical point before which the slot will be picked up by recovery and
after which it won't. You either did that operation, or not, and can
adjust the in-memory state accordingly.

I am not sure I understand that point. We can either update the
in-memory bit before performing the on-disk operations or
afterwards. Either way, there's a way to be inconsistent if the disk
operation fails somewhere inbetween (it might fail but still have
deleted the file/directory!). The normal way to handle that in other
places is PANICing when we don't know so we recover from the on-disk
state.
I really don't see the problem here? Code doesn't get more robust by
doing s/PANIC/ERROR/, rather the contrary. It takes extra smarts to only
ERROR, often that's not warranted.

- A comment in KillSlot wonders whether locking is required. I say
yes. It's safe to take lwlocks and spinlocks during shmem exit, and
failing to do so seems like a recipe for subtle corner-case bugs.

I agree that it's safe to use spinlocks, but lwlocks? What if we are
erroring out while holding an lwlock? Code that runs inside a
TransactionCommand is protected against that, but if not ProcKill()
which invokes LWLockReleaseAll() runs pretty late in the teardown
process...

Hmm. I guess it'd be fine to decide that a connected slot can be
marked not-connected without the lock.

I now acquire the spinlock since that has to work, or we have much worse
problems... That guarantees that other backends see the value as well.

I think you'd want a rule that
a slot can't be freed except when it's not-connected; otherwise, you
might end up marking the slot not-connected after someone else had
already recycled it for an unrelated purpose (drop slot, create new
slot).

Yea, that rule is there. Otherwise we'd get in great trouble.

- There seems to be no interface to acquire or release slots from
either SQL or the replication protocol, nor any way for a client of
this code to update its slot details.

I don't think either ever needs to do that - START_TRANSACTION SLOT slot
...; and decoding_slot_*changes will acquire/release for them while
active. What would the usecase be to allow them to be acquired from SQL?

My point isn't so much about SQL as that with just this patch I don't
see any way for anyone to ever acquire a slot for anything, ever. So
I think there's a piece missing, or three.

The slot is acquired by code using the slot. So when START_TRANSACTION
SLOT ... (in contrast to a START_TRANSACTION without SLOT) is sent,
walsender.c does an ReplicationSlotAcquire(cmd->slotname) in
StartReplication() and releases it after it has finished.

The slot details get updates by the respective replication code. For
streaming rep, that should happen via reply and feedback
messages. For changeset extraction it happens when
LogicalConfirmReceivedLocation() is called; the walsender interface
does that using reply messages, the SQL interface calls it when
finished (unless you use the _peek_ functions).

Right, but where is this code? I don't see this updating the reply
and feedback message processing code to touch slots. Did I miss that?

It's in "wal_decoding: logical changeset extraction walsender interface"
currently :(. Splitting the streaming replication part of that patch off
isn't easy...

Greetings,

Andres Freund

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Craig Ringer
craig@2ndquadrant.com
In reply to: Robert Haas (#3)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On 01/16/2014 02:28 AM, Robert Haas wrote:

- If you address /* FIXME: apply sanity checking to slot name */, then
I think that also addresses /* XXX: do we want to use truncate
identifier instead? */. In other words, let's just error out if the
name is too long. I'm not sure what other sanity checking is needed
here; maybe just restrict it to 7-bit characters to avoid problems
with encodings for individual databases varying.

It's a common misunderstanding that restricting to 7-bit solves encoding
issues.

Thanks to the joy that is SHIFT_JIS, we must also disallow the backslash
and tilde characters.

Anybody who actually uses SHIFT_JIS as an operational encoding, rather
than as an input/output encoding, is into pain and suffering. Personally
I'd be quite happy to see it supported as client_encoding, but forbidden
as a server-side encoding. That's not the case right now - so since we
support it, we'd better guard against its quirks.

slotnames can't be regular identifiers, because they might contain chars
not valid in another DB's encoding. So lets just restrict them to
[a-zA-Z0-9_ -] and be done with it.

--
Craig Ringer http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#8Robert Haas
robertmhaas@gmail.com
In reply to: Craig Ringer (#7)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On Thu, Jan 16, 2014 at 10:15 PM, Craig Ringer <craig@2ndquadrant.com> wrote:

Anybody who actually uses SHIFT_JIS as an operational encoding, rather
than as an input/output encoding, is into pain and suffering. Personally
I'd be quite happy to see it supported as client_encoding, but forbidden
as a server-side encoding. That's not the case right now - so since we
support it, we'd better guard against its quirks.

I think that *is* the case right now. pg_wchar.h sayeth:

/* followings are for client encoding only */
PG_SJIS, /* Shift JIS
(Winindows-932) */
PG_BIG5, /* Big5 (Windows-950) */
PG_GBK, /* GBK (Windows-936) */

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#9Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#6)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On Thu, Jan 16, 2014 at 9:54 AM, Andres Freund <andres@2ndquadrant.com> wrote:

Maybe it would be better to get rid of active/in_use and have
three states: REPLSLOT_CONNECTED, REPLSLOT_NOT_CONNECTED,
REPLSLOT_FREE. Or something like that.

Hm. Color me unenthusiastic. If you feel strongly I can change it, but
otherwise not.

I found the active/in_use distinction confusing; I thought one
three-state flag rather than two Booleans might be clearer. But I
might be able to just suck it up.

- If there's a coding rule that slot->database can't be changed while
the slot is active, then the check to make sure that the user isn't
trying to bind to a slot with a mis-matching database could be done
before the code described in the previous point, avoiding the need to
go back and release the resource.

I don't think slot->database should be allowed to change at all...

Well, it can if the slot is dropped and a new one created.

Well. That obviously requires the lwlock to be acquired...

Right, so the point of this comment originally was you had some logic
that could be moved sooner to avoid having to undo so much on a
failure.

- I think the critical section in ReplicationSlotDrop is bogus. If
DeleteSlot() fails, we scarcely need to PANIC. The slot just isn't
gone.

Well, if delete slot fails, we don't really know at which point it
failed which means that the on-disk state might not correspond to the
in-memory state. I don't see a point in adding code trying to handle
that case correctly...

Deleting the slot should be an atomic operation. There's some
critical point before which the slot will be picked up by recovery and
after which it won't. You either did that operation, or not, and can
adjust the in-memory state accordingly.

I am not sure I understand that point. We can either update the
in-memory bit before performing the on-disk operations or
afterwards. Either way, there's a way to be inconsistent if the disk
operation fails somewhere inbetween (it might fail but still have
deleted the file/directory!). The normal way to handle that in other
places is PANICing when we don't know so we recover from the on-disk
state.
I really don't see the problem here? Code doesn't get more robust by
doing s/PANIC/ERROR/, rather the contrary. It takes extra smarts to only
ERROR, often that's not warranted.

People get cranky when the database PANICs because of a filesystem
failure. We should avoid that, especially when it's trivial to do so.
The update to shared memory should be done second and should be set
up to be no-fail.

The slot details get updates by the respective replication code. For
streaming rep, that should happen via reply and feedback
messages. For changeset extraction it happens when
LogicalConfirmReceivedLocation() is called; the walsender interface
does that using reply messages, the SQL interface calls it when
finished (unless you use the _peek_ functions).

Right, but where is this code? I don't see this updating the reply
and feedback message processing code to touch slots. Did I miss that?

It's in "wal_decoding: logical changeset extraction walsender interface"
currently :(. Splitting the streaming replication part of that patch off
isn't easy...

Ack. I was hoping to work through these patches one at a time, but
that's not going to work if they are interdependent to that degree.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#10Craig Ringer
craig@2ndquadrant.com
In reply to: Robert Haas (#8)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On 01/18/2014 09:31 PM, Robert Haas wrote:

On Thu, Jan 16, 2014 at 10:15 PM, Craig Ringer <craig@2ndquadrant.com> wrote:

Anybody who actually uses SHIFT_JIS as an operational encoding, rather
than as an input/output encoding, is into pain and suffering. Personally
I'd be quite happy to see it supported as client_encoding, but forbidden
as a server-side encoding. That's not the case right now - so since we
support it, we'd better guard against its quirks.

I think that *is* the case right now. pg_wchar.h sayeth:

/* followings are for client encoding only */
PG_SJIS, /* Shift JIS
(Winindows-932) */
PG_BIG5, /* Big5 (Windows-950) */
PG_GBK, /* GBK (Windows-936) */

Perfect - that makes ASCII-only just fine, IMO.

--
Craig Ringer http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#11Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#8)
Re: Changeset Extraction v7.0 (was logical changeset generation)

Robert Haas <robertmhaas@gmail.com> writes:

On Thu, Jan 16, 2014 at 10:15 PM, Craig Ringer <craig@2ndquadrant.com> wrote:

Anybody who actually uses SHIFT_JIS as an operational encoding, rather
than as an input/output encoding, is into pain and suffering. Personally
I'd be quite happy to see it supported as client_encoding, but forbidden
as a server-side encoding. That's not the case right now - so since we
support it, we'd better guard against its quirks.

I think that *is* the case right now.

SHIFT_JIS is not and never will be allowed as a server encoding,
precisely because it has multi-byte characters of which some bytes could
be taken for ASCII. The same is true of our other client-only encodings.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#12Stefan Kaltenbrunner
stefan@kaltenbrunner.cc
In reply to: Robert Haas (#8)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On 01/18/2014 02:31 PM, Robert Haas wrote:

On Thu, Jan 16, 2014 at 10:15 PM, Craig Ringer <craig@2ndquadrant.com> wrote:

Anybody who actually uses SHIFT_JIS as an operational encoding, rather
than as an input/output encoding, is into pain and suffering. Personally
I'd be quite happy to see it supported as client_encoding, but forbidden
as a server-side encoding. That's not the case right now - so since we
support it, we'd better guard against its quirks.

I think that *is* the case right now. pg_wchar.h sayeth:

/* followings are for client encoding only */
PG_SJIS, /* Shift JIS
(Winindows-932) */

while you have that file open: s/Winindows-932/Windows-932 maybe?

Stefan

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#13Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#9)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On 2014-01-18 08:35:47 -0500, Robert Haas wrote:

I am not sure I understand that point. We can either update the
in-memory bit before performing the on-disk operations or
afterwards. Either way, there's a way to be inconsistent if the disk
operation fails somewhere inbetween (it might fail but still have
deleted the file/directory!). The normal way to handle that in other
places is PANICing when we don't know so we recover from the on-disk
state.
I really don't see the problem here? Code doesn't get more robust by
doing s/PANIC/ERROR/, rather the contrary. It takes extra smarts to only
ERROR, often that's not warranted.

People get cranky when the database PANICs because of a filesystem
failure. We should avoid that, especially when it's trivial to do so.
The update to shared memory should be done second and should be set
up to be no-fail.

I don't see how that would help. If we fail during unlink/rmdir, we
don't really know at which point we failed. Just keeping the slot in
memory, won't help us in any way - we'll continue to reserve resources
while the slot is half-gone.
I don't think trying to handle errors we don't understand and we don't
routinely expect actually improves robustness. It just leads to harder
to diagnose errors. It's not like the cases here are likely to be caused
by anthything but severe admin failure like removing the write
permissions of the postgres directory while the server is running. Or do
you see more valid causes?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#14Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#13)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On Wed, Jan 22, 2014 at 9:48 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-01-18 08:35:47 -0500, Robert Haas wrote:

I am not sure I understand that point. We can either update the
in-memory bit before performing the on-disk operations or
afterwards. Either way, there's a way to be inconsistent if the disk
operation fails somewhere inbetween (it might fail but still have
deleted the file/directory!). The normal way to handle that in other
places is PANICing when we don't know so we recover from the on-disk
state.
I really don't see the problem here? Code doesn't get more robust by
doing s/PANIC/ERROR/, rather the contrary. It takes extra smarts to only
ERROR, often that's not warranted.

People get cranky when the database PANICs because of a filesystem
failure. We should avoid that, especially when it's trivial to do so.
The update to shared memory should be done second and should be set
up to be no-fail.

I don't see how that would help. If we fail during unlink/rmdir, we
don't really know at which point we failed.

This doesn't make sense to me. unlink/rmdir are atomic operations.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#15Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#1)
12 attachment(s)
Re: Changeset Extraction v7.1

Hi,

Attached is v7.1 of the patchset with (among others) the following
changes:
* rebase to master
* split the slot support for streaming replication into a separate
patch, early in the series
* slot names are now limited to /[a-z0-9_]{1,NAMEDATALEN-1}/
* computation of the initial xmin for changeset extraction is now done
with an extra routine getting rid of races around GetOldestXmin()
going forwards and then backwards and getting rid of an additional
parameter to GetOldestXmin().
* slot locking is rejiggered according to Robert's suggestions
* comment improvements
* sgml documentation improvements
* ...

I think sgml the documentation is in a reasonable shape now, I'd
appreciate somebody else having a look. I think a bit more effort is
required in protocol.sgml.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0008-wal_decoding-test_decoding-Add-a-simple-decoding-mod.patch.gzapplication/x-patch-gzipDownload
0009-wal_decoding-design-document-v2.4-and-snapshot-build.patch.gzapplication/x-patch-gzipDownload
���R0009-wal_decoding-design-document-v2.4-and-snapshot-build.patch�[is7���_���W�x��a�k�BK����H�:)�����Ds0���j��>���I�G�Ub����������$�����{�q����R�g����'G=����d��=?����g�"������S��?��E�����0�S�����c_����O2���[�_��8�����o�Cq�<L����������h�������O�e��zxw���������?��K� ���t0���xy��L,��C�-���\���!�y���X���5�v�!t�u���W��M�<<�I�
�)>��������N�1��A=?�M?��w!��$����8���t6��
O/F������7g��jD�p_T�?���L�S��3�b�RZR?i�6��*H@D��X}|x�l����N�h��d"��i�	��
A��bp#VKfI��F��#��:�������#�]_-�q�
������'��oA�i�O?5��n{��[�$�����K�K0��s�P!��r�����)n�} ;q��lJF���x�|�b6,�>���\������b2g[x�&��L��Y2�fI�f�-����r����3���*�A8�n+:^5� ��8��4�s�	|�����]��"-��Ou&��y(q��l%�Jd� �sw�X)_c�$������X�$����r&3��_�c3�$��J�UI��d�x�w37��.}�2o���<�!�4���A4��v�$g��P�r,-c�dX�RM�&��>��,�f"��=�c��@@m�=ad�i�m����H�u�-�z�KfRLU�R��� =O�r]�
����<\��4�8I�	v�����aq�8\	�-f����#Y�������2BjV$J�6���2@x�0����k9�A��K�`�)G'�5H��2���,�{�&��*��s��I�C�BZ�t����/�u�A�C3���N+r�R%$�d����P�S�P@�_�5,+��R#>@��@)�OY����[h�L�Y�����b���,���n��,���#�v�t����r����%��?���O;@���Ni�U������:�u�����R����a��?:�o%��d�^@'XgaJ:�Lbo%�<%VZUT03�"�A�����}5���)�N"(�K�A����VkH�s��!�*9%:�qb'����Q�=1�h;��di���8X�`6�A��.8�R�$f}��X�
�"Z�2!EUi���|��4p(�l^?��c�d���&�:== ��c���AaL�
eB�ZWB3���$v;�������L�W�|:���pl'OIIy��H�!�_��(����Y���d���m��m�lU[	/OS���
��=`��YH�������MLmt'7����-��0�WXg�����IA�J�B������6�l(�
�W�G���X�������#0
bHB��3�"_���	�Y�	�#�?�^�V��s�$hU�wW�r p"xJ�$��%~��n��x��@QDr�Xw|�^�����|O`jfNoij4���0n'c���q��Is������f��hz	H����y�L�|�7���B�tH��<C��$O�����K@Dl��
0;�`������/�5�%����7�ETd9p�^T-�zY�`2
("�H�ad�7�:�L0�$ri����^%� 80���������18e�D������ flM;]���ll��<�5i��o
m��|Q��[,9Q�gp��Q���f�A0�TiFx���L�&�~��m�9��D��!|nm��F�h����?�����ZX�E���_0�C�}���#E�GcL�,j�o�` 2��T�/�����CrE��hU�h	{�'L\�����]��W�7K���n@�*���T1�05<�,:�~S0����S���>s:3�u{�PJ��G�������jS���+����>C2A&�����,�:�en�%�`�������d��2.O(�c���)���P��z������r��:��r#�a�qH�������x}&����	e��9� [A�����pB�soY����IQ���
���33904 ��s�l���2I����}�f����P�q��S�X_�S�Jz(*���,E�NG��Z��:�c��8��V��@��|�B%:���t�
�m�Og&yp�W�v�S��p&(���������I�j���8Ob"��(���d(!�2g��4��Oh�q�;��;D�� >�l���Ed����#��Ef��J���q����ny+�s�\aV' 
����%t\�p����d�#�����*s�J��=�z���;��	aH&<����a$%��\�*����K-�o���>��=���
NQ����peb=	%f�3 �������3�dj���;��$�@l�)dSx��"���{��e����GT��3�X�t<zKD�B���*���9���r�
6 ����V��=��l���pe�V�\��������j&�iJi��6oV�Hk��KBB�*Y�A�����EF��N�Sm�>������.g~!�y�P+�c�*���F�3��m��d�kSm�FM���-iw�����D��4�N{��P�|��\��|�����g�[*��Py.+:�����m�%��8�,><"{g�h�h6�R�,N�HH��&	r6������W�;FB���
�#R������r�z�	�Ya�: �Z�Y-�R���P�K����
!���[��*�h��@��DT��
&{������f-#�'C��\����"����")�;%O�S1t�l�a��%0���
�]��Z��� *���j~P:K�7�AY����C%Z���7"�*���/�Xq�L
k}���j>�6[-�+"������n���E����L�B�����CO\��&���W�BYK�q�<RiKp��.�g����a��~r���4;$��)C&[K5`9b�h�s�gsH�:��A���.�
��E�H��*�E?H�5-����@0%���`�}�a� ��)�^�%[�Hq��K�F*�3�Ea�b��O8Z!-4���tEM�6Qgr��g*H9�n�6c�����D�Z�,,iCE���XL��O��!���:Sd��J-�2�������25%��U8)s�N����Y�����9X����b"9�yfH�W�����m��=�0jd��q?��K��.���F������-n�|2!�D��|�	���0��i�g�Bz��p;5��_k5���a�C�����F[:��������v��Cu��<;�B��o�������F77l�}��1���xx���������d�w�.�h���X��������L�"���	���?����#S��u�[r����c8+�r���-�j+?n����T#[����Em��g�.�<�O6�����E����f��'�3;V~nr�}jEp�q<�Y��/��B� �C\M�^i��m�����_T�ld���\{h��,*�A�B��>F?�&[ENs�m�-��r�sQ
E��8�1�t�`�5|3l�����������9A?�s�>w��}�(J�*��u��n;�����/��|;�\Q�u��'���k�M|������
yC��A�SJJ�t��/���9��`������6=+��0���d�*No�7:.V��H�m-0�YT�I���$�HW���jq��b]si0�M��|�����c�2��eB:s�ena�d�1a�Y��.�S1���u���f�j��5��-Wp:"#�YF�.R���rBE�1R����D9e$���V��]{`�5�"s�~t�N�`�I��m$u0�3-�n�`���!�>m80�	�
��-]e�G~ZI6���,��&�"
W��7�*7�P�'+��Zc�i�q.��������QE"aF�Imi�,N���+��2S�AbZ��<�/P����8��rZU,To�^��<��YH6S��]�f6�P��I�^
�z�C;"�a�\�M3
9�|Q��\��46�<�+��/�@���6� 5���3�HtSI���\+���!s3��|sG����QK�� �}Ef����q�D
6��d�����T]Vi��2�^�w���
��#t��u�q�9����!����5���[a�N�=K�,$Z����E���JY���������lk'���]B�NcY�	6b�Q
X��;�����B�����k�t	h�Y9��&b	��2�!&yV$
���"�L��5"H.�"&f<�q���v�+�A��_l)h��k�G���c[>�a��%������qy���%�3�H�CU;f��Z����wp��������v���i�}L��m
g������,�u��N�5�X����n)Q:V��g3o��:9�Z���"�F���X�U�7U�ZM���%�A���J������o�U�����!�D6GV�
B�i*�ew�a���p��/�T�$/�Wt!�n�PG6�6�1��[0�T�������,���r7�l����0�K���-h"�i&���8������S�5Ui�UT�ia&6�z�a@Y���� ���3w.�<�c���Tt��qR�F���;t��u~����NF�AH��"N�g���T���r���2���8��
�H��J|-����C*h�|��?��)���4�����8��\��k#}���F��������)�/��X�:`�eTq�m���	��9	p�D�m<�	!���v��k����f*��������~�A���j���M��!�J�C��D����2]��:�+o��J'����:w����C���/���23���bYS5�6k[��rl[4L�����d���v��
�'}\��E�nd��[e�����aB�D\Q�����4�������F��~%�%��/c���(�����s��ARon��)c k��f�����]�;8��6�.�����R	M���23$��%��\B3�_�?�	�sGE�$�E����J���zzz>05s����I�����SG����Ww������G3-z|j���G���%i�7���6�7W����'�������ft*v&;��h��>���'7���H�
_��x5��B=��+;C��/o�'wgW�vr�yzsum'��,F�����V�?�C�������N����|�a|0�u��R7��������Wg�w��mX�I������o�.�7�_G�&3��[���h.H�d����������+�	lx�q��YgW������V<��Do������Wgw�&�����f�y���T�\����c��<��hh����>������q���v��]��Z��%.����1��C�b�;�����@�>e��6���o,����I)��P��p���V��c��'c���rx1r���IlJ�y��:lg�����m!�����E�`"����I���D���=�%N��q="�<on�._7�O������~����3�2��d��EE�cO��a�%�N��@���#�G��Y��{����={~p���NK�/�F����m�o.������F�>;$������G�{?�_< �zgQ�?�@���_I����`����95����������������c�|�b��-vXY�D��������:e���o���c{�Y��c�[x��_���a����I�#�
R��M�<}S@_�)��/��^��l����S����/�rZt�d_��l���`�}A<�2�F����M�l����_��_��;T��z �������l����-�P�Bs�j��K��8�
��gK^Yt��
_�����x�����^V�r����9�(s1�Z8k��X���s[����7H�����q�Hc��-���_s�����l?_~E��d�A�L��o��0�Y�@��{W.�H
�����%df<�}��Uu-�_If���:}�u��k���J%�4J:�_u��:^����M7v��N�H��d�w�}��L����<|�����4�l��������#���	0,��W,� ]���V�M!A�3
C��D���fhd��n7:���S�xI4�����$����D~s����@��!
,�E�/|l�,VM\����L�'���`:��&8p2%%�����0���w�8���5��)-��?]� j^:�B��<
yz�of+u���z���KC+��n�����_�v|�����i�����;�%X�����K������|bY7'%�(f
$OD������ND�)��\37�Q�QX���[�
����x2��{�G���Gq��	��C������T>�m��x���K�<B���CF&O5&�A^��~���v���L��|���"j �����*������~	[�nA=�H<�h1�2�j�j��W�>bU`s�IJ��Y '�d/;9-��ns2p#G�P���=��B��H5�T�8>��at�i��a/�q={8�����n�����{��\<Wl�����tn^�
�����K�1�&6$��v��<�� |�>y��%���g������5�1�"� pcrm+�"����g�%{_[���
B���v7�A�s	���yD�*!�W�tF
��-��*��6od	������}m�{@U�8��d�y�&���+��K73\c���f�E��~������)n��w��o�����[����*��=����Uu9*%��{*}�@���9�
W��
5�����X�������j���U'I`<@n��yHt`��f?H0Or�������#���v�_�����Wi<z!�p�)���ZK2��'��
�����D-b�z���������>���b`K����z-��q$�F6�7��6J�3Z`��	 QA�k�,�W�I�h�����0C`;�4R�\-�oxc�=8>���H��_��$Qv��W����H��r/�`T�y�X���p�����p�����F�8Yt���mMHr�_���M���'f5����M* ��g7��	;�d2u�Lhn"ee����+�OC���1���y�lF�Y 4d��o�(w�2�z!��7��Bg�x��� ������P����^k�q�B�U��S� ��V�R�0��X���
$D�i*�F������*UN�s����.��8?��2M�$����	{C�6+�5��!n4�Au��o_�s��{�0S����M�xVqj���n�+�����"�9X���Ch<K��r������<
~�)Z(!J�J!��<ZD���o�X���8�������Y����9�N�� �<�J�b�5mQx����.����b� i�~v����#�r�T��6q���71������x����J�]�<{�� ���%���*Ery*��������qo��)Wo-�|�����.cq
y�k]%�a��������@��W����ufWs����!�f��(R��YW�������Q��G2�$��n!%���\���V,�thv�'�����Ty��'�0J:���Yd��i�v��U��1�������i�&��ya9pM}��=	�����4L��s��{����%mX���EG�������xR���7�a&���N�dDKr
E����u�}�X����{c��Q4�k�v[Q~��q0�&S��������0z��@����hyzP8�j?R1����V5A1
��H<�m�[��������_�[��}x\������%�05�E�k���d����y��("@�S��C�J�/��4���+�g:����@�)�$�kf��C����tG��
B+}����H_�<m3�b�Z_��[��]z���nXg/"�>�h�l�Mf:�n�����qo������l�QE+���E�����P�eR��Hb'b�u3����p�;r�
�*L�@P&�c�����2�YN��sR��m�S���lJ/u�dNNUQ����=���q���s>��K�	1�������%��7
w�(��<�'���!Cj�?�2��WF)��: �����)z�0
2��x#����8��K>6O�@��Y�����*�0
�a=Nn�������i�7Gg�5��[Z��s8�����1[��i�54a�)F�s��6_��r�:�W�e����M�x$5�$��Gz	S��/��	��'���"B3����F��U;Nb(e���V5����L#��R��4eK�q��D��JK:s�_������{N�8�K����[�g������S�u�!^hAV�����E9��z��1aK�x
%��M�/��'u	�����(�~�O�(��twF��T"�;dry&����QI���b�4��1Z���A`F+�[����FN�������wzH@�IL�'/�z���w^���6>�9�IH@�7�@]�:y�K`��H�3��>��c��O5���N�L�;9^A������5]3���o�'9�h�@xU����rX������84�Y3a����r[��9]�	$�3c���];
�=����t�\�i�H�]N{���I��*'�n%$�"V3INZ��������������O'�g/�G��i�A���,5�H��k��g�L>i6�*o�S{�~�E
|�*�
�^���������7�_�:8}�x�*����8�f��{�������Io����<�����o>�
�_p|v�d�w;���a�����r��w�����H�*��%�lH�����
�����9������_��[X�
we������?���#�m'������;'��g�/�v�{�K�7��{����H�B~������io���a:���_�����(��b���������>���������k�q��� ��\j�[9���iu�%wy��p�����#EH��e0���d��8x|OLA4���GzrS�l����3��/M������L�G��$v&�O���K&}��=�~���M�������y���V�����������(t�a���������
o����W�����d�g���6\��r��}�a�l�eGO�|�=V�[Y'��W������9�Q��n���5o�|�1�&g��d���M4zK��2�.eQQ����e�k�\�$�\d����������,n?���2Olle���n�����JY^��=���Q�|����~V���/�JH��JHE����:{|WI���������A����0%�Eg�CK����cv��3t��A�e�gaG���v�f*z�uwc�P��z�����6�|��8�@[b��G�X�@��P��P�Xl�_���Y�b�������9���=�XkX�}p��)~���T.��n7�R D�s�Y�P�y�\���I����rE*���1
��"�IQ���EN����".%���CO'���M��{����d%�H7p�f��uI��e**���� ��|�����mB���u��aI	�Y���W	;����Z\��A��	<V��
��K|t�}����U/Rr(
��rZ�o�X���m�����1	�(%u5�����AXr��t���d����B�V�Y)gH���agG���C+.�a�+!-����d_D�I@*t����xq�
E�����v���D�d���eg��[�Ro�9�zgj�.������5��J�1D`5�d'.��I`�3K�=���FN}�
'�����h*�e�y�(��M+��8n&R�{P{�!�u���gWNS(f�v��]��B�������\M�N}�g^��rqb������H�4���f1�Q�Bq��^�y���;alF������G��v����/��-b��v���{�J��Y;e��(u��]��:��Z6vJ��'_�@�0  ���b������$_@��5
����<��%��H1��O��w �9�c�.b;�n!� ���@B����P�^$��Se�����?�t�������`���06��U���S������r=��������d��7��Y�{���V.��&!,,�/DQZ�������0���:��h}O��X�?u��4��^z�8!�����Y-7c���V�Rr$�j�5���������pP(���u;�(_�D$�3&��{)�)���yg����]�L����!�����T�%\�(�"�o��4,.��s������eO�0KR�g���x0_1S��P�3\����	&����q�:95�8b��#�(�r���PU����Z���&6�4	����+�����})�j�}��(�[�b��#��*6����D��#>�����/v��+'�0M��7�4��-@uG#�����'��-��X7sv�VS�w��;����,Q�����,e�(�&i��������"��dx���~�vNAV�^�
�D���TIg>�t�����hI4h��H��V7{���J
�r9���	yS�	��q�f��+���w��V���B�����w��%�
V�%�$�I�������4K8Fu#����T���@(�J��&�)�Al�Z�6|	�>pN8]����4R:KQ��	�{fu�6q:d�B��mH�E�#�����i-7�w�i.�;�Ok��<)'���Nu��y[o����"S����N�����J&��3s��Lq�H>o4	a���bv_�������
8�,������cK���pWU�������#�����?������;F��$��@mt��d�DuQ����������l���6m����z��i�
���Sj�^�Jh%7��O��|6hg����T
�����&��K��:�*�fzgdn���;�Yt���xO������ke�/���<����(����H�
������(gZ�����%M\y*9J�M�����mZK8������45���A��El-��y����4��t�TC�bZ��M��/���w�3>9>CfQ�y^A>�@�/���:`�x �#!T�a�w�y��G/H� lTaT���NM���D7D���{
�A�Z�o{{2`���Q����U�o�q�n�qE�S�)�����{i���0��a�b(T����#�������2����=-�h9M�#��`#�1��2*3�eZ����$w7���\/)B��=/^�EENL2��h����H��)�,��%p�LywG��F��"����E,-�.$�jiv�����Q�7�E���A�%V�ZP|�������f=��:	(<;'
I��G���������*�,M��1�G����u'�Ije
����w�D��@���E��
E�n���C��}C"D��_��|�>����W>6���_�##�X;;E��W����
+�_��I�_y�8h,���x����Zz��k'����d-�^L��������z�
����<<�V�V�����w\YC�6��o�~��}������$�<����X�Rx�\/���b&vk�����#��Lnp������K��?���7�)^\�l���>��bI��e�p�(�N�3�p,1�������N��6���.��Zb��?�����x�\��p�Y;�����W�v�X*ER������@t@IVn���RG����@rMs�P_
�=�|�n�k@�2O8BO�\�}^����F2����=�a<���nnzr�@�m���)���V�i��FW��)�2�YK��!u�]����K=6W��U1���&�V-}ui���b������A:r�AByC�`����ob�a_Z�J_H"��/Z��:w
��rX�Kq\� ��ex�����^K)���Nr�a�hVkv���V��m��W!x�y�b�����BXv�;�scY���S�t�d=��v)AJ�����DO�E��F�����s���,�r�d���@��!T�i����s�?%�lQ�|UX�)��D��*����^';4ugx��SP�g��@����F���I�Y��p����������xm���6�w	������lnBb��u�(�*�ahri/��b�����/���c�&��&A������g��^�����}��3_l�<���2q�RBK�ZA+��������[�/����Y������������>]~�R�DIB(�Z�_Z�'"��a!���<)�~=�v�A��8�����Q��1Y$�p���I��k��FeSFm�Ec<>D3��/��F��g����B���rOC��&���c����*@G��duJ�>����Bm��8Y�������[��-��c��1��fsF��6@��j�R�[{�C���sN���t��o�	z��K�����J��E������X�$R��6h<��L���0��v<��������T�J�p�K��C�I�v��O�k�o�u�%a x���n��@��q�-In�hP������&����y�FF�p��'��T}ID�xJ#Ov�X% Y��0P���B��r��
_��X:,���>*.�)i��X�s�"��[
=�/&������3����'Bj��Tb3Q��he����~��i!�)�� &�X��^�������N�,��+ERT�
������xQ�.H ���^Z�o	����t>U"h�s�k����G��j4��F^�3{x��<��a(��V�h���BC�T��8� ����tR�G}����l�����f������:/����Q����F�]%�+��E��;�0K�������`~1�Opf�����o��x��������@>Q~=�����y�y��|�l������xr�3������s��������,*a�M�M�k��V�a�a1���Vum����d���$B:�F����:���QB������JjP�k���O(��8�jf<S�ZjV��=���^�K��n��]3M_3�6�Z�>�D$��^�13��c������0\H��N+`2ec�B���K��d��7E+RJLc.^,]c��nC�l;�l�~��������^���������/�~p��
0010-wal_decoding-Documentation-for-replication-slots-and.patch.gzapplication/x-patch-gzipDownload
0011-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gzapplication/x-patch-gzipDownload
0012-slot-hack-up-pg_receivexlog-support.patch.gzapplication/x-patch-gzipDownload
0001-wal_decoding-Introduce-the-replication-slot-interfac.patch.gzapplication/x-patch-gzipDownload
0002-wal_decoding-physical-streaming-replication-walsende.patch.gzapplication/x-patch-gzipDownload
0003-wal_decoding-Introduce-changeset-extraction.patch.gzapplication/x-patch-gzipDownload
���R0003-wal_decoding-Introduce-changeset-extraction.patch�[ys�F���������H��d]kodY�U��Y�K�m�XC`H"�������{p�P�$��"������N���������N�xh���w0����������C�y�}�K�P����j�������X�F~b�z��,��?5�^G:�_L����W:5��G�w��ze<������xxp<<T��~������/=V��tzu�V�������V�#�x�D�cu�I�g�Q�LGScM��]�h/
�����V�"���1�U:�=nn�����$�l21�S5�����Y��Tb��f>
���VMHbZ�+�*��&��o���n#�gA�nA�_��t��x�h���)��A�NU�-hC��be��FA�@�����<m+,���Eq�.�T-�lDX5I4(��4K�a���>���X{������N�;}��a�?��y�6��v���)�
���&0�j|��d 	�ff������o����$H�T}��&I�[�m��	���.�"}�]��u�K�����y:���zo�8�^�����&T���Yd����9�Nm�2�n�%(���Y��������������,�q&
%�W�;Kt0~�y��$VoM�����n��l����L��jfwgF/�=�����o�����7C&��2���g������}������Up���~_�����q�d�x�I���]/�,�����w7������M�-o��E�m������L8��M7C�I|W0��G��d�3%��<��Y5��}x��@���g�?�"�EG�AF�8�Z��ojp�/�_��}|E�s�����?T�AK���ow���N}�d`��{�b=UPD��/nr28z{����ME��n�����?,C����h�

>�>(l��A�_�������BD`.H�������~�m��}S
Fz>��0[���Z
akA��M�.��U	�C�<���������-"��Z�����zA����|�H��Y}���C���G��+�y8|���5��~O�����:��w-<55�E�l���Y��UX��o������h�)����=2w����)�����a�.�����}������fbw����@����@Q����C�}xp������������Aeh�A��T���PEl`��g{{�N�8���H����?�b)��!�\�����M@E��#P.h}�R��&����M����l��d���)�|������w�4���>8�{�xg��7Co0q4Q���}��������U�U��G�����CZ0B9�F'�l$bj] �~��5Ui��lB	:E��Q/y��NS5jk�~����m����v�����_�_�@93h#8|J-����-���FGFD�� :u�3�#A��#�0�z���"��[��\y:�(
��n����T�]����8�$�]���oG���q��1���lA
���~;	(�j5�EZa��7�Wi�#c��W�bP��$l���`�zl��M`�q)��~&�5v�!����]���]��{E�u_�4������e{��9���ho��$�����6)zS�O��-�(0����9�9�F�%V;Ch '����|��������SA��9a4g3�]�n.M�
2��h?M?fi���TL�D����3�b�RxLx��C]1:�(����J|�'����-���F�4�����r>N&��I�]��<��a����&�p��w�rO�@Q���]<�l�Oi�Bv�w�9���o�v����{ z#^3�dD���f�����`�����W���\�����\���m�V"D��QV�,L�y'����g��d�Xe�u�F*^�P���
�b����E���cs��sqw<>�y;;G���^�qq�����[_��7��Q������T�������,b�Na�;�'M��.^���[j[������,B���a���y`=��)Y>!�,���4�e�;���[Pk��-(���/�Ek��q+����
��wy��~����T���Y[�<����q�"��9@��J�����K�-ES})�������D8[����u�x����
�6�.S�y�����/C\��*��&a	�/^�_3CA��=2^"6<@��^�?<�Kv��91
F�������
���h$v�>bAx���Y�r��+#s[��yx,�H��xo�Z���t���Z`l��z�%�JTJ_�X`�������6C5�r�n������	�])D���xdkY�y�n����'������4�����KN��O�#&@�'�n��bJ���Uyq�+?$9�C�"����m_��y�O�>��QN+p�9�9R7U����Mc������~�*�,X�c#�i:��e�Y�lX���
dy� ��"�<��!�n�`�z�.:(�yy�d���d3A1��S�����=W��-
E�|33��{7��Ky��T����3�j>U��C�sao����s�ZY4���!�i\��wls�lDF��YW�.J0�o�N_6���8B�������J�h�So�Os�V����Q���z����]�u
���1����c7�`����P_��S" /�;���e��L���r ;qQ�c���M3�G���>Ui�(HK�'C�*�`n�zB����mj�����+��|ZJ���.7�y0������;�`4
�E����@$�C���5
a����g��.�i�����[<��fx3q���B�|��+��x->���Lt"� Q��,�MZ�j�AJ�)3���g��5J�n�T)��=�V�nI4{]aB�.t:�����>��tz��g���uXQ&I��Q� s��5b�~!W���x
���
m��rR�=����x�����/r��s2�s��(�����F��R�B����@%pe@pgP,uS���!�**
�P�7���U�$qS�d�&q����Z5E%9�%��"9��M+M����I���/�B��EoJ�����W��B�R�/N]y��cZ���u�y�bp��Z�+�$��"*��%C`������<��J��8���(v$#�k�F"����C�Cu�jy��G�<U�w����Ad|�� vER��J�1\	P�*
������/r������|���baDc�[Z�����H2��A
�`o�_x������	�~��5(�Q@C6/�c���������&��Z�t"���Q��"�Ns�!��+��G!������T@�VdU���d���65��A�GC���}���f_Q�;�2��	Y���0�G��\����H!�����OZ�E[��,��([#��"=���{��}Nu���8���EmG@����_�XvK7�=�����������w��E��G��z���F����%ZRov��g��N*��J�j��#?�W���^���?����&x9;hV����"�6������5�,�l^ey��h���\@n`�>���gk��3�������<I�;t"x\~!����Q���8HS�q��V���~����P����;�� .&�""�2�X�<��p�T��b$
���b�(�{��6����_������C��j+m���)��L�u�j�`������T�9�;3# |U{�?�"����
�(W����p�~�Tf�lAg����H��c�����-�;����4:��||���;���I?����nt3�����Q����R��].�A<����t��hZ���z�b�-����Me���
������+��l�.�5%T�v���z�B����"f�.��5w�%�R�3�Brr��a]�������M��-���h>��@�����|hp�2�jfq|q�����$��fHj��*���!����Z��\Q�A����7z'r6�"�sWV;pb!�'�??d�\��3%�������[d�r��ytd��L�z\CQ]�f2	��D�=I��������4
��]P����Z��j�E�dZF`��8C�����-M�xlaerrk���(6����9,l�������P+��M��
.\����D�Y�ROLz,�Zw��nhpXj8��FgJo�qd�3F�=C'vo���BX�nLf��Ej�x��pS�Y&���2l��� ��K
dG�@��R��S'0���<7PW��7�M�H��	��gA(A��X��3�� Q�O�8'+��k�i�a��1bx��f���G�ga�B�P���Ta���w)��r9����R�)U���a�D3�g���	���3i?6����uir�M�l0_�G	�Ltm;>RS��-������R�"���Q����x_�g`���wR�$u�J� ��a��Cib��k��U��\QMT.�R6=+V���0l�F�kA3L����V���S�A����*T�3�a$����b�>^�(GD� [��������T�ZO9�)�:9���^:r�H�h�l�4�,�"�[��N5�[�c�,Kp��u^���qh��9��Dt�o5ka|d�T��3�[aw��8�����O���=���<�Z�r���y����^dr@[�
H����*L��n�!�*)�c�6�6s	@ru��u��B�R����DaN���QH��"��X�2wt��Y��p�l��%;Rd����fr$iV������#�[%�Y��.w$A�x_���ES��<$i��BZ)�H��LnA��A���[W	'�	��	o���h)��gNy�����������neh�
�����w�3������yE�dz:v�	,��M��C$c>�����-�H�V�f	n`a�*��I�pLt�v����!�+C���f{y��������o��^�=�z�>�7���d���vbF�ZT�;����?L��8X��f0Y*|yXi�I����	~���D�H%@�2����!���h�� ��]v*����R=��3o�/�)�A7�."�@^9
Z+��Cn�m��M��A��Z��^s���,
������w�\����6���S"���4�C��\U=�O�uG���64D�j�y���p=�MKC�hM�=*��>�^$1]E��N���t�`rE���#sqL���P$B-m)�R�5Ec��
&�qh�n�P���AL{r���.AGu9=G��5['m��,FMth�IM�
���@�f�.T���g�X���eY$���v}��CI@�D[h,]��}��z����6c���\�{Zn]]��tT��z�4�2��RZ]�6�P�}��0���
r,y%�4OV[O�'n���;T�;|L��q���P�P��L����Rl���������7��_������������W�?]�_+��5�\��n�������C��jEN���
������BD�������.�N�~�D�����g����,�Rm��;)N����Q@�7�Sh�#`���'�9�e4=�O����*���9<b%����W�/x���'E���l��i~4.����q�&Dr%k}WJ��65��4��DN��u���E��
��hi��1w��">DA7�3�Ynr��4�������=��~�����r����7�q��[��{h8��g��
��]pV����S�J
4g�+_��x����R�
"Qf��������o��Z��zU$����;�����$�����w[�$v�d�RO�����g7y
�������X�cZx�;Gi��?��R!��5��.Q��X�.��Q�S1���;|��J�C�������*��L�'PN�r���&2�H�k������~�k)���X�e�Lp�t���wmo"��E?��"a6 �lu/���N�c����~tRR��A�VJwW��~�]��dFJ���gf�<{waedd\V�X�w�8*��P�V����Ca}t
�a����y�����C5�q���=��|�_d<�y��Hz�\
�M��22i�pj��l%�i����5gV��M$'��������_����Q�.�v?k������/Fz�������QY������p]�G��M�_�����.)�\���^�<�>�����|j�����3[�� ��!�&�B����c�{�P�<��D
�B:�G����X5�>?!�	@K@tn)=Aq��.��"
��0��������1�f�,�U�������~+	���X�w�7����i���������JS�l:E�>H�n�a�������=2�@;�������{����f<���{d����1�74?�p)��F��x�Bc��@c{��Y������-i[0��������=��7y��!�^
��o�����e��Z�,�VB_�����e�������9�����z&��+y�?Kve������D�t��
�y��,���S�T����U%��������	�."���e��6��$6R�*�JU6�v��C�/%���
�xJ������/�fx1<S�)�=0����p��)�?E:��k4Fo�����C����ma�����~��������f�a|`���9�f4� 4�!r��������/�DVw�u�k�j"���k8SR9�w>��D���+��s���1g���D:�����-�D�B�D��doDo�6	�����'4z;�u5��B����2��7��@�]�Zl�H!ml��^&�t��K�-��]w��z�X�+�!;�Mu�?Xe*F��Q
��G��vh�����Eg�L.]��������;z�u^���9�7�c��iw&���#Z\CM��h�D���>K����I%��q(k�";QE��U�%N�^5���zl~=L���$��5B!��ag�d�,�59����=��;9:<������������_�WN;����'����;�/'��/�������W���cYT%$]�!�+�%�9%q��e<��l����
I��tv�	.a�~K�`U�eT(�����\j�s
�5�!z@�P0��uD�H{��m�4�����e,�L�!��qR%{����e��;���Xje��O��YY�P@��Vb
�O�6$[_�
���+]����Wj5�`,��/���c&��7��o������_�O�u�w�/�;@�O�O����!��;Uo#��,���	���y��X5&2
F�5�����=c/Hp���|��=Z�u�~����� �1 _��b���Rl$e��<��vq�x�A��L��O����G?+�yK�����!1$��uI?5�4b� f�iq���^jC<����c���J��y!vDEP/.n�4 �C���=���H��i��h���{\��e�):L��x����`I��
�~�v%�O�Jj��]d���������&k/W&2���8�JPC�����@���� �1u��pYZ�"k�W�`�R6��3"_��L.����K`*�H�|���Ty�������@��������0��PcW��6/�37��]���S��!�k�j:���Gi����{�/�W
����rW?������	�~N���.����N������""�D4J���,��(��<��i_6�H�i0����iv�N�����n��Q�
�-s��c�>�����/�e0T�|�	�6�/9�c������#��h�S ��W��y#���A�J�`x�"�nb��\��+��M��
8���H/�#��h���A�s��FmK5y=�i]����wPm��jC3�����	EF,�\(�F��/�gD���K�UxN���������(�V�v�����K�v����BJC=������1e��\t��/�(���?.�.i����fN��2\R�*��V���fm|�q��hZ�UE���#�T���-D��8��=t�EC@G6���4�A����6��p�G!wb^Kgn8H��Q�p3��%�6k�Q"��.V�T���G?�/�wo��������s�,
�����+��������9q���wr*k<�B��nu���t�����3Z���_r9��Klo�r�%�SN��'����:�Ms���<n�;^w�����q�p�oP�Z��0�R�0;Q���]m_j%c~6��GN�(6�����#ip0`�������F���8Z4������^�0:ov<)���l8��<�(h���~8�����bi�M��.i���5<�C����Z�:oB@��Ey4;����8�y6Uk�v	Y��XM)]��,��j���D��=pa��l�?�R�T���1'��Or����!ugx�zs~�j���tI��g����C������x�0{L����+��&���I�F2�/�b�����4�D(����G������	{GtI:�|��@Jt �>y�a��N<Z|
�fE����p>��:O~���9�Z�"�Ir���;��9NI�}3�kJWh2�@3��� Q����;f�E�i=1���Y��#�����NfS�I���2fL�o�����,��C/z��������AND����!�������fxB��iN?�
��o�#����a����H������x7p���'_W��;~w���y7�7���O����<��������[�Z+�g����f�S������$M{��7���Fm7J�����&�$����!6�j�h�_����w[I��2��IO�e�d�P��|z���!O6�t`�
O��@>y���[��w#X��]lT�
p/���{�c����<��b�Y���}v�%�Iw�������4
�q!���N�24����~�B���#{�y���E����K��Il����V��-|�h������,�[�	���E-�(Z'*O���E����N�*��`����$�C)�c����� �H�#�h��Z� �I��v"�
tY��XYq+P�p�G���}�7-Yu����S���	�!lqI���;C�����[C+�"��*!�����x~��x��}��O�]F���e0H��8<��1��C��\�FF�����&���Y�%�/����b�^�\�G���4��W#K����c��������������f����'�~�
8�U-p�1AE}M�,�����-�3�3���1<��Z����e��pp6�Y{��,��
�?�^���L[����D�_�ft�`���,8u��h%��F}7p�W���������$��=��9|{�i�<�4	E[M}�E�!FC�>n&dS\FH�bV����������w_on�?������|J��RN��0}E�V_�0�*���Al�ub�q���:�-��9�b�-E�&X�����c�6��/��n{H��[�����T�[��<p(������,DmW)�2��VE��|5���t:��)�}�-�p��~�Q��)OG��������������?���G�!PD�>���mMpN��*�v������0��&9�1��)����$v��O=��|���Z4��AI#~b�R���nXl-�?��-��f��Kk%���D�\�%����w�6��!PUX Z���z&�0��Q�,����w������38�����������9C�V>�YR��$k�5;�qq�����]z��o�	���G���_���u�R��E��H��%R�EI�~$AB��@
�f�b3�����]O\�qd�������������2-�F�t�WA�:awI��|�~�}cd�'��7_�����tQ�"��`�%���1?���k��p�F�O��{���k��������m�����Eu��!/:������EF�vV��OJ'
����h���{��[-�b�cc6��W��3pC&�����|I��9�j��v���q����������:��$(DY��~��o��|�85���_��?_�V�^�K�����!��oD`�)q��F��i�Y#��<�-�0�2
���Y}��>}s���
d�D8�w�8Bn���������Z3<\�=�#BP�-��b$�Kw���0�uG���f�1���p���Cb��^d�(�������-��j�<�,����������ZO�|�����t��A�������l����*�~�#G���^'���H��
8;t�^�s���5ot�
����m�����*�cU\��AG�+l� �Z0 a�O��"T�/��*��x>���`I����yL7�~����>&��{���9z�����m���t��h����7/,�oZ]���7����Q(��3�q�O/5�fKr���gq�
�R��_f���f~��S�X�%b7bV���"!�p/E��s'-��(<�Qa�������l�k��9Z��������~�����on~{�������ys��*k�6�rl������S���<�yu���,�h��������>1`����E}'���%����_Xc��F��?2w2�\L�V6&�������L��1����/��'��r�������'h�^�6�HU%a���&��=����2�nhG���E��W��ttF�x����mn~��q��7=���~�qk4G���m�|�����{�'��>��/��a�2�/�o�(�i�t�H������Y�e{w�(�����>�����.;���G9��������(�Rm�t������D��ntM{9�RH�F���y
Q�gE�����[t|9��:����'�>�v��p��a?��TB������6n�~�������� ?F�e(cX����yi�����
l��&����������<E���$��!�mm�����#��7��O;���C#�fFj��uZ1i�����8��L��3Vg}U/�`�M����%6�6Q���D�{�� ,��d`����3������+�����Z�$*N!LSIL�� �&K?P�.\g�$�PVv��.�VWqxwf�8*.�}A������?���� +P:��H�+��WNL4�KxQ��'q�!��_����G��i�l��S%�!^��(�yA���v�x����]�����f�����x���W-��j���A���b��=Oo��t<�,��kT����c&oG9������n:���F�;�������|Vf#��e[�~�f|�����u�lA�j�:��b�	b�����2�����B���k'j��U����R��������]*�K��\T:!�a]T�u2��q]�D�0�:
�����B����m��;y��$yM�nZ�D�f�w�&U����f�Z�����\��u��������/��)S��{�*O69�7�q��|P�-U�w���f�i�_�;)���#S���@��;g���]$g�1�����	 )�u��t��k22z��������R��I�a�|�S�I��%��p����i���W��f���c��o8/K��1��,N"�+�gLd 8�S?�}����F
�?��\��e��J2�yzi�w������`$�!rI���!N�6K��4�M��4��(�����0�9@�0�� <���ly*t$�H�����8��M�Q�r
��:�\��e���.BC�����G�f���t����	[��l{-f_-,xir���I�L���g�D����d��7%���y����}y���3��j��	uE��S�{�0x[�<������#�r�g��i�|4*n~��CQ%�=.j���}��I������;���o�]����g;�{/�R���^���`~z=��~��%o�v)�Zg�����9SM*��XD0Ms8�I��g�[��H�F-`���]�W:���S#r�,��]o����;����^���}�������>8�?x��T}qv�_�� �J��jV:�|�h�����v�\������������O.I���
wr�������W����R�p��DN�UTA%��jH�s�cf�6t!�����e�j�����n�=�q������������������:ovN�,�����$��WT�������?���4��{����_�����eZ�����>>j�uN_�=�;zw�c�������i6%�<�(�����xzr��8�)�qtx�>���.�&'o����K���N)'.{��
��N������MG6uC�29
���Fwxtt\ZP��d���w�����_�����1V���x�d���������������������-K����w��^���(�������XQ9i9�Ds�%3�/u(o���%�M�p,���8��D!�3���R8���c\=��d��h3�
'��#W��Qj�f �T.���dJ�,��1��,A��DR��������������y�����e8��h�w���i3mJ�g�tX)���+z�C�"`)-�{H=���]Pn����^;.������FiT��~C��?!���Ec��XR�U��5;����/���F�(���_������K����1g�������D��#@1�6��FW�*���v*��W�k�<E7J�R8�$J���}����PEG]��G������Y�c�P���iF�;$��mnj��1z�&%<�T�O80�'�?�$+��O�M��c��"�D�@���o!�q�0���V��B>n�RA+��������q]�%���F��(},���������l���ri�Z�����7Y��������b��&�K~�����E|�<�U�ZZbk��@��=�h�!��%lMq�Bt�������m�m��i�������CS�������r�g�p���h��uuFd�l`��F�Il�n�������A�o��N��F�,�����#I�E����%��E�v<n6������2&�kU�\�s��d��,+�����1�D�����y���-� &����T��;���q
s�`��j������k�X�jt��u�@�����L�_H}�,����*�e��U�%�O`�(���|;vGP<�Oa����,�N�x:�����^\��+�D��� �
�$�(���-� ������_��Q��'�j�l����]8��B-&l��@S��c�Ny��4�3�C/��>���S�8�oc�����Z6��+��a4�d��L�_lqb��`%�����
N����W���1��MI� Eok�����|���c��|>��Gm�n��Xl��Y}[`Gn�VV1�����5r�u���y0���=q����l�����W�������p�]g�]r)o
p�=H���J�m�2?<��v���y�(������\ �������k?4�%�: ����fz�<t����>�h�"�7��v���(����z+n)o"/O���}�s�S1{���O$>����i��A�[0����������hU�V�G�ag_���/3�#����b�XI�?C>WbF����Be��hIZ�������g-� ��W��5�!T�x������e
�6�S9��
��bz��3�1����M���X]	![���������K����7��e�e��C��G�S�FSG$���~���A�����C=�Z��R��F1�=x{�?�����27��#��������U	���i��c����VV��5����uT5M*
��s�������'��;�s!4�e�.�!�1)���
�Uy���>�ek��A�+��>�N�0/3����������4s�S '��M9�F��ez��R�J?c�
@�5Ca���9�3IW��)N��.�RsEI�����J%8jj�$G��	0�(���,7�������P��_e3�`�j^�ic������C���	�3�E/��Z�R@�%��)�q<���IoIZ���,�,(�������o��O���W���"
��>����0��oL�I���+_��1ak��zh�>�Qq��k������E{S����.���{��(���1-�����_�rI�X��]e>������M�2�J��D�����_�Zs��d�.e�R]����]G��������,em���2sg�A;gF�^
�b������\�f����Q���2W��H56��8��d��`��'T���`0�}dRJv-�L���PL���T����<�z>E�jQ��<g���&�c�is���P��f��C��s�����U��E�f$�	_�U�q1Eig�iz���������?�w�u�x��=�\m��k��b���(���gQeq�8���l5���Y�K�/���r~�$m����)4��>����qM�M��/�������\d���@��������}}�����+�EDnT��h0.�<�{�5r�\r��g��m�#%]������i�\��N��=��R�������������������{��DUN��{�����w<cgx���>d��-�]��q�2JZa�zq��g*c�lbg��N��2�
�����f�v#w����F�SVa|" ��6�2/�����t^�}���������/�&�����[�P������mK�����v��v�g�X}������J)s�	�Z�s#[������cX���k��
���
-2�^u�4{��f���
%�PR|%�8��r^7���F�6k����y�� )���e'��P��cv��@��g������p8-�I����y�p
6V1���Q^D�2k~b�d�!�|��0���R����Y�1}pItH�o^������Ry+�`�C_����h&��;���5��2&�/��$��������y�Ov�aw����x����Jf;��U����Q�<[9Av(B�T����2&�������q�N��?n�_W����=�EK��u�z�7l������		�s6F�\J�K�b�J�17�3V��|��r����}���n."�Yb�v�?Z�eJ�o|A���	i"!��~eIV�'�Y>S���m��
%\�	��������q�P]@��q�� Ah�T���$�������b��Y
�
��v��h7�4����5�EO���f�wQ���YE;����H
�	����-���r%aosB����<���i�Z��Y��0:t��6���Xq����q�|��dc#i��e��I��q�]��k���<���R�������w�+�{��F)�@�e2��v������.�e7��OT��9pc9���n����QO�
�&+�G��f�-t3��72��\����������0hb�v������F����'|�U(r/�^
��r���
G��2r��m��W��������&��oE����8z)����d*h���1WX<�f�#m��6�G2o�:E68������i&���N�v��I������
l:jZ��1�3��;`����[�I��f1�=�/�S����e��\�WQ�u������sQZ���(0N��H�
�[�du!=5���''�b��Q�e����H�,�N����g.�x��~��t;9��N���`N3
����s�1��|�CO�6?�D}�xd�P�����aj(�S�����o<���4��%���/�2�&\�X�S!��is�]9��H���%#��<��^'�����f3J2]xj�Wr��������V,tR!��A;��)��RJ�&�]B��-1����*��q�
�
�c�@l�W�t	H�������-#�7xp�'T�:��_{6/Qd���g\����O��7�'�y�K���C������"�~c��qY7��a�}xUV�"����S�Y�4]]�PU6�&��r&����h�YHK2��(�V��5S]�Ro�Je�u6���������!�\�67K\s���,sAM�������m�����>}���On�����Ax�����E�x�e��/���ri�F�!�b�5��|6@������z~`�����7�B�=�qeV[!�m��O�Q^��������b���<�9��9�j����}P������Wz_����N��u���j��Y>(�������f�)�K��T"k>
�_g��y��.��F�[d����r �m��0���=�[�OQ���$T�����;,�;4�g�9
�����R�=[�\g&��}wz4�������e�J!��	�Ff�;��L�_�" NJ��Kx���avaw`��j8	����WY?+�����i7>Q����E�5����ys����2\/����7�����Cy[�m��7��@A?���}�����Q���e9L�VW�����S�qv�������1�S�c�_�n�?�K_B��,�B�lG!#�mE������l"�m�(���l��GlC�#���X.�����Y����E5;gd%�at�S|.�$Q����g���}Zi��A�u�~}@�!�������_qaj
��QR��~1�Q �zo���{��������$���|���6���?O��[�W�_��c'F�BY��,��=Y�@�3��/K�|���9{�����Cv&a��L�'��}3:.q��Q)9���9��N���U�sgW�@*/B��`Q�]%S�B�G�XI�Q]o2���YA�d�.�I�p�C9�D�8>ZB�=Fo���z+"7��E���C�b2��%d�g�o<��!��7������b�Zp��]e�l��y�?ke��[�&-�����B�H�����K^P����w/�r������,�]�t��u��OF���2zD
�U��/���te�<�)o9�+/+�G�^|�����_�nJv�4d�������Nn�	�L�B �	�d<u�)�(�8���d�n}����������w�/B�XW.D�a�E��T^���L�-�yJu����4�M�G
��~i-�\�C/UG��Ak�4,��������(A�.ur�>n7&���<u���C6{�o�/�_D��*_D�c��K
v,�,�/��E�ac��aVbo�L�����������/��9���c�N~���,6:�9*RcK(?V�zX\7�(.>p^
������y:�Y������/����P����!��wE�N����)i����'�J%��Fh����*%H���H[�G^�h���X��O�=�L|��?NXHu���B�"b�!y����3v~P��s�7��p<�f�R�fH���}�5��:�<G�G(�h<A������Grk�P����?*�����	M�1�d�9�
:�� >6���d4��X���4U�G������KcD(����3�����D� 
VP����{o7�S�
�,|�^�G��������;���y�3>T(\^���H6�8�c�g9��;C����$l��-+K,�����$�����C�:�Y����}����N�2S+D��a��pf��$��%��#�+s�)�>�%�_����Ii���zF�����������-����4$#��S4x�c��*H��Z�q��y�c��2�6����*�����y ~�T��WzI�S����������d��gI�1�NQ��By��]��8����[������������+����4���U�Y�3����&�����|4�\4B3�:>�*�P�kau���� 2CZ)�G�j�I,+�����7���F6�e��^���6�O�9+fC���G�"G�	��B�u�\�s���`V����m�0������O��D��}���|�(��l�����]��5��k���C�i�-��7���'�DHu��JJ��%�����s�z,��W��A�DA����q�;��ssO�%�zM��uO4;f�X���?�����:�M� !������D�.���Ys8K|G��DZ�zQ��?%�VS3q���GS:��R���8���;��sKua#QB�E$m6��O�.�����O�=�7�D�&�]�L)Ax2>Q����b:A/�����u��7�{����s@+i�0����F6�B����G{�������Y�����>@�����m�����{�o�)�����q76MU�
�_=��s�����������o�<�����A�} &W�2R�!�����P2��^�M���U(Q�H���4;7���d��G������O��re��k��l�����C;R#i����%.^��v��Wey\Rk]qJ�Q�t$��y{<B����J��>X�MlA��w��-P�Q���b�!:�gn06f�K�����"�����[�Rl�d���5{���%����O~Wirv��
�����!���#�%�5j"J��7��7�A�A%��!u��V"6�A$��8�Q!�c������5�f��H{�O
��&����9f��m��q���x��Hw�y�f20#��H��;Z���=e�s���%�;^�F
����h%,T�eq#�?*a"%�k.3��@!*��M��awl.��4v�����6�w3��uo<��y�`��H�SD�3|8?�;r�HJ0}��)2�P�]q��0�bVa���xj�=Lx�lv�I ��^
�#+�Mr@�m�8L�`�3sQ��^����x�'���3K��2�o&gG��Y�w�]9�!�ex��}���<L�����k�=����X�0�`��8|�~ �%�O���D�m�%E�?��+�����B7����SU'�n���$��0;�M4HCO.�sd�4Wh'������f��D?������"�nI�oH�B�HV��5/dG��w�M 
z4��~���<"V�]� :�B�����B����C�o����g���k.YG&}w[vQ���\�5C1�*��fr�N�od��%�O�C�����!��	r�P5����t��X�n'
��z��t�\��~��v+�z��mS���e�k�}�i���
��-�>q*�R,+��W��y�/e�J�JL��+E�k���PGB YI��S.?9�������9�\����K�9p,8�>��1�����Yp�������;t��u2�?�e�	����]��+�j>��~��yf��`��u�KrT���[H������a�����h����n�������#����F�/p`��hOL�'�?����|���
�I6�0 �G��R����E3��Su�SU>+j�����5�����E�����DvP��pg
]���o>�B��o������FhrY��B�\M��)W7�j������#���S�wZbX��Z2}j��/I�J�oIdc���
~��W�wt,;���"����;yu��6��������@�e�]�;0��z��SI�qCYm�!��b4���;�RR����i�+��b��3&��/\�54�Q�	�s��t��mUw��'l�:C����X�u�~g�^d�$ kx]d������KT�<��{@9�kR���f��A!$�lb��H���"1����_����c�0]��MY5��Z������]T��J������� �WOt.%5��A^��D7*����?�nv_x����zM�pL�S�����-�d9�o(�W�H�}��`<�w�������x��}<�d�:Cy4�������(�*u���]�	����}�W��a����$?	l������R��7c88=����s��}�KB����}���[O������<�X��l%�������\?'�oF��h	�A�8�;�tA��l��'g�V���tnS*�aZ$�'��G�������7M���<�������8
R�g|��"�h��
�;
N�_����]�}�"
��-w�vO��:{�/w��u��O�����
h|i�7;����o��`���O�����!���7�&)&��!HEqf����
��xlq��Vf!{!5JQQ+��OP���.��9����s������)X��"�(��2��z�"����$��w�������r8��~��I6�'5K��??�a��|!���i���Te=��f��F
H�7F����R���K@)�����VF��s"%��F�G�h4�Xh���p��F�2�<}���'�_������W�`�F��F�Q�C�'��b����4�����o�>�;��
���m�	
�<sY�O��%�mh�^���_/��I��fh�A�g���S@9'!c�6���4��W�-Z�^0����(n�l����I��������}1O��2�<06RqN�t|U Q�?�1� �r�~����~���Q_��>�� ���>H��K-��p�4��9;�:�����T���(���|g�Y1v�P���3��
a�9���hH�����?�j_3���KB"a�Z0
�K�������X��C0G��[a;AL~,� �����������9V	|H����A�E#�/��$[��-k�|�k���`��D�bxmG9���RM��.���R�������
P�-gU��u��
�3B6��C�iE��J�d[�2R��A��8��f�"�Zc���j'�C�����������d�d�|��
���_���[���r���9�V�#�+K��uK+��n�HFLM�����N6��K�����]?����Z���m����h9����!��3�]+��xz�"�����%{���2V@Y��Y�������J,"h�d����~6*lvcTt
e��������������|��XE
pz�`���3�Q��k5<�����nk�w��ze	��v��+�UL�a���1/�a�����ZNaoVR?\��N�Ii�����B�B{�/�9���&���%����JS�0�X����Tm.�����_��<X�3��m���6�mT�����z"�;���#����F~��Mn�p����K�)��.���?�����e��BOw�vjG"��
�<z�7���a���#D��r5�*���J��mkz\�sR��6�<Eb��U��m�X�o)i�n()�/�Lz�O��
�k^~
��iP��]j?��l�&]�w;��aI=$A��x�]��[d����0�D�w�w���L3l��C� w	-��g������]��T����c�5�d��mk�����2�V�9	��������L�<&(3��1�OfT��q��J���2��3��j�����9f#�{�3���%������
�qY~�uw5���(�H����v�?�@���{��V"���S�:tlAF-���J�&O{4W,���O-�c���
U���Q�`�d�'��� ���	y~]������`5m:��G};'���f��< $D���>�?X���;r~��o`X>U��,g<����Y��Q40�Eb���T�����T��������=���D�o��A�7���������Uc��$��n��E)j����c�s�e�[j����������=��9m����m�p^��&����j��?��=O���u�������o~o�u���~:�@p�p�`9$!z;�er�^�5:)����c�&��v`]��\����o���H'��(�b���\t��Ty�"V��z�<���O�0#�:�0�e}�1�������;b�{VoA��`�!}1!�CP��HA��%eK�`��XY��;0/*YA6�3Z
�������+�C(��[�+�5���|h�.��Y	����8~�y��p�|�;'�N���w'����F������^��%x��D�-n�R7����N���-�Z����7�C����h�Bw���-�Z���RJj�����M@��rN��E����f�����N,���l&c�����r���B:�Zw~��������}8�Jn��pe����&�|�C6d������[)�,��s���&��Nv(���;'��NN���t^��'�N���t��l������7�@CK4�K�w��hv�*�PM�}5��u[������C?��@w�1\��Ll(����/���u��i�-��SKEN���az�%+<�lA'}��bC�6�"����o������!:�W�A�^-��{M�3w(0N?�N�X5s���,����]���Hb�e�O1S�9e�H�tM�)q=����&�c�����P�(�����bZ�/�Jx���O^�����1����g�I�M#X�c��'��a>H	��N��M�l\a��Hu'���|��ei�%�A�����JM��@�t[[��);��c���1�[ G�:0F�4���d�=CO����8A��wh�z|D���h&�M,��Z�g������L��a,��<�2��W����f��.tN�;o��-�"�����aU|����O�c���y��t���
~������`�9Ig����y��x����~�$[*��!�BG ��L��i
��\aP��"�Ol��l�k5��k�f|
���Um�Q���AG�l�����������_�_s��h���������I�K���������Q,dr��2/��c�G���zK��kc��`?�z��U���+�b3>Rj��������_fh=��4�
h�9������~��=q��bI�:�p��He"�������w�����-��1��m3��i��5ms�p����9�?kV�t!����j�y�*'�5����#` Q����<\���f��n���v���
*�u��+����.o��'��5<>d$7�����x��� ��5�������}������l����aZ�������^~�";=�>�p�[n�["�&��]_�]���,7*���`<�h��i6K������
���a���a�R���Q��^��F��I��o�����(fST��I���c���y:7"`����;���SVF�zk ���z�o���������a���������W���!je�L���9+�M�����a��
qY`/*�b��@��]�e
�@4	�!z�5�A�jr>��1f������rI�a6��*�V�k%���&�^���J�X���;4!��$L���r�����a�Y�/�=\U�6<�F�v��S��S	e�$������]�(j��������y����X���G2�m'�=��x���%26�c����Rc����Y6���5k/���l(�;a#"?����}]:��94�ks0��1�;���Ii��s��	�DAC���Y�v� Z]Y(t�npk���j$��z��� ��5�Jd�+���|�}1<�F�����`H�l� �,"�(�q�rw�������jJW�1����.�k�>�\>Fg�GS�����s����a6g���=>;��0J��d�������

�z)G�_�U"K���>jMe}pd����?��{e�����uo���#��!��N��`d����a-�V���R	��4%������Y�
[�8f���t�����=
���FQ�x�;NK��B��Ub=����!�7���#u�p�
��.'��3t}(#%S��ol�e�(1s#g�4�W�g�i!�
���-4����FV���i2. !�����C���9{����l�f�R���mu��d�{Z1�=�����lT�_'G���x,F�kQi|�	���/��X������#$�T�n
�h�J�*O�M?�,��"���J;�����D�(��G~�|Z��5�$�T�J�xtn����������U�+�,�|�hj��u1#AR�lJ�1�x��8�E�m������0�ka1�A,r��W+���Q��+5H��~`���7���t=`�.�������`�F�I4J��$��G[iK��Q���$7���I�Xt.X�R>�VRkv)Fb����&[��t6`�jo[8�F����3e1
�:���F�$��S�oh��oL}�;g��=�+�E���-=�3�O�Xp;���~�����������=K���m����|�x���U���b 6}]ft��_�6aon�5X��6��viyyN����v�v����������Tw%��#��M��V�8o��\��\��������Y�����+�\e�����7�z����7:����_���6z��e�#�7���qpA6$�G�T}U �S�#�K>a9�����!���)`���N�R��+������
�z������� ��%����|��g��s9cGBP�b���3�02A� ��l
��U�k�-/F@������!\��4v���pA|�2��pJ�����~�|j.z��7��;����U�����U�9a&��9'�V�{��y������J�
�������zsI#3���������^�����
:}wh��~x���%I
$��E�:l
�o<G��U��8��~r���M��Y�)G��9]�Y�%5��k5���O��>�v���<����M��,�}x�Q���{v7�'f��� �T8� �"V������f�R��C;'';��:���D.8u�Z89����4R0x0��2�*�����[D����B�{���y�,�_��q:����`�Ak���F<9���VU�����y��;
`����V��� Ya��I�3L����K�gt�����UfK����C����6����2����� a�����E�G�g�����Z����F���EC���j%OlQ��/`���=r<R����$���8���l��k5r4���W���Is�0z���*�A�u6�~�,yZv�a�E������D>l���%��8L�{��^K%O�j���� `�o(�Z���}3���J���F6q9|h�MX&���@u�@�z	��&�t�+����Y��>���tR����,"�z�.5���g^�Q�����Av<����/F��e�!�&Nm��f�@���! >���U��(�wB�����8<��JDYhW����a=b<[d��-�#l������r;����>�������
h�m�N����6/3L�\��m��#�%RE�_SS/&GS��w�<2�FY�U������q���
x��2��c��in�F6n�m���b�
w�j��+6�k*��P40����0��O��K5O��*RN9!0�����$�
��JX�Pb���uC��<��Cw83j�?l�v����K��M��<�CFF��B{a���Kw	�q��fA��ZX�Y��O�a��+�z3���oo����I�,���3yd:'g����]�v��^}�s3���������I�����9$}.��*8T\�4K�9����I�5.�'DQEND=O����;�"���������94u��1,;���L�,������g�h�#a�:D(�^�Ky�L���)��/�W��$5)z����L���@| ���`.��P���\��� ��K��c��������\I����U�Ej2K�"bD���y-�\����A��g�-�����-K��/�u�o�y��o������5a[\�Ih �Tt1��CR��j�_�[go��X�Y��[���g_=���0�W���t����[zc����O����o��U�o�{^����<�������Y/�V	jJzS�
�}_<������9P'�Gg���.b��ws����4g�O�P?����2�e)��e0�N������<m�U�6��������1G-I������e6$�R;O�~��Ur���pa������dFp�'��>"��.���/���"�]7����g�8E���M#l��/�3��sP�T6�y��n%��K��S��b�RQ0�@��	�E_�#����������l�,���EB�w���*�|L1����M;�B�C�`��8�G����H���
��PZ
~��K�/4����t&��Ex�@�.b�nLa�+�ut0��I'�axv �C
�j�t$�,W�����Kf�H�E�GS�Ji����H���J������$�iB\��� >������"KQ�����x��f<;E�=��]�G�����Xy(��!B&��N��I�Z�Q>8�RIX��������*�.�"�d����.�Ea�J����d�*�D��r�����
t��f��D�E*t��F���6�=A�w��:
[�~R^F3���j���Z�hefDl���K������Y��f��!w��������>�,��������E��Q�+j����g�X��71&��1�tm��.I�A@S@�D�u���$�[^����1G��.x�=\<B����
qG�ml@o<�G�k$��/#����R�����;������a]��X�!�����c{x��X/9�����j�@��Q'��ds��fY�,^{�@��O?�����K���H[��R���B[�����<�U2��^J�>D�[}N����R�*�yw�Yw����u�bY};��Z��^��w������b�0B��^�;��]��4�I���R}P8T�������{y�c�����������jX�C�)���.�k)?��mn'�p^f����]�$��{���$����D��InE�*Z	�B�V�O�:�����}+^S�������P����e��������������������}	S���6�0Y�Ap�(M�H�R	N*��g
	������gE�����<����f?;O����M����@��,E��Doh����������t/����@v���G���D
�!6�N��������R�{��?M�h��H��p_��4J�$�#�O�q�l0	������t^�}���g�����}Ny9�9��F��7��\�!o�

�v��h����y�s��i���������n{�>5�����I����I���8il�d������+��
]	��\���u��5{S[a�e���ve2�/�]���9#r�{y��<{n�A��'�a�	�n�R-=�����H+ /�������g�P�6�(g��U�����������dX��X��@u���S�����0����]���{��a�l�h�}���T�~�����7+�}�uV2&�(�������I�\��!I��������d�vIc
O�Q;%y���b"�p�Q�M�	�&�\R&>$�+���������}�����b�����p�^�(%�g�C2�%���ONX#w������M}"�+F! %~Rd�N���'�k��M��z����E1��:Y���{/x<��.bX�U���P�
F�(�����T��C�b]�o��'	���$&�����c:5�)eo��Ne���O�%�C�������77�0��2�D��m=m��*�r�����C�G�4.��Y3�!=I�,����*a��rqu����c."sN�"d�q����R�[�;������������1:hL���}����oz����'O���@����@���P�b7Q���*w~A����r��i.	� ��c����U��^u@ti��
(��5/��&q�#<���O�	��{����x���,m�1�#'�R7��"
Ej�%W���v�(U97�+Y�Y%8ud��8� n���nm�|/��3�`�"kW�w{�_�4���D���Mpz�U������_	K���#�_������l��������������]�d���|b��M����P���}{*�����zK6T��w���n�N=+����WewC�����**o1����C����go��D��VfX��A����R{m�
q�O
A���W_/�'�K{O���s�U|���)���[�=j�7���[QO�KG��{6/$g.YJZ�Y�&��~rv�sz&"��M�F�%=�������ICI;��G�G�D�t6�����������}�Z�p�}�������GWKw$���{�Fo�[p!��i�_��� ���h�d�����j��C	�P�n�ao1��,\^�CRS�[|�+��:���;��w���`���f����=�(:6;�l2m4a7���H�Y�����]����KF����o�m��.��XZ����,���b���6�����g�.S��B6�n6�I{��I����e#o_9��?��1�ZL�T;�|4�aR ��!s�@�;>'������[3�_98�|�CvM��g�Q�bM��d	[������jd���>���J�
����!���SA���9�m!����[!�Byz���o
���w�����}�C&9�k+lF��q��m3���SoG[9�NM���8��9���n�����$r�SN��
�5Yl�C8D������.XmY�emeU�Y��K]�0B��.��G����/�U���������i�D���.���j�Wm	��.��s��+zSq�4�oj:�+rx��C��C��2���G���TO�5U���R��2+\i	k�p1w��QH����,�P���66([��i��nM�iP���-��k%�D����O��|w��q��=B�A���x��"W�GV�k��n��n��/~�t
�+�&W9���N�Q�j���iT:������Q���=�@H���E���Qll�O
�:��Y��m�It�3�FR�|�a>a{>����@to|����������7����YB����cG���H���u$t@0����%�'����JEI���:������O��r�Vg?3�5p��G�_�~Jj\+��G�hr��f=p�k6p�0^�~��;�N�>m��?���y{h��������6����>d�p��������?���1����|��Hc��ut��)��R�
���}������My��1�-+
�6��{��������VU�`)������v��%������Fl�~ PSf���vGC�,����j��Wm�����Y7���+#�M6���Xe��L�����
�^��m~5��c���<����Y���W�����X�
����uV]G�c���������m+s~��]����x[��J��]���w�J,w��SZ�KSi�{S��2������h{
���u�Q{�~�%��I�YT��c��"e{R����d��H��%��X�.�����h��&;,������z{���9k�h{��zT�����S-���F��!q������T2�]���������S�H�g�^$}���Q-��P���W���Jr��t'|�X$�k[�U��X�v���B��}�I��(����+I�'B��d��^��E�1SW�C��^'�sN�G%x6�"=���R�?����Y�P|��>��n��y��������C����05�\K2�Qa�(���d92z��2[��L�>�Q&�yS����eU���"�V��Zl��<�y�0�D+�����l.o���0d$JQ0{��_����������p��C��;�68�=0e���b��c�DG�O��O���Y�[7�<1Zl;�;���yX�
��dKb����}`�?����q��Bc�W~i] y����Eg!����
|O$r��	��#�F�c��#R�c������?+�)R^0�0bdrO)��~Y���o���9��7�*��|�#�/\��i��B����aF�3�K��l ��}
�� kY^g��,��.}S���B�B��Fr��������B�/��!*����O���x��(N����}":(Xm�����Q'x�-Z����&H�'�&�%(��E�������H\m@�b9�X�`!l�4a�U��k���M0y�Y!������xl$%��xu��\����a���A�D|dr�U\rU
ck�pS���h���L�k|�q����\	_���~!G�s.��G�v%nQ����O��RC�Se�O�sG�n����gs��4S�e��\�qx%��Z�'	b�4G���N"wb�����
f������OK)�>%��������,x����$t@zd��4b:(�$�����H��<�j�&f&P���J�5��B�G<.�l����h�� �~~���a�7�(��h�#�2��l�cu�Q�������Vs�Q���y�y���t���"�+}�(w�/x�(����%�~�o��u�J�J����-���|��F`����s^���V;�B�\��U��G�>�Y+TYt��dv��~=26Qw=X���:�%��gCV�p����a��|J��o)92��=>�e��!���H
�hP������+jGj�)=�U���*A�C�;AKf��L��������\�������$�M���VkL1����i$������A�f2��KO?G� �"�g�@*PC~�4;|N/���� �z��dzA����G���v����F�A~j�yg"����/c�R�	���@U+�tA���g����L(�6(���%Z�,=���Oi��r�~G_��f��m\��� ��Pbm-r�MD�o)\(��&:�e���t���A9��J�@E{���Q�C���~IW��A�fL�,��G��n�hq7f�2�;��Q�WB�Wt������aF�d��P�� �����i�.�����%���L�����H�4�$�5������7cp�E_�+O�X�=��YH����[�	5�%2�~����8��J`^����7���L�U�u5&=��I]+9��.������"�%Ff����<�����*�>��v����JG����l+t��jB�����XJ4
������AA-jA�5����������S��Y!`a��%az�������D�m�Y��L%@�p?�"D���������RG�����iv���(�u�qL������a�c�������aN=x�.g?��v�^x��@�L�y��:+���y��H�K�e����-.}�f���tz������2l�D����=.:)|�h�3��Z��
��F����0����e�v���:��?%���N=	�2�g�v�=��JB���w��
�H4��d��i��d*p���Z4��N�������q�4SA?�!��H�Y���"jw''k3�z���K^�t�����d�?��#Ucu�������R����>���4^d@2-����={��%�����>���h�W���r:��H�/A�V1
���TYhY�k��a����J��j\��*S�P��P��s����p|���;	�/�.�=I�������hT����
���+�����[yXBnjm%���U��=����+y0��{m&�VlNX=MT��Q�9�;�, �&�vH�'x+s�����S�I�>z�d������<�'�8`�9e�+���%�i���C?<K�QG�6����f`���V#!���@�}�#�,=�et4��9��g�$��|$�'�i��g�:�1r�6{�	|�0+b9�`��[a��d��.g�`>���%���#�#��f?b8�����
�|�K0����!�F	����h%����.�e�����rbF�:���@�%s;�`5�mK�5��������w$P������.�fx���o�+�k�I������G��j	�F����eL5���D�+��"���v�J~C��/ ��@>�����[����1,>;���9����yU*����o��$l'R�o�\���QE���|�A2� yP������?��8hV�������W�����,;���>����v����"(>�
/Z��=�V���
�Pu�b�	�����cV�I�D�7x i1��'�P��5�����y��x��5���I#����nq����lv6�*��_J����L��p��Z��������b�S���7�������m"�]���qo�7-;'m�IU�P2������J�76����ipT��1Jze�����_��G��g�C�e���t��Q��#\`8K��\F�?��+��������VB�h���^��������E���(g����~{�1g�7�)�5�Z��J:�$���@�F�hZ����z�4������e����Dn���rj���8-�����Fs����,hJ����
��e���.����]�����!����-�,^v�WU �-��������h[�k��)H�r�0A�
�p����
��#�]tC��h��-��]X��2�w�@r7S��?u�F^Q�g���P�&��l���"�N��0sz��J�F��42\w��Q��#�O���x��D���~t��W!Z8������u�����_/�y__Q
���jS�g����%�[Nktb�5���i�n�+Fb7�_}_���By��bp�#
MqqM�1��3�?���<ja���I�0��d�I6��}b_n��G)�/$�h��x��T�������
���L#qk����ju^��B?�(B���l���d�v�L�$��ju�@���x��i�3d���[���!�����:�[����T���.m��������_��OT}���?�qV<�.Z�*-+b�sDJ��h����bW�:S��a__U��J2��M���U6���=�e�����(B�B�
�y)4�.F(���PK1��Y�����KV�53��+V��|XJ����y
�a7�2l'AX�S�j�����o�fY	K�)e��x��O�;�3��%�>&�OX ;�q??�� �m�~���M�t m�����x�C�jV_aZ3=�,!��@�]�+�T;����{�3�B������Z�p�E4��	�f>-2v#��J�����x�/���ZjC�W���'	��9����X�`��S�QA9�w�8ZX���~N��[�'���)\���)\fk�rl\��k��\y�p!k���������eu�q����x7d�%`�nZd�0Q�q�+�y��
�,c.��+"=&1c�)g���[��e-�)W��N8$�t�hUU�(�����W���s2V?'{��u�����/v�BB�]~c�.J��'�o�~V R/�Q(�������FZLr�!,�;����n�E�/�I��
����@$J��4�bd�I���6j�U�Ai�r�	W��=(��F����S#L�fzo~����C����\���i����U�����!��J�#��T�����IY�+��J��M@d�Qb�p\e��qu�XW)+|q��ZM���J��|(X�c]Y��x��m���n3�W��TZ����'X\���������cd?���!Dm4?o��/R-��G$(����E/U�\��6z>��$�������o����y�����Zw�+@������CK��$8��m<�	0��e��aht�X����*���������^&���Lz��a�����F��`�����{�Y�)����i3��m�u���c��y8�����V�����g�������r$I4�N�Z�X
��}1���?���Z���^�\(5�A4d������m�"����\�N���[7�$��vC�f<���c�|+@�
��u��5��	�x�k�J�T�6����J�G�?_�E����H7:`���s�?��nTX1����VO)����eL$�X�YC��\�1�pC�GL��v����w7KaGn���a7B
�Q�D6G��B)
�N�a�=��h�������������������,?�f����r:�&8!����7Rz��Z��\Y0����L2����](����
�T��RO���T����q�#��yJ�)5:�������Z�?�R���P��$1�4���-�#o��������5q8��P�4����YHy	r�R(C��F������9QdZ�
�G��d����5����n�e[&�S�j-�ExNy3#��M�L�P ��������}�P.��q�1�N�s4� ����8����\������.������x=��M�TU[��������4b���WV��5�h��.�i;���-t�mF8��R1%I�O��A�zv����k[l4R�����y���.M��Qnl<6���/��C�'g�7��{���������j�Z��|�P����
��W���%\����Fp��#�-X��}���I�&+5"fi�~���jv�J�F��|�1T3�c�����E��������o�*�r\I�u���;�K�+��8
t[��%�]��Nr5��0�*��5�������$�K*4����`4Z����@]J��u�g���_i��5��g%k�!;*��{d�sD=#n�����\%�`,�<K�j��Q��M=t
���3���y+�H�
S)]`�>~�9;�K�fCkSw��#M�EdU�k��������fK�"�j.��������W������3��y�����D������YW:��-]��'3f$Ab����(��0��������\-����A ������0�F��!	���z��"�L*A�W�)��ITJF�/I�j����/QD��$����� �5�)�w�o���KX���4t+S/���|����O�H�g���Y�����.���h������c�^d�H��O�]�q�.��w��P�����3|��I��y�3�n4�8�Pxc�@CD�y!h-�f��6���VMK���J��S��{C.��L��4_���������u��.1�5_��MIx�a�jo4���6�����>�i1�5-�`��}
z�U_�2�,�
k ��
��� 8��wX3�������'���.��f1�V���"
��hGg�Y6`��OAE���XC'����N3p���������e>���M���H]���x+WV����Qu������9L���[����k��^�Ul�����d�adOZ����a�������i�{��@F��
(k���{C�/o�f�x����I?+z�|��/3����F4�q�]�hSG�����nA��tq��T��n<��;����B��C����3?��������v�W~s�@[�~���n��!��K��_U������~\��a���/�]���'��	�p0���"v�J��1�/d8*$Mvx'X��e.rS�%F����5��g�Wg^��C"f��O��������#�M?�����K:%~�<��fU����}	y'���������(
ud�o��'���B�LvH��0���O�bAj�h<
"�
���ii
����n!O�6{9����\�������G��E�j������X|���#V���q	o�3}�O���l�
\o�z�����?�w���	�!�"s�a6drSUJH�(�������I�.2�APhDU��=������r�uYj7�]p;����|#�3G����d#'j�`L�"��i�v�c[.tT	��pw����)���T{��g`���w�x��C�x�Iz8������V;Hf��h==;Q�������;�k�YXC~l�+�����w5�����gP�\���>�QoJ�9P���{�v@��"���� ����0��+��l�=�rK�m�>���_��n�o~.�^%IU����������5��C�4��&��"k(��M���.LQ�6�&W�����pcI�Q;4!�|��3���f3��*�S@��Z�����|�R��"�@0s��F��K.1������5b�t����4��`���W��A������,�F4M�e�+��F��k�a���y.1��c���)��IOl�I	3��!H��$���`t�L�l����^j4��H�t��U����e/0�	���Iwg�?������d��d��r7���f�5����bu)�B:5Fz��W������������������g:fD:%+�D��q��#�����t<�:�8����{X������[�����=����>���YjT��,�l5�	�}m�����������w
����D�N�%�xJZ�*t%�=,����6�C��0_�jJ���~��q[I�We�}%Q���=Fu��'_���m��^&��{;���]�iD�uPBs��Xx�'�M�#JS)���Rr9/�r����e�v�
���JT�������h^_$ �������yv���h�^[�����1��a��U@�m���!�
�2�����j� ^����*W��@S=%w�SN3otO[�1���IK"�l�I�g��?U?�'u�CKWG�.P�.�O����!C�(�Z��0V�����E*�O$�'�f���x��2CB
�|S%)?��&�?1��`�9F'B�J>���z���"
����(�2�����r:�2C����|!���Y^�����h%��O��^��u+s�>R����p*K�J��AvR�S�|`���"����q��J����aI��q6GPxJ��#�����JR��F��-����JSs�^w������(��������I��Q�c�`Ho��&L��$���T���~.@�j`����0�\��E����3����-�����1�Nw��(o��iX8����y�G9}4��#�3���j6�ux��2A���;�.��:L�7�5��
��(������'�ave?��;��2';�Nr�����3�~���/Xo���(ys�O[�b��n���<o}����BFl!��Z��OACIL��
�C
)�j�������,$� �
�(y^��!z��C��\ln��]h�+�xkJW���������h)�����W�o4V7a
��0/J���a�_h*� m�����,<>�5����z!�v4,.
����Q;�/�1�=���P����1�w�10��%A$���:������e��#�����{�B�kci����`�jp����c��C�����h$��:�Vb7����9�3��G0e�2B�L�U����&_��(�Ex���r���h�g^Q[�ny��x�L~I��vXY�����OI�&���Z;�����0���_���W�M:�PN*)4��Ga���g�p������f��!���^��`cKKu��LU~H�2�;Wty/}��+�K��j�|=V4l�a��>}�^�~O1������]oy��������N��dCu�TV��P�F�i�J�X��'[yCZT�6�����>�R����?
��DOpA���c�l8	���D�;����Yw~NY�j>u?Gs�K�����/(�WO�@
�����|t�MR�)�u�/�*��'Jo��h�����������$M;*�;J��pUW����V���wb�����N
.w����*:����'�A?����:M�D�9$�#�m���{
R�{�QK+�I���KS�H1�G3q{��G��UiS-7���M_$��������d/{��}�h������K�S�	�<��-A'���A��4+��<�����������5��v4��Q��8����z�D��os��H��
����2���y�H$�n>s���j��~�N����.��p��{�,�E�����vA8�U��M���V��5�G����L�����R���sx�H���J��I��sc��6��I�Eh\ygrD��%�k��h��UW��~�0/i����H�����\q�J`-!���-m�
��ht�U
.
�)���<���	�T^��V�R�v*7zM��������:iQ����01>���DYt�����|�����Q
�T��^��Z���/�V3��~r�����r������jax���.B�N-�������~����	�f�<�D4.
_m@*����
~PA3��.����IK�&E�&qt�l,q�
�x��\?I��FK��r��B�f�N��^7�p�K�P*�L�RW� G_�

��y+p�����C
Z�L����">�����TNQB�����H�S�2���(p�.R����\})?g=�4^G.�	c���
�y�^�btG�lD���NW~���`#��_��������'� +���U�������r0v8fc�}����hEL]�?
�^����ht�����zHp��?k]���c- 3fTt1�����V �3����.�b20-PNz�����b'��ap�9��n<P0W-l������{����������W������\���Oo���T&�M#%
=X����#�y�x=;h�"�$�#M�l0�P��v� CK�7�F6����g�����d
3?�`��+&��d��"��.��R�d������G�Q�
1F,~��49��I@<������%���;9:<��s��x�p����U�E�p��/�k�����S���3�j�(�'-����B	��0BKP���F��r�fD�M�6�	�����,�:�u�?1^�u|,@E���(�����E��3zq
�<�����_t�Q�(���}�t:��0`�C8�|)���+h2�L=o�D����xF ��_�z5���h[�x[b�=�������������-rCX��C/��,&�q5i~�z�ZpI!�&��i�R�	�o��������J�\��V'�?������np"��Sw^V>q��k
w����dI��@@�[&<��Q2�]$����o�G]4*S<T�b���V_�X/!�*@�n�)��
�-��6�E����"�������z9���_	��$���d
#2�����DE#�D��_��YX�Y�����a�B#|{������d���HKe�����v������Z�b�C��b��/*+)H��
�J7L��8,��b���r��t�������$�l$*yA��Ru����}���f���O��4��$�ge8L?�����J�U&���lO~�R��+LN�L9�S^�.0lu��6�k#�����e���z����2�2hjs����4;���y��~��g�|,i��U��d����,L�(��n�~\�N�rw�cb��yc������o8��>��7�^�c���Q
W�7�(����9q�31n�X��L�=��*W#�/��k���Tj�I�������K��>*��#@c��z<�����J�jH8T�=%�L��u-G�!��A�X����-7p�s����j����GX-5v��d��|�4%`���,I�������J���(��_qq���CG��K������������$rI�j6e�8��Q#�H	��e�i$Sd��/kn��ZH����{10K�X�7E���*�@�\������#{�mpT��!U��r$�v�&����
:�U���F��F���m��*N�8�� ��:N��V�yd]�`�>�P�����
��|oR
*��.��w�	����VsR��E<�_�����Du�1�1>����um���Vk�����X�J���L�s���RXJ<�RD���I�nZ��������������%If�7M�KT�k�\�;�!e?W��JA�3/M2���6���&7LC&L��$``T9Q���	���j��s�.�$�� ��S���k4�������}���������o�cp?�w�%&�����(�u�R6z�)���f��p�}h�y�k��z�n�,+Z0qa[m�,�Q�t7�J� 9�3��d�� �|�B�.�������������������"�����F-����O��b�6�����b{��T'�#�@fD�JJI�����g��jW�ymA�p����=��Z�F�k�V��*q��w�o�j>����~���[�k��*b�O����.}�Mp�����x����)��M�1�f�59pd[���5@�`Z�����9�@���C��X�b�����n	K��� �(���f����6/5��_��yn���;';gg���r��?�����w'��243�6��c�Q��#1�]��Zv���v�t;���8���f�����5����S�ujM��������F�<�0�qB�0���;9�w����9H�7Zx��|;�o��_��~��
Pa�������d��t�<T�Q�q�c�1r�d�EN�+�;�<�����L�Cj��#�)"�)m�q�P���m���a���<E.���+V_PV�H��V����|~������%���k��7�*��A�����W�A��F5l��>V)�"fp���r3~���^����Ltw�0a>s��2��'F����!=|L�����_����l�W�����J��{��;��!��!j��"E�����@�H+�B*�^V��P����b�y�<
K4p�!z���_��o.���x��m��a���W#Q�%���6�����F�l�����l�Z��$��'-��BYX��dsG~��_3��>�������+~��-oi���Z�.��e����V�����_\5x�JW�����]�g��[�3x<�;L�6)�~�0�g��_��N��-�%���u�
������qB[�����eu
���O�x��}o
�{la��'Z����y�~(�(TMS�����a�F����w�<"��:��:�3�|������T4���-R�oz�_"��5�����CSag���ff"��cO������w��������!�w��0����/�t�����?�L ��vh���_������*�1e�`��1�zB*�Gw+���HN�^�C�s��yfW]�H�����(��O�ie�j��g#��;��(,���N�~AR/����%�[�'3^s7]B��;9:N�v^� �����o�4f�;">[x����b�������(J�+"+UAu��J���	lE�C�i���x+�#�
D�0�����_���PXQ�8i����S�`]
k�����B�|g�Q�b	���l�0�;�w]�����
��j�e��]6}��_�,�|;&�����A1�%�E�Rv�����,��}�xHW� ��Z.*�W�G�MQ>�
�v�c���ps����pl2���m:��G�c�e���
Q������g�8c7���@d����jkhT�������7]kr�2O~\h��/0���'������\���\t�|A�j����D/�G~�;����v�V���t��������^=u^ax�o-{f�Y�,�M�ic�ws��,��b���1#����6��v�!|�������i��7����x�_�Q &��!T��W�s`���8L����Ph���pT(��������0���*=��y�����������I�T0>��#������u�����%�N�!���1�^����M5���5�3�������6�j<5�]h���S�1�R������NF����VF���5���k9�^1-+&�ac�~n�S����0G%�<�>6����/j��e�!�eQK��8z�le��#���]������`�Lau��J��U&&,J��������yF@�^Q�l|�;i����7+L����j�n�'e�J�#�0�����$�E
I�%4�H�U��a�J���P1��"��c���.T�.P��b�w#�>��-{V
;Q+���W�dD��?Z���Es|��,�����=���]@N�t��)T�e2�
��q`�@k�V�������a]�'zM��k%��K�akOx��6�S�x���m��gM�������^���+Gi�%������'B����D����8�,>�xW��3����������/�H��k
Y���|�����pJ�?Q���
��s�g����|6����`n��MQV�V)� �dq�I�rW~���������G����&�rf�/Ch�h0��H��� V
	oo�OVm<���/	N��hA�`�\����yV����-�������nH�1�c<��2[�"�����n/�P-N���������hG�N_����t{�g���	zj��Y����C�P+0[�n�����M��7"���g���Uw����Rp�S��[y��U��Z��������;�g;goO�K|�-'��Z;(�J(��5v�>:|z�0D��Q�H�;<�OK��/�KK����(�0�	cZP	L�����G��T[����rbq�p�e���
MK+���;���Q����5_�����da�����"���|f!k�����/�d�K�}�`<�`n.QG�)���B{�����5-���/�(��*�.`!E��D��+=�E	��8)zF����Gk2~���E��-�R��J�p�Nu���hk�vA�-���Z$���HFF�����T��V�H����6K�����LX��Q��7tD��V?���g����|�'I�M.�T����y��{�������^�?��"���Cev���
�j3	��qo@�����Rv2�+5�v)V$R��D����;#k�T>�jz�����Kf��tl�����'�b�������\*�ptU������|�{]*���
;�n
1�q�����S��J�L
���u,�,������:��b���k�0�>��:5����;�����FW�a3�\p�Ga�Exy�Z�@V�K�r��s)�M�SXOb�^�vsB?�OA�4�%���(>���4�����GZ�L6{8T�A?���%_��m1#�6�f�]�kz�m��7/�2�Tpr���6lb���E�N���0dv~��r.���T��i�o�dC����?��<���s�D����E:����'�Gg��F=-IE{y�*��F������pix/nE�G�G��O�H|e�@��|����}�J���Hw������?�Z�����|vt����7,a�0������V�����������j=�O��uH<���[f�����|0����<��59�3WGK�N?��*����/���Q�� �e�����X��k~E�RS	�v��_�`_���R��N�Ig�����k�5�� ���:@Q��~�a���Qu+92w49�Z	����I�Jh�.,�B�x/2��4R��!U�3M���F����*m}�q�A�z�0���FW��H�9�T,f=�k('���5.�����,��QG[���h�����4;���������Pk��o ��h���F	��I(���E��x��[l@�7o�������_����G2�)�?1��������b���)��������U9�?D�X0���O%K�-���A�#][�<��}��^f���^q`�O�v�+	���S�n����I<-������"����������A���aG��BA�f��f�=S���zc}�?JKI��")�Q��Z��0�x]�T�f�����L���jQ�1f����_z��( �K���E��,fsT\Sub��)�
f�+�V����ReJ�x�
u��k4�m�Bo��T�t�
�����G�[��W��e���H��An�SIM���cWQ3��7������#����<���@�=y2�6�j@��N�k4�<(�A\�+��m�v��Q-,W*��x�Rsr>	HP?�*e�{���qn�h&4�2;G����YS@\(��%����{��4�"A����z@��5��,��iN;����n��x.�47{��{��i���y����ng�L�)\�)��?�"c�~e�Ri�<����oG�E������i���1e�����Hn��Q$CG���t�By�X*���)���,c�I��O�903��G��!������N�m#��!y����s�b������}��:�~D�DR��������2qm�\��D�� �:v��M��"ZE,����v���l?����d�'�1�w>�<fc�}��0�C1cD����B%���sy�s����������K^���Q�{�|6��?�j�f~�0r��~Vj$�(z��<��������A�d��I�l��������c��e�Z������A�E��m	���H����
#6L����4��8�ha"����/d������u�G�v������;�;���V�#r�c�o`���[���;)������.�;F�����n7�R$&��~Y6hV#��x�a�h��q��������'Q��s��N-N����s&�8i�w��(�������W��=��b��������di��}0V�+��n:��d���%���s4�=���s�o�03����o�|����#���a&<B�>'������]x,�H���:���)H�CY�qQ�
�0���Q�=����D�V�����m��a4KO���������������L4u��� \O;�w%���m�?���D���{h����F��#%gO��Q��j�IU,������t�J$�����N�y�������2M�v��f������A���,']��&[�8;�|��%n��jlk�MCy����s7x�����S��9��&���z��s�1�j��k�mf�!@qe�Kd9:S/:��c�
���g��uIkf�!�������n�S��TA#�}���pO?���q�����?jJ>A���x���T�u���H�F6{40���V��,5�Dm$#�gC��Ti.`C����������x�b��e������*�R�w����AT�G37D���Z]q/�����8���2�F����u�\��&�"GZ�Hn���),�d��Q�������|��Y�W�`�2{���A�]��"�0���n�.����=�MmU�r�z�v.�tz�0fU����E������|?7����9��V1�m!��[S��%:�����^��I�uC
l+��<y�����^7��}J��mn>}������766��~�q�m��=�����_�������'�'�}�U�����rHY��)��[�=:���7�	:�F ��[ �b<��X��`����~N���L�����rl�O�M}�����O]���L@7
��0�!�5�Hs	�%���~�{-�d)��J��WN}��0p.t�I.�4R��XP;A�MQG
L�p�R�,������H�������_IJ�G���`�E'�>L,�"�U?�m���7�����������������t�y�.�7���B�P8u�T�}}�@#��7�����mb�Fm�]4�k&�LJ�M�u�`t��\�6�|���k�������<k���N�y3/�� &*~��6�`��2�������8$W���ag�;D-^n�t�]���]���Sl<`��H�|$�8����`l���m�5��7:7X�����e�l�W-@�u�S�/h�`z�����R�O�����.���V�Pi	>��-#��=�$��=4�i9��6���
�|*�Q��p�N��
��1�'�*@��A�D]�M�ms?2�^����v#�n�Q�Bi|"!�qy.C�j��=�:�(��hT�1��'�PB��D\��x�9�k��`@� hm�tOoH����������O�P��������X��n6�B��S����C#�y��.c��Bfi����d1aG��L�H�����T$�8+�v)U�4c��N�,ag�=��b���89����DD���>E�������_~�n�fp�\+
����� �:�?e��}B.��1��J.�e�N�9B`2"G�	hH{[{o�fv�;b=��Q'E���6��9$��H<�|je2L�Dw~�i�
��"��S���&��}�H���w�X�-l�w�\r�*S�Y5D����������F����R:�6��#>iL�5*�����.���LN��S0���9r_�G�f��`�/7�Zy2Pb1�t�R� G�f�����~�'S�aY�9���I87���p9P��D��{@�T��J{k5��
��� UL8O{�l*����J=���
N��[�a04���d'FR��5�Q{�FT[��]��Q��	k�-Xn��5r�����\l����l#@�!��I2$(^e~v����`k��)3�D�/�������2@T��=�������C�i��V2�so<�
�nFi�S/l�Es��[��0Mg�����r-��fT��n�;��3'8I���n�>?���S��"����^3y����
�?_���q13�����W�q��r��<O�_���N�{��g��������_��Dt�/��l�q��G!Q���OFP��r��y�g�����#s��G��a^���9~���2o!"9v>���&��k����Uz�h����!�o����=s��i
F�)u�
��DZ������<0~6��\���&��y����;��`fA)�YZ�]}0��A�����9j��K����H�������G�%����U����H�}��l4��Sb�T��Z!'�������8�[��z�'m�B��2r����SM?���%�w[
4a�OM���y�b��#'�E{#�gE�s�3���
V`R�����{7����j�3���PTXs��^��N�J������h�#�e���&�R�Zhlq6A���O�C����pmj{E@������{���AGt�XHq�T0�t�>%S(p����&� I~��7�Wdg��pc?g8���si����K)��G���<(C���p:��FK�{��Y�f������zp�����/t �%t$H��%!a��w(`��m�\�=��R�S�u��J��pp���.��?�C�[��;$�]eB'��x3�m��uM�k�,\g�X����C-�����l~�'�k���l�5%��d��@6���Sk��pBK������"�����{����M�0"���>����i����&��&1'V�E��)qR��jE�(������������{?q��j�l"������ZP������/��=��?+��G�6�mefb���!��{�C��v��WR�S
��F�(@���`3��/E�i<"��� ����)��bn��9k��[)��h��&�+�Q�=�����_�:�n�k�")��H�Hw������p������g�t���d	���
K���Y6����F4Z?�-6�+3�V�s���>��5��!���(Ez�q��\Z������|o��%�����������?9��;�"7�O���3���M���C3��l�"���P�����f>�X,�9�h�}��o����p8V
1#c����7Nr1����
^�d65v\i�������KF~��2-]��Cr�����N�����l���S��`��0������xf���KOf5�C����\�7�
��
S���;MofE��Fs�"@�O�z�H�H�������S-����g��=l3V���Kw�$�O�L�N� �_d^���4������F����|�
��Yl����j�&��E?���:�|�lx4Ed�������AH�V�K��3�#4WM��\�����g�F
�w���3r�NB��+��M��s�(������G���	����O9�Q��p����]})>Y���=�[�G����[]+����'?�d��� `.���#-x	�h�z'���lG��������]��g��]U�G��2��[=��n���m]��Z
zi���-%�������z��W>:���K��T*]y5]H���)�WJ��R"�~��;�r/�m����1kU�UU?��*�$NN���"�`g�H�z����a�@X�m�;�q<������S�v�5�`�iIN��c��q�������s������*�����.`���_��=8��i�ma��a�li�7;��qT�Y�\A����[n<���Y�
�/������������������.��<"�I�gfC��^�L�w�:�{6�C%�!��D+�{c6���D��<f�4z��{Vw�i77W��)Q�Xb�kiB]���xO�j��V��b���A��=f%��k_5o���r�����\�;�UH�Z���G�]��.r�/`Sf�e��l�����@i����-U[�:���;�\`f�NX������%���K��*�V{t��6:]*,��q1�B��V�+O��U5sI��T�i��G��\�0�zF��mn�XM�7\"�s4�lq���[�B��+��H*PH���.��R��:
�=s����+�|B������q�SL��Y����.���t*v�"�.D!��"�x���TFZM��~������H�4@��H�h;�Nk1�ea��Qv���FJ���eBT��ZIE���Pkm;Y����I���tqg�$�����8Q@�_�d����KE[�J�9/���T��K��-R�\�xB>'wmiL���V	���?@�p`���l��������qr��{��!��N?��e���2��n�����H�*`�bFV-�TbQd8���k2� >F���{,�U���3@��E�Aj�������b.�X�u��f����%pp��n�����Bn������9T����A��+������h�Y�9���I�U�Ro�����K3�`8�[�A�����=W������wj�v��1�����-�s*��x�FuVB��Qj�6�
VrQ�G�fu	]����d
c�"E�K/B{��B�5bdi��.
�����������}�F�!����J0�Y�~������Om��*�:
)P����&>����F������GgJ*a�M�����=�k&�C_�5��/=��k66��c6 w��������PKV�7��Q����p����=���B��;D�o��J�y�/�����Q�)�!�l�g1#���%����\j0<�����m2'0�nKv�:�;-f������H0����0L���r��C�a�e'��ctO��0���5��z�cQ�!A_�����eM�t�e(N������W�yct����{���< [��:�W�"sTGX��b��v%���}K�l��S	��?����Nm/�A^0;�$�i��Yc��^
Xo�>a4?��W+ ���y!�^����P�"M�*��L�`��]�}? ,6�P�%5��]��.\E@��K���>R�t�#����.8"��������9��m(=�.����Vm�UX���������7fD��D�
��s��P����h���ua�!�AqH���U��e%��O?5+��
�n�ZP�`����U�������f_r(z�S�Z	G	���t/?�^o���JYs����AF��
�6�EO��v�u]���#0� O���T9Jb�Zz��������!�4|��
����]�<UN���� � y���Qi!�����}(�qn-��tz����_D319�@8j�+?�2K�s�kQ�
�����"S�c�F�x^��SM\�6�x2�/��WCH��x��>4ya��"� q���%g';��;�t�������@�*S���0@���V���K���
5�R�8]#�>�B��[��RE��l5E�#�fs�cl,�MM�Rv�d�%Y!��s�%8�Q�����\���Q!����h�f�Wb8[\&M2���"�C�zZ��5"�3�x:�Z����qT��~H�S�w�'��tNZ�_�pAU��l5�I2����&#/��>��"���q��(8��rmA
�
�O��]�g;�
x��$�$gSY��t'��8�������_}�H�_��������.�M�?��q�o{A����?�8�&�5Q[�{HHs�:b1��n����M@��W��"�����(��S��w�y��3<��fi2�
��9ns`�LL�l>�.��u<K��9�?�������;{���sGX"�X#x��6kx��xa���N�9��LHDW����
��������YPC4�>���b�TG/�h�k�-I�u�����9�%'����7�j�B�1Z�G�v��P1��_�Qg�0K�&��K�����U��,8�[���a��������"��"���Z��H�.�"9MW" �8�^��X�d��MK��8�5��#f�s<�������3���HF4����kT)��E�~%���{lT������f�e��ia��n�.�x�#$wC0�`�u:�PA�4���Y�hU��I|�D��*U]���Gk7Al�vx����fN���~���������q2��2�59�H���������EwX�jH���q��n�W�����IxJ,�1���"i��dwY�G�/�m��S�T��C��!+>KJ��Z�M#�@?8z��fQ��O�#	�vx?
�9����dg�J:�8����El��z*���pN�:Y���w�[hY�c���dycE9����������
���U���[+�dYU�VTe�1����}YM7l���r�vn���&�"���$���JY7jH?��	<��u_�O����Q��QK~/���lA��Kf��
��T����ap�/�}�W��4@eA��O��0��[���$EB��P9��n�=+�����A>�����c���9mP�&�i��|�R@�#���;�{W�+��%�Uj�������2�R4i^t�f�����H`B�Kw����������z�������D�OC���B�S���`�?v8�J�f�����Ut��f����0_JQ�e�i^��s�u�S���� �������*��d������������K������@e�Ewd�E�����J+�3s�sK���x#7�v����\'����	�1��N�����RwVhB$�H�e���_Sb�t�n$��"������(*I�@�Q)vC��*LC�
�F����f���J��~�
(|��;ft���E���F�F�x�V���~;��-Eia�D>Y�,P��t1�+�r-t�B����F��?�������D��{]��",���F2�����"�v�u$� ���O������eY�r��b|���> ���E�4N�W���8�����e��|�� �����G�<��wWQC3}8�a��7�����.(o:�Dh�>��������q/0N��#�k��4]�o~�	�XS��)�������	�R���
���V���@oT�F����Y����Z�{��=������?\���O_��������@��N�KL�������?��8J���gq,t�<J��C�Be��5��_�H����`39�A�!�DP��<��I��Hn3.��OFY��O?z�z���n6){Y5�:�D�� '\�1��+�28����^PW?���h�cI,�E^s�x P\zZ�f#��S/�?��5�V�� ��h���rL�_,���T�rh1������m8�j
:�~`�����<�����##�S��d���y2Rx���KpP���r��'�V�l���d�`a,aG��?���&�pD���aI����=tH��^T��&[W���9&pO;��zk0r�yP��&���D?�+@L<�E�b���il!d�(���>�K�Z5)yh��\�������F:���py'�.������C��0#�[3�)ipD�X3����#�QC�=e�u����Q!�(I��sb�1)�6�4� ���eJk1�`H!�0t��F��]A��-P�K7�<4=�����I���U��j�z���R��gR)yR��&�vU�"�>;K�	�B�nNBz�B���T����v�^�VA���e�f���W��\�sZh�w�Ds�Q�b���9+��Y����p��X�9O�����!�\'v�@��T���x������~��a���~��{�U�����\*W6�z�������I���i��
�R�j�O�b����+�U�G��cs��_�����
,��G�;���RNm�����r�e����D�B�v�A'g2���d���C)��9�Vr����/�jVH�(#dF��e�:D�J��l/���.Qxq�O]F��l�%��\h�p���n�i������-�������i�0w����0Q�fr�<��`iao7����R��Y
���MhM!)�|�
4������K���������*�J	YBo��.��
q������]�UC�\�� ��W������8`:�p2�P����Vy�AhWFL��.,w7Y	����DI���p5�~P�)iX�����{��pB%���V|�����d5����m�#?%M�u}1��Ja5;2�k���Le���J�64q"��l��qdv����jf���
ga)�5���|#�Zd������BYs
��uk�K��|�|��V�dn=��:��g�>!<����n4(�D�����_��%�H��� ���@tS�(�G�W��G{{,�<<�(+��J+=��s�����m/��R�Te�0����B���6AJ���o�g$��������'����f���&�@���7�?z����,F|��0jyovg!��,�)a�Uo��!�e����xT�~�<y��N�llD�E���G!{��
q�O���,��-���@�K#y
��i5N:�Vc�3����x�&��l��������P?r�����41d0��]e���P�-�6��@X������%�\���r,y�WI��s�Ip�TWc2�q%�a]��y"I�s)�����U�Jo}9(�j9�i���l/�O�{��������z/g;':���'	/n.m#a��+��.��EdVOk�~�M���
����~��c�L`�@�7��[���MLG���Vp�-hU%{�S����
��o�a�Tj�mu#�b�B,�Eb
^��~�+���|��@S2���a�L�3�$�@�q��G7e��������*��������H����[(l^���k�e����D��)���a%~X��9�$��
�J��`��DX?�8���L��-����69��G��LK*��^��0]�
:EX0[]5K��6�-J�Ds
�`���z�~dl�|YEh��XrG|e<b0P��B�w��o:\�u�#�9�K���/�3����
�0��ky{���q.�� �x�x��^�-����8�z�����������S�b,v�^oNV�P��n0�
�����$�Z���w)��j����R�J���i��0lGFM���xz���-g1�sr���9Tx�G����v5�?bq^�!�-^�-�2;��e>�����Gs:���*���>��m��������R��E��Q��G���z<*Xr�6v/o���_aq=fE�*�~�
+���,JT��dAaf Iu$��cdvG����kD#{
�l}�lc'�����-�'
��F�(�%V�� ��Q�����7f�+�Up�_������>j�
�,Gb��*�J`RMBG���L��Q���+��+�����HK���.�@m�L
�X�������TeFW����}�zs�;������aY�9n��A�un@/���w�@]uk����5��i%���c��7QKF��c/�{$�J��
^�c�;+eE}�9����C�����j�j@a���J����*!Y�m���0�T���\�h\<�Wt�n��"�:����[���{Bl��@*qI�l
���yY:�O8F�:u�������L��)1�
���a1�cD��UR�~����B�7��-d���PUk<�Il�To"t9G?H���<����T����:�bC?
1�c�%����F�a��C;y�*i������a���V���,%OH R���#�.����)�N��e^�����;*�1����p���z/V�dPYmE���(m�jEb����6Ig�����s��X�?o���Q����!�Z�9Uwi��T����+�U����-j���r��#Q�W����1t�1���C"���e��hW���dK����pj&��X'J_9*T��N�oF�r<=������F�d�1�XR��2�'�7(S��y�Xl9��%z2,�1���+u��*�+�a�"-�G=*������A=(���������m(Ae���������;����x�+��������F?C9f*,o��lh���l� }�()������U�HBn_A��V���m�����$���nf���S\�Hn�"�����	�^v)��B(9P#�+�� n����F�\����L��L����5�*������"\�H^vv<���/�4Y��`�pz��{��Z9�8,<�}���L%�+#7��(4�������q�%=u��7��Bk�����R����v[Z��qax��X4��(3B��rQaE�#/������v���W�eE���� ���j8~�z.����J��.-$���hd����#�E��7��au�xq_�mJE,�Tr�o�-N4>�R�N�|~$gF�Q���4�?G���DHe�*�zQ�-C^������R�����TA���T�'\J4v���)X=��+�,����gH�G:��.Mi|��e]K�]�����?�/�Q�1����e>�%��a�G��z��j��s�������J�4��4����&��=��
�L��"V�F����i�Ic��@�g!,\��H���p����lG,}��b�A��m�iBU�I|�Z��)�C<J�@���z��@�lW�&0�\K��?b,�g�x	A��F���%����j?�����5�R�#�|��Y����R�Z�;�#n;U��9cMqG�	�>o&��1b���,�4�����bP7hd�k��z`�X��
�*%�5_��5��� �R�H0�&m��:6y����CP��J���U�gB��4d������fE��U�a�3��}�M��J���������+~����W�p���_q	U/w`����d0i
I�[�����B�F'_�(��)���E5�����I�7O>��n��
w/��Vg�J'�P����6c���qh3���Vz3�Qdz~�/y���xq���2CH4�!w�J��6
fp>0l�F5p�B���9���X���(��/Jq3Q�[b[P�`�T`�k��|(���2����o��a���������9����S^6��`4u/������$N�gA.Z�K�+�3����fr���M�
�\���K��'����n��Y�ZkU�^�\��gX �g$F.�b�����
�l*�F�saA.�MG�O�� �kF�[�;�����1����\��������O����$J��{� aF�/1Wk,%�P�Ms3���������+��m�N�]N^
��s���TP�	��V��g���pO�1K��u
�]CB���m�x������T��#�.���R"���}<�����/�G-�.%�s�t5��"N�A�g����G0�:�\�5,��\�����(��f����*)'���l���_�� �����G���z�%c��G����&�u�`���<����0�N(<m$O\l!)�E@�=����{E���dZ����2�����YW�
�����6`8��R6�Yw[�������G0���������H�/`l���<���$��G0���F��N���P�#s�"+���1�I?��:�>��2��:��`�yHz\����T<��D<�K���`��p������r��fzx��Rc$���i� � 0F��P�`j�%���:��z��oo����9Wb*+L��KFq�����18}�
h��+�d�v�]�GXj��OpHo�am���TU�Iu;������+2�9��ai��Gk�.�y4�3�ms}�0�#����v���j�%�-`|����f���f5��j��'�2��5���$���T��M2�?����'TP���0�:��y��/��7��{ ��E�7�����v�Y]G�DF����}c�/��|���b���`��6�tix�F3�Gf��h���%�/Pq|� s�Y�� ]�.�K�L���W�v�}��B2i����
!:��P���!�<+?��	�
_��s�o������
������p<���1'|�e5������f�U{7y���';O�?~k����i��0y��S����q`��I�O���g�r]�&w��:	�p$��\�Q��FR�Tt�f"hk����9�^ �vsA��x`}���c�����>�;�l�:���\��U��u��JDWP�X[���@�E���=0�<����l!�19q2�����].�%Ez��W^L.h	V��;�����?y8��p��6�S��!g���m���p�(�_���?~u�s����Y�w`�W�!����t���|��;s�k����U\�Z�����?������0�)�K�$=�BR�HQ|o#G��
Vn������J��Y>�`]���5J�"���5
6�J�,��-4%" ��B;�F�I��mn����M#�n�H�f!����l���Nf������E`<l�c��E�eO�����P����(��W��H���y�
������.�t����6��������1eY8f\��}%s/�`bC���!%�O��kv#Z��Hj'?#�/s!s)��{C�j��M3!�7��3��6�*GS[�S��q���!�o��1IOP�4��r�8����if"$T�RI��N��4*b�����Up/�E�$�94��T�l8�5��PU
�!�p���-��pA^�'�d�A4��l.Ur�������Ud��*���O�b3�Ht�>��u�i*L?�|��?���y(/cB=[�����i��YU�s!0�d��qJ����`|��J�R�hDs8�3�����Y��;��z93�x�M���
�d�jxt:s��%c��HzR�R)L���K����Uz�<q3��Q����I�;$�\b��(C m&P�sE�B���*��@��Mi ���M��4�/�����lp�~L����Z����|��[��L�YY�\�K������i�2l�J��g�+��oG���@#Oac��%�IO��-���it%�ZMi��[��]��`_�l
�
�]�LR�=���F��e/����,d%���.y����;���������[�������X:\���[�JW�zI��D $���=Q��cYZ�<be_��J�Xhm"����y0b��J�U�_�v�.�{�9Y,��~���U�@��]��$�>l�uvOv�z���jQ�A��9�yn���6/71{�\�o/R�7���-���G�t�;)���:����_g���{��@�[N.��x�s:\�7���+�Sn���uM$wQ�;T�����*���������Zwg��Y��������v���]��]�})�&�iP���i8W��'R[n:2����������"������U��
����i&�9@1�LS�'��^����^wATGf��;g���_��w��N��b�y����}�s����N�����yl������A��}�`>��.B�Y������|@W����^R�ew0.�p!���K��V��NE���)'�X���e��V�G�� ���7A���p�F�����C]�G�7@��������!`0F�'�+������_-F\M��R��H�g���{��Z����>!u�r:qa�>>�~T��S a��g6��L����]Zmgk��8���u�$1�yH��K|��dlH�Jm����{)'��	�@Vr����J��.��a�j�X����$Mx<<}�*S�MamT��h�aQK�A���+�h���LLF�D�����;:)�����#�L����� �5l/g�Da��������'L��a�hm���A9e�QE*o�l��Ki3L�Gzu������<�bN�^%��d������n�.���x]�SGl�l���������YV,v�����X�x��_PU���o���#��������t�9�����	N�}����k�\A��)�ZE� ���9�X��]���"eX� D��Ob�}�[hOV�r=�y���?��E���������{���3)�i��B2k.��`
x�6Y��S���K�����B���n�1�9��{s?V�O4����iU��K��R��;=���>ITP��K+N��T����,u�����$��wT�{a�y�\bF���j��fg�:{��;��J���<�����x����e��KV	�U�;J���������v���e[�|�m/�]>k����������;�7n|t%�����`~�o�8+Q�3�W%���Fa/�/ �Eo�{��n���0�3������X8`������a4>�����C��<�P����+��� �)�d��W6��1�q��$q�1cv�@�P�Y%�]�2�A��=�
	��Bt7�x��]�k������p�u�3t���Sh�(����?� :�pt<�p�����{	CB���UM�%x��yj�{�e6GY\�|;��\a��[�V	9�6��&��*3�K?�����I?�U���[.&X���0 %%]�?��m��*n��V-�>R�D�V��"k�6���J3��d>�(�W���_}�z�l�|2*��U���G	��9��O��a��)����i���b���J�x���|J�E�7QM/6�i����[tm�}��w���L�����5�����x����-�Nc�W���EK��5b����H��Yl9b3��{�d-Q��Xi���.�`�e7�P�UqDof��T��uf4�|+�G}�D������R�����(m_$����������1~����W9�S��
�����jA�d�J�b3����c�Y�,Q��FcNlj	2|8L�����g��x�Z���^�V��+kq�6�6��7d�1��,p��l>���+'%P���z�����n@���Gh�S��>�ae4P�]"x�V��p.	���`�K#g����|���1�g��'bUw����|&��������^���<�A�~>�B��_�z���Ef�P���`����}�Y��pk���<�-QDb��3Fq����nX�|,>X�N�_1
�]:������_��>�,y>��R4�N���5�P'���l��6�,��^a�1�`�3E�^xpz�}�%	�U��IU�?F�y��J�#tH��d�e�}��`��i��F���e
�Z� L�xC;��%��+?��4��2���u����^�������0�g��p���x��p,����M
vV�����2Z���K�q/���/�����p���(��O��v��'��������Q���BFYQN��;�.��t*����c%l��y����Pi$��i#GAi��d$1��)`����q1;�?��p��L�>�F)}��u�3*�a�: ��5j1��y2��<�fI�DR��l��t���.�@�y�R|�W��t!�����DQ����idG�U�h��k��[��<p����������2o&?�dD���d0��XJ��k��u��x��P��#(�C~�����K����d���������!	���[yV���(�U_Y��Zm����FH�����='�?�*�=��%�0����Ioq�T)w��tWi��4�O�_}�m�����������������~������j_[����_��M6�|��W��G��'O���w��
�`���	���}#aCF�"E�SE�)q�0�1r��UG�C4'}pDIe�]�8�p������;�g����nH�_O8A����wv��}���3��o�I�Ga�>���F�����h�TZ2+&c���E?����l��"!�����9b�}{��!��B*'5'�B
k�`����L�Q;�5�����B�?lj�wu.����g'i�:C�w�o�����|���9�`�X��P0����A������2���L	mj&t�I�%sNh���g['&�b��+s����������l?�5!�G������6��~��q�[sB�����+�P��}y��#%�y���{3��y�83��v�A����"��_�qf�#j�T��8�d�^�v������X!����QN�Ts��U�5�1�Rz�5�&oFv&�dm��r�W!�.q��$��v]{���J�+4��E��W���n�w�&�_O�m=y��~E�WY�gI����*zb�"�N����7Ye����w�I,f�t���l���K'�M#8����0�C6qY��dp"�q�6oW�������z���p��M7Z>��="c0_��f2��+�
?<i��T���;=T�f���������F�U���.7BH�0&Y$�u~����k��P�v�����<)�f������7���.��>���_�*7�u���J�S6 �vI��`&*+,���AL��bC��D#*7�����R���M?�TR���i���HVWL�z2D������l����=G���@��'�����&����njk���<;�gq�R-WbV��7ZWH���Yx3_fYP*}�'������mf6m���OJ!)�������5���X
�dy�us��QG~�"�}�{k�	���B����L�?Z~n|�]�S6H<$���p��>������_`��`5T�.Pic`p@������A���n����Fhg������7e]�v�Q��,aA�����}?�/,B"�h\-�C/����������)%Fa0Gw�����7�7���$���&C�2�A!C�-n,��P��,����l6"��kh���QE���bf�L�����
�uN_����q���p�\������t{
��v�B���5$}���>Y[�b>�X�u�C5g���b�uy�l���9x���A����g�@LI��-?�FR���Y�������K�&�;l<�nr�+�v����mgH�c�����,���9���I���bt��v�������S0�V��4*5'.n�b��+o��{���p���)�
�(>��O�^����`��$	~}D�LF��(�gV#Me��Oe��Qm��j}0�E�����fE�p��*R��ICD(��P��q��`l.�)�#2<�A�����
�u��u&���F;b~0�.��@V��e!������isH��t��'T��K2 ���s%!��~xp����*`���!���|����e�������=�X7��u�������?����B���|�M.�]�������z�:�>d��?x(����	�oyL��/���S2M)�$���u�A�dQF�<(�F5w�]�P�h�k\X��L�������`k�V\����g��T�O�Bs�n��Pe@He�B=�	�?�S�7a�����!��������g2�@.�"1G�z������7����x/��baV��":��]l_�m��z��������f�������W���^�V];hh��C�������6��Sna#%T�w�j�"��'��K�*s)f���l^p#'tL��(���f�������3J�D��`�Q�Xif�s�����U�Qq����N802�o�L&�k'������1Dt�M��y�
&�tHE����	��4��{��pY	i��B��R����i7Tn���;���?a���������j��p��b�����VC0#�Vsp��L,�H��W�f������������T�K%��S���%������b��x��8W8A������~��y�xs���o��A=��Q��V��<y��.y��1?�d��*h{��G������Ej������L���h?�%��3
Va�
�c�x�������3��Z����Q���J�?�7�_��t�������0#���Z���k����sr�����--��8�g~*y�U��:'�Lbyp@�Z{a��m�.\��"�#��?	�~��.������f��f������i]X��^��
-�?R�k$D�4����yos��m�����W#r���t�5��~G�H������_4
�.�c�Y������C��0EPM���H������G���F�����^�;(�i�!�������i>�JH��]p����Q���&��fO$yH�9����h,n��P���[��Q����O- .������`���E��������gA�Q��u�N�P795�������x�X����,������?�������sK��>l�����%��0�� -�	��J����a�8�������:���S����(T���*5����������JH��i�%���A��z��Z1�v)���0����WI����q��]����|�~M��C��E�v�p6x	�z�
��W��m=y�5���I".(~��$8�S��P@�y�������b�/>�C�"t�x����8i�A��zm�A��0��Yb8������`l�d�6�oc2f48���d�x����N�� �Y�=B�Z��F���?����-���m�?�L��`�"~F���h��A�\S�e��W-���!t)�[���*b�����k����M��n��@����y*�I�c�:Q�HT�N:��3@�E��e	��5�zVV���x���o9����FNu*:�)�h� Z�~x������[_��/^���������O#��|�P�8�����~g4�g������;�\���A�M�i�,���?�? F�0���j�aA�e�.�T�%YO#��Vg���e�Am�vq�G�������[e|��^h�I��|l����������
xx��F�"M�iK��^��x�z�>��Y����|RH���x�$EIP������J/�
v����`o)�S�������a��%���('pFNk@�JL���F"��No�`��R����b�u�?���y�}F�%E��z9��a���`��������}{$����%��g�tw���
���(^���@�|�q�@�?(4�
�a���Z}3��V��M�Z�Ji'��7:�1���o��.�k�x�I�8e�4�Q
�����?;=;y�{��H�0�1�$
K:.=������]���e����N���_��-�6�RY>
�@]�3	���
�^zO�}��{|��"Q9��W�]�S�L{�n��%9�$"!����0�La�NM��8�IFI��l�R��^����Y���eSXf9i4��D��S6m$��,��i�V37�?����_�v������/`k4�-�.�i������p>���'�a�;N�X����KP0���m��+���N$��j���G3B�������}�~<����aZY�������|�X��le��;����M�Z�~��y��ts���|����e��R'u��R3���?���a)��� <Zl��o���
85��yV��yw���x'��������lD��W���<���)F-9��-��h�����Yy�l"1Y���k��c~������qI�l��%���������*��
`)�,�J��\��p�-�C�e���	,�l4X$�M�?�=; ;�
�*y����'��[�T��k����,�����}�
N��i��t��],<��N����/�
9�c�F�p�>7�VM~��%:����d��0�����q/�/��u��c�O|����(+<}������OA��WwF��o���/���b�Q��t��j�����l�?mSA�	Z���^��<{�4z���C%JXp�K���v��8�>�y�<$�o����I����,Y�vG�Y_*_�^�z(�E�8���R�O�������C��9��42GaW��,��f�Z	'������Rw'�]{��������+�sD/��d��f�^�0�����������7���~K~h�1��g���`	����31�:���_����a�1L^n������f�@��F[�(����L���(�gi1"Wdl7KA��A�q��P�1e]�S��O�Q��"�y���j��v���-����:�����F��	I�N6P����pK��y��#� ��T��Cw�+��%t�������������:����G/_6��\	��_�a��!�����{j}p��Z_%���p�:H��D�%E��!�i"i!!������~�n6���HGM��%$���c��^kP�d�&a��gcN���$2E�T���MC)���uW�l#��D���BYO3�oY��Z��{��rH`��S��!NK{�]k��	G)�>*QV��������j�����^6�<��9]��a�T�:I���g�E��g�PDDUE���
s�6�Ro���tdW���8���T�\Ei�����p��"���h�=�#F�lx��#%s]�.��Q�[ bf\����G�����!�-rn��r��R�$8M��P�e��F�����c�0s����^���m��<"^%
�U���3����;�����4�
�D,Z6��������an���B!��Da%����������Dc6�����7P�2����k>�k�\:��@���QS>�|J����,v�����P���si�-�!3{�`tw�S�h��;���Mm�?���7��$�4$xw�2MZ)l��==bR�E8A�
���?�E���L`7
�Y:|R��:�	vuxB��n�h1p�:���\T�`+D���U����"~�CZ<��.�=0B��|ZyC.6�����-�`!z�%���P�b+n(���r�(x;J>�0��wO��Z�5��b�[�k	���I"�iE��]0�O����-Z��,�_�b%���%e���� �����w1N8�����A�Q�?n$lU�@�$��������>��������9h��p��J����l�)y���k;��x��v�v�lV��W���p]���d�C4���9[~�x�C���R���<�?��=����G'	%�l�=��9�G�
E}����%+��i���������pd�����>�/S���'1,�O����@7M��z)0">�<��Y�cw������&Q�����z��9.�M�e�/���"�����E��7��*�q��������!�����_o�V��C�������7o�gg�{�\���*Wvx]{���������W��f��]�t�nkr;�o���#U����5�]����<r���"zK
�2�a#�~g��JZNi 5Wy�>]:0��<,?��
�:��vi���h&VA&�������0���.^��2l�-�FEyOTd6���1��9�8�%j���3��*�q�8��i�q�d,dqhTN�H��Y#�o��v��6\��l�� �c>��qh�T����i�P�	8h�$���_�yWh�E�����G���4��� �Fh�����o`���!��}����$���N��T�� Yi+���,����3��l�}���/Q�:-{,eq/\t0���`���+OX+�{���5�����z����Z�B�B���1(�{�g]9�(Z�g�%�����:Wn(�td#El�o	��!/��c7In/���+l�G�`�	����)!�1Bj�c/"��!,��Q��6�}����#��f���)9��ds��A|�#�<��fl��]pI

t�6,�)�f���� .��rU��h`��`�eo�$� a�g9@�H6�
23	��vc����- ���2�b�uy�~	)&E�.�%�@6b��Qi��G�{�(pd[�	�u�!�7@���!-:���Zt�:l���8z��"�
��}*.�%���$��%��@.�-����z��R�xd.�1��2C�g��A�^��u��ZZ�a��YW�5"��������vw�,�{$�QJ(
?��=�����v���e���8�
rUK���N=�5��<"7��^�bI��n�C-�����Q������\�K������~�����~�C���XNx�]/�%��\�r��p���*T��f��_�����d
�� $�P~�u��g���?6���pr��N�wK~�p��_��Y�6���	�^U�UB`�$$U:�|B������&�������+,������o~�.��N��/l����V���m����`k$%�p�q/'',���7R��{�I�����yt�f����Y����X�*�6k@���z����-�+�n�v^�����>���g��������;i�������$�b�`�����s����W������5s<|yd���c��������%d,���2�4�PP�(���(�E~��$D���Q\z5��	l�f�_�_�R�Qy�#$�<-����(N��0�Z�I%a���x��t|��Q�'v"�����^�����7L���i������Oo�����xnzm|~�A�/�aT�m���6c:O�l<�`Q�K?���w��6�u=�mB�Q��������i,��CG�y:�u���o����0��/r*f��������VBC���9�av�k���S�7J��������3J�^G*�Z��;\Y��`���t�1K�����o$���]��7�z��~0h��t2�����|:�F��^j%����^���l�p/����������2~���O�����P3��oi:�.��}��(GiS$?h�bR����3�]��2\R�j.���^@��>}l.���W����
;����ft�
��G����*�Dx=_/�����W�A��T2 ������hR�e���)�Rp`l9;J�D���2�&����>����S��C��Pz�g>��ja�t����o
��fR�+�����`W9v������C��������)	�F��\����Efli�����a��[_'������q�Y)���89����?�Dw7��0�3M�������H�0�}�)w�D)nP�u2<1�;[2�.���g]Y:��E����r'��
���\�1���h�U���>�"��
�4c���#���~��6���smL�W�A�C�w��pN.�v�,Tqi��-��-+h�������~���Drm2^"��U�^{�d���&����MT�(n������b��f��Z}�}H���&F0E|�"�X��\!�K/�i��
Av�`�'j,���V��s�������������O�w�����Z���_��
'���d�f�������9�F9N�+C���,���o6����c������o����������:[~;�jo&��R-�E�<���Ww�Mm\[�o�]L�D`!#	��7c*,
N�f��ZR�Y��n������=�]��b����%u�}=��TH>p
��	;��Z(({�����eQ��BYvzI�<�����f��R�i�K:4��%i���E�������1+��:�v�����jm�{�
�����$.��uW�!���?���<��]�o���K�wz�� ��	e��{���gKaQ���������aU5[u�Uy	�eUL���akV~60���E�}_��vv/�nO��$�6��8K0dD��}5������i�l1H��As��T1��!�!s(��Q���mt.o���s� 2	�������I�O��V�qT��� ��������N&��K�7�y:xx�'��Pj9C�.D��%���_�����q�U'��V����qU��h�����I5����C��h:����~#�0Ms$�Tc����������Q���C�&����1LS�x�0��a�12�0<+�Ky�VY�S��f����F��b�f�W��k�t����5�Cr�A-N2*}�S{��):������[����Hg�8���?2w�X���������s�T�W��^	��^:N"��'G��W@�?`�de��w����i����4|�����_EA�|��;��KGR���ak���v��Z�� ����$��Y�<>�
d/�1n�R���>���)���F�D�v��Y��_��A�k�h��i���O��a�����|��o�
!"!2��J�7��d(���^�,��rRl��7����@�9
�~vk�������0��K����0d	�D����Z��E����"����
������^��^m�����o��t��*��I�4�=fq��k�D)����Ta���40�i���k����`[P�����z�jy9N���s�I��Y����tII� �{D�[�D<Lt4�����`�D�&I$��M	��d4���E���"��U���J��1������������<O�`q��c�_Mf�M��`a���"��f/fpK��d�FB��v�j��U����o�F�Vs����5��w�]v����[�^�b�4��1�s�K9���h�Y���U��������.I���\�����(Jr��S�n����-xv6AQ��bj�j�N}�
�`;~�b��n���U��]��
3�u �/�/b#���"��(��|G�Y�eq'�_w2a���*pa/��7���y%�u�M0BD��
&�50f��IGY��vN�x ���-4���H��C��D�p��;�p���9
����@�����`}bML���	�e�����$~��"'��M�����S����ZP;��v��r�bQ��,������eU�,��-�#������dU�,0����Ne��_��Q���
V����qv��1Q5%U�$hd>$Tq��=#�
���
|����K����iA��M������q�%��>>���7���I����@�_lU���3��d�����L�Q
R�;{(�?"4f�6K4��@NJG�*����V��Z�PK�-��e0F������rQ����f����C���IE���E���j��r�<U3�f������(a��1-�${��wb0����g���s���,U��f�VvI�Q��<����G�ti���e��0SR}6^��Vr�9�t�E{��jB������ph��X|v
S����8C�AP�]�#��(p� D'
t�u���i�����o"��(_����+������b_VcR�G�����I�k}�D6�;�n�]3�������M0���P%`�����J��#����F�p4X$3V���]���+��vj:��aM�
��_��^��M<�]_��Yg�8�����\i�����z��[��g���e��57
�Q,�����X(�h�-6��C���;��W��.)�X]��I]�b�-=��I����I?�u���wO�����s2�\8`�L,�C\3�SFD��Ms;�_��4�)��,��v�m�_�
�Sl�\���7 }��<%G��o�L���$�%H���I9��l�v��bRg�P�u�-���"���p\��S6���_�2�xgB�����"
!w�����B�����J[	����}V�L,LX��"�'%
�,��o#]�_`�����3}��.�^��A`��c7��*<��B�6�u������~�
vf/u�cGfp�����6��
����/�miqI�@�<���
V�|��pg��B ��X�����6{��x���`����+mZ������93rg�J������$���)d$:��������%�t{���;���gX�'�*5����W"�����
++��#_�1/��J�D&Y�:�B�����I��������Z��[�A|6[R��(�vJ�jT��i\���0x�&�T�XA��lV��M�_���_��=|�pqoR���8���xqhE+����'��.�Q�
V��&�'I�B����4#B��^"��,z�r��Id������	�e����3\���K�����>���(�t�	h@��~�@Y���os�NP�&#�_T� �#
_>)���@1��M��}������s��)���+�6��(��Q�=�AK�Q(9�?��i ��}�V[��������"���^�����	�������E�Bt��s"��xG�lkU�P���.����'��*��#�]PI��*x�l��ef�Wx��)����i�H�;$�Qh���H���t����J��!��M�j��J�Bqs�	x�Y[|P����|C�	��j�1K��L���
���i������A��q�Yu<�����d����RI����b��B^W���X�U������-vB�
c `�P}��j����7�$�$���X����/�?h��A��{HS���~2�$yq����a��;o�rp��:��(����u��G���*�g�;�'F�1�$���%���%���'
HF��_R�96��L��Q7�Z��=��ip������7p��[��D�����,��0s����p<�v�ra������3�d�!�$��gC���P@I�q�z���+3�y�d�����!j4`/���5�X�?������n�?}��O/�28���f�t82���u��������3����n_�,At���p�~e=s�������v�����G�<U�����IE��m�O�����{�B9�]��Ig=DtdaP�������/,(M0x��;� @X���v2b.��S�JT>
�l"�)��B���B��@\��@� v�@f�m$	`�o�
�5���C�Kg�ix(�k����i��G�[������}���	�l����+X��J��&3s�<���(a��r+�e��2�I� 9��R�Xal��e��V���e"K�uf��wA�;o�Y�-�K�4��{�8���)���G�&����r[I)
y#��9N�g�}c� 5�����K����.���{�g�R����k��]B�f�_s��sG���7XPE�u��W�1��d����ox�Ty<C���+N�!�/�o�	���'�_>�@@>�['.�M�Q�L���,B$m�9L�4f��>�<�[IcM�r��i6�9/��",+��j���D���I���
�(�Y�h�=�
�rBc�3,B�44�C�D����-���zmx�
Y�
0�$�Un�&Dm��)��2�9��?N8������b���xJ�(BE����~F�
q�!��<�QRA��}]5�.�8����j�;�����hT]������>�W����h���&!����DmV��L����o�������5�}����G��-4J���f8�1?����P����t�����;����p�!�����.7��DE1g������p������,����g��UnH
�������(��"IXb/�@N�1�����
�k"%t>c�bs�t��.�����7q�G���iEAUwi���.��X:���lt\��v��`����f^�bOKB5�w�y>���o��-j�%�su�/ ���_o�,G�������R��K	�q��i2�@GK%
�/��M������V��}�J8�N��e�(�#
v�~��x}��8\�zZ�wR&{i��N��
]E��{KT��JyC��Z��U�@��[]6�0 ��,T%�'k�\����)�i�+��$��3)�4VFN].�&�Y���qD��Ppd�Y�fhRqf�R0t��i7u�|��(#a��Uk��[�?������
L_G��4S!������%3QaXA���3l��$������w�o�+��:"@QzL�::<���-�q��u����Y:��(,urz��Mc�%��{��X�f@E�`I����O��$�������U��D���/����T�>�?�*�`���+��O��@�K`���{����<��!�%cb�����E?�U�e��/b�`0��sq-��3������Y$�1ah.>�1���G���W�6�F�z4'P��a�]`�t&)��!�w�xi���|[,5�p���_�����Cjr�P�����H��~��u"�2�:l��^�����qS����+N!te�������L�����"s�e��g��(�K:�m��k������ny�<e�<��qYQ��`����@iM�z8P��*��%��DJg1D/�!z)i�)����d<\���a����n���V����������.*�nio��)]s�x"0-{�ugx��P���V�������U(�� �fuj���	�U���������j������jht�e(����Y�Y�U�|���������c^
� ��2VuW����'��W\��e&J+���0a�Bi���i�(�c��]������zC��2#�S��M�O�[�UWl�1DT��a@g@{����]fZ��V�L���GG�h-�4����AeF��q��AE��@c4rP��X�9������������i&g=,�
I�R{��G�J!e/`c�5����3�-I�~��N�Y������u{�h=e��K,��	b���������=
9�������p�N�0���J&�w�yHSF�2���2x+��R�^� �(F�k����T
��W���A%6�P����I��g��D)�
�+~.���!��~�s�������)��p��AK��uP-*h�e�����R�h��Fv���l��l��<�cV%���"�������N��n�W���m�
7�q�Ip(�{��1F��)V�)1��X�����$�L�}�e9��
NpRk�3�������.6*����)�Bb�\�Da���
Qp�����N���m@:H�X��g��P���wP�)6��y��r7����z��5����>�ze�/���>
�]_�f�t��g��Q��"Rt�t�������8���X3�#M��:;	J�ii����J���2�~N���~��������Y�{,��}�&�0�B���4�������Z�M��d�z'K�*f���]�kl��g'��P��^�b4�#El.Z��qOG
,�|����J��������q&���w$#�l_^w�������S8�s�=�����������G�a�Y�J],�H��`���R�����e�w�'���A���@=����fh�5�I�9Pc�46�(0��O��S�]4%g#*iK>��h���/�Q1Sk���|��2�^������DQ�d��9~�(U*���
���
�`����g��8c.�~#/�����`�_���Q4:._f�K�L�������?x89(�W�o+����(+d\��~��q���@��4<�����<N�,�
�����P��Ku�.���F
��_����d`a���$~p���8�������B�>_^ ��3~)W��_��7�,s����M%kE����A��j�a��?jy��P�U�
�^���
�"�Hi?����kd��,�
�#E�7�{��,�����������o�B��6��`b.^��|{���������O���!N�?��;��A}�xpT��[�^�|"���Y��c�}�A�o���6��}��29�����>���.�Ru�A��kn��qG�#�#2��3m��s�f!�b�_l��t��a�YP��H��<�acP�;��F����h�L��es�S������'�����Q�2��68��	n�M������O��6�dI��y����(��<�����I1vsy����~���~'�4����Vk5��9Z672w�����
o�F��or�;����W7������qc���������C��ciO�s����h��F�?��l��o�I������6��G�z^�G�
mA)jN<)"���7E���?|CP��\6���z��U�4���FE?���n�,&<XX��|� �N�f>;��6�R������3'�W���8Y�����{������8���Y^����� ��]?@��s��+ul��.�*{cq�K�_�`lA�?���u�kCn�x�R�f'4�cN�4P������b`�B1�X��?��k��h�8������5��Sh��8�N�ea�O�@~�����tO���.�����5�����:��(�8��,�c.4%�S]�3����t�%n���8��;3h}gK:<�~�`y����i�����A�����PJ�D����G�:'��,J�kd`�4��?:<<�7a����}���}�.L��1�����g����6�'p\cP������,�/��������|p-�Si��>�H���l��<��}����GQ�������7=@�����?$����M����nN/�����Qh���A�dw��7��`����`Q�<�)�'��U?Op'�,��������g3������1����=s������:Gn��8B7��qd�}��,a���Tw�Y��8?-S`��ZT^d�`�+�p��e=�0���fh)A#�}�����@�))>n'���
Lr�z�����
AH�h��.��T�[���V���&�
��&����&������Vk�(���yx{zs>t/6��n�(>n3��a��]���k�mD���O�������'>;�����:����&�a��I�����a�"~�/E�KM��4o�����"N���0�o���=#z�~���v�i�:���RfN�k������;�|+��6���<pi_30���g�6���Z��h�k�b[6������n4�Ec
0004-wal_decoding-Only-peg-the-xmin-horizon-for-catalog-t.patch.gzapplication/x-patch-gzipDownload
0005-wal_decoding-Allow-walsenders-to-connect-to-a-specif.patch.gzapplication/x-patch-gzipDownload
0006-wal_decoding-logical-changeset-extraction-walsender-.patch.gzapplication/x-patch-gzipDownload
0007-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gzapplication/x-patch-gzipDownload
#16Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#14)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On 2014-01-22 10:14:27 -0500, Robert Haas wrote:

On Wed, Jan 22, 2014 at 9:48 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-01-18 08:35:47 -0500, Robert Haas wrote:

I am not sure I understand that point. We can either update the
in-memory bit before performing the on-disk operations or
afterwards. Either way, there's a way to be inconsistent if the disk
operation fails somewhere inbetween (it might fail but still have
deleted the file/directory!). The normal way to handle that in other
places is PANICing when we don't know so we recover from the on-disk
state.
I really don't see the problem here? Code doesn't get more robust by
doing s/PANIC/ERROR/, rather the contrary. It takes extra smarts to only
ERROR, often that's not warranted.

People get cranky when the database PANICs because of a filesystem
failure. We should avoid that, especially when it's trivial to do so.
The update to shared memory should be done second and should be set
up to be no-fail.

I don't see how that would help. If we fail during unlink/rmdir, we
don't really know at which point we failed.

This doesn't make sense to me. unlink/rmdir are atomic operations.

Yes, individual operations should be, but you cannot be sure whether a
rename()/unlink() will survive a crash until the directory is
fsync()ed. So, what is one going to do if the unlink suceeded, but the
fsync didn't?

Deletion currently works like:
if (rename(path, tmppath) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not rename \"%s\" to \"%s\": %m",
path, tmppath)));

/* make sure no partial state is visible after a crash */
fsync_fname(tmppath, false);
fsync_fname("pg_replslot", true);

if (!rmtree(tmppath, true))
{
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not remove directory \"%s\": %m",
tmppath)));
}

If we fail between the rename() and the fsync_fname() we don't really
know which state we are in. We'd also have to add code to handle
incomplete slot directories, which currently only exists for startup, to
other places.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#17Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#16)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On Wed, Jan 22, 2014 at 10:48 AM, Andres Freund <andres@2ndquadrant.com> wrote:

Yes, individual operations should be, but you cannot be sure whether a
rename()/unlink() will survive a crash until the directory is
fsync()ed. So, what is one going to do if the unlink suceeded, but the
fsync didn't?

Well, apparently, one is going to PANIC and reinitialize the system.
I presume that upon reinitialization we'll decide that the slot is
gone, and thus won't recreate it in shared memory. Of course, if the
entire system suffers a hard power failure after that and before the
directory is succesfully fsync'd, then the slot could reappear on the
next startup. Which is also exactly what would happen if we removed
the slot from shared memory after doing the unlink, and then the
system suffered a hard power failure before the directory contents
made it to disk. Except that we also panicked.

In the case of shared buffers, the way we handle fsync failures is by
not allowing the system to checkpoint until all of the fsyncs succeed.
If there's an OS-level reset before that happens, WAL replay will
perform the same buffer modifications over again and the next
checkpoint will again try to flush them to disk and will not complete
unless it does. That forms a closed system where we never advance the
redo pointer over the covering WAL record until the changes it covers
are on the disk. But I don't think this code has any similar
interlock; if it does, I missed it.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#18Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#17)
Re: Changeset Extraction v7.0 (was logical changeset generation)

Hi,

On 2014-01-22 13:00:44 -0500, Robert Haas wrote:

Well, apparently, one is going to PANIC and reinitialize the system.
I presume that upon reinitialization we'll decide that the slot is
gone, and thus won't recreate it in shared memory.

Yea, and if it's half-gone we'll continue deletion. And since yesterday
evening we'll even fsync things during startup to handle scenarios
similar to 20140122162115.GL21170@alap3.anarazel.de .

Of course, if the entire system suffers a hard power failure after that and before the
directory is succesfully fsync'd, then the slot could reappear on the
next startup. Which is also exactly what would happen if we removed
the slot from shared memory after doing the unlink, and then the
system suffered a hard power failure before the directory contents
made it to disk. Except that we also panicked.

Yes, but that could only happen as long as no relevant data has been
lost since we hold relevant locks during this.

In the case of shared buffers, the way we handle fsync failures is by
not allowing the system to checkpoint until all of the fsyncs succeed.

I don't think shared buffers fsyncs are the apt comparison. It's more
something like UpdateControlFile(). Which PANICs.

I really don't get why you fight PANICs in general that much. There are
some nasty PANICs in postgres which can happen in legitimate situations,
which should be made to fail more gracefully, but this surely isn't one
of them. We're doing rename(), unlink() and rmdir(). That's it.
We should concentrate on the ones that legitimately can happen, not the
ones created by an admin running a chmod -R 000 . ; rm -rf $PGDATA or
mount -o remount,ro /. We don't increase reliability by a bit adding
codepaths that will never get tested.

If there's an OS-level reset before that happens, WAL replay will
perform the same buffer modifications over again and the next
checkpoint will again try to flush them to disk and will not complete
unless it does. That forms a closed system where we never advance the
redo pointer over the covering WAL record until the changes it covers
are on the disk. But I don't think this code has any similar
interlock; if it does, I missed it.

No, it doesn't (until the first rename() at least), but the number of
failure scenarios is far smaller.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#19Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#18)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On Thu, Jan 23, 2014 at 7:05 AM, Andres Freund <andres@2ndquadrant.com> wrote:

I don't think shared buffers fsyncs are the apt comparison. It's more
something like UpdateControlFile(). Which PANICs.

I really don't get why you fight PANICs in general that much. There are
some nasty PANICs in postgres which can happen in legitimate situations,
which should be made to fail more gracefully, but this surely isn't one
of them. We're doing rename(), unlink() and rmdir(). That's it.
We should concentrate on the ones that legitimately can happen, not the
ones created by an admin running a chmod -R 000 . ; rm -rf $PGDATA or
mount -o remount,ro /. We don't increase reliability by a bit adding
codepaths that will never get tested.

Sorry, I don't buy it. Lots of people I know have stories that go
like this "$HORRIBLE happened, and PostgreSQL kept on running, and it
didn't even lose my data!", where $HORRIBLE may be variously that the
disk filled up, that disk writes started failing with I/O errors, that
somebody changed the permissions on the data directory inadvertently,
that the entire data directory got removed, and so on. I've been
through some of those scenarios myself, and the care and effort that's
been put into failure modes has saved my bacon more than a few times,
too. We *do* increase reliability by worrying about what will happen
even in code paths that very rarely get exercised. It's certainly
true that our bug count there is higher there than for the parts of
our code that get exercised more regularly, but it's also lower than
it would be if we didn't make the effort, and the dividend that we get
from that effort is that we have a well-deserved reputation for
reliability.

I think it's completely unacceptable for the failure of routine
filesystem operations to result in a PANIC. I grant you that we have
some existing cases where that can happen (like UpdateControlFile),
but that doesn't mean we should add more. Right this very minute
there is massive bellyaching on a nearby thread caused by the fact
that a full disk condition while writing WAL can PANIC the server,
while on this thread at the very same time you're arguing that adding
more ways for a full disk to cause PANICs won't inconvenience anyone.
The other thread is right, and your argument here is wrong. We have
been able to - and have taken the time to - fix comparable problems in
other cases, and we should do the same thing here.

As for why I fight PANICs so much in general, there are two reasons.
First, I believe that to be project policy. I welcome correction if I
have misinterpreted our stance in that area. Second, I have
encountered a few situations where customers had production servers
that repeatedly PANICked due to some bug or other. If I've ever
encountered angrier customers, I can't remember when. A PANIC is no
big deal when it happens on your development box, but when it happens
on a machine with 100 users connected to it, it's a big deal,
especially if a single underlying cause makes it happen over and over
again.

I think we should be devoting our time to figuring how to improve
this, not whether to improve it.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#20Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#19)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On 2014-01-23 11:50:57 -0500, Robert Haas wrote:

On Thu, Jan 23, 2014 at 7:05 AM, Andres Freund <andres@2ndquadrant.com> wrote:

I don't think shared buffers fsyncs are the apt comparison. It's more
something like UpdateControlFile(). Which PANICs.

I really don't get why you fight PANICs in general that much. There are
some nasty PANICs in postgres which can happen in legitimate situations,
which should be made to fail more gracefully, but this surely isn't one
of them. We're doing rename(), unlink() and rmdir(). That's it.
We should concentrate on the ones that legitimately can happen, not the
ones created by an admin running a chmod -R 000 . ; rm -rf $PGDATA or
mount -o remount,ro /. We don't increase reliability by a bit adding
codepaths that will never get tested.

Sorry, I don't buy it. Lots of people I know have stories that go
like this "$HORRIBLE happened, and PostgreSQL kept on running, and it
didn't even lose my data!", where $HORRIBLE may be variously that the
disk filled up, that disk writes started failing with I/O errors, that
somebody changed the permissions on the data directory inadvertently,
that the entire data directory got removed, and so on.

Especially the "not loosing data" imo is because postgres is
conservative with continuing in situations it doesn't know anything
about. Most prominently the cluster wide restart after a segfault.

I've been
through some of those scenarios myself, and the care and effort that's
been put into failure modes has saved my bacon more than a few times,
too. We *do* increase reliability by worrying about what will happen
even in code paths that very rarely get exercised.

A part of thinking about them *is* restricting what happens in those
cases by keeping the possible states to worry about to a minimum.

Just splapping on an ERROR instead of PANIC can make things much
worse. Not releasing space until a restart, without a chance to do
anything about it because we failed to properly release the in-memory
slot will just make the problem bigger because now the cleanup might
take a week (VACUUM FULLing the entire cluster?).

I think it's completely unacceptable for the failure of routine
filesystem operations to result in a PANIC. I grant you that we have
some existing cases where that can happen (like UpdateControlFile),
but that doesn't mean we should add more. Right this very minute
there is massive bellyaching on a nearby thread caused by the fact
that a full disk condition while writing WAL can PANIC the server,
while on this thread at the very same time you're arguing that adding
more ways for a full disk to cause PANICs won't inconvenience anyone.

A full disk won't cause any of the problems for the case we're
discussing, will it? We're just doing rename(), unlink(), rmdir() here,
all should succeed while the FS is full (afair rename() does on all
common FSs because inodes are kept separately).

The other thread is right, and your argument here is wrong. We have
been able to - and have taken the time to - fix comparable problems in
other cases, and we should do the same thing here.

I don't think the WAL case is comparable at all. ENOSPC is something
expected that can happen during normal operation and doesn't include
malintended operator and is reasonably easy to test. unlink() or fsync()
randomly failing is not.
In fact, isn't the consequence out of that thread that we need a
significant amount of extra complexity to handle the case? We shouldn't
spend that effort for cases that don't deserve it because they are too
unlikely in practice.

And yes, there's not too many other places PANICing - because most can
rely on WAL handling those tricky cases for them...

Second, I have
encountered a few situations where customers had production servers
that repeatedly PANICked due to some bug or other. If I've ever
encountered angrier customers, I can't remember when. A PANIC is no
big deal when it happens on your development box, but when it happens
on a machine with 100 users connected to it, it's a big deal,
especially if a single underlying cause makes it happen over and over
again.

Sure. But blindly continuing and then, possibly quite a bit later,
loosing data, causing an outage that takes a long while to recover or
something isn't any better.

I think we should be devoting our time to figuring how to improve
this, not whether to improve it.

If you'd argue that creating a new slot should fail gracefull, ok, I can
relatively easily be convinced of that. But trying to handle failures in
the midst of deletion in cases that won't happen in reality is just
inviting trouble imo.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#21Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#15)
Re: Changeset Extraction v7.1

Patch 0001:

+ errmsg("could not find free replication slot"),

Suggest: all replication slots are in use

+ elog(ERROR, "cannot aquire a slot while another slot
has been acquired");

Suggest: this backend has already acquired a replication slot

Or demote it to Assert(). I'm not really sure why this needs to be
checked in non-assert builds. I also wonder if we should use the
terminology "attach" instead of "acquire"; that pairs more naturally
with "release". Then the message, if we want more than an assert,
might be "this backend is already attached to a replication slot".

+       if (slot == NULL)
+       {
+               LWLockRelease(ReplicationSlotCtlLock);
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                errmsg("could not find replication
slot \"%s\"", name)));
+       }

The error will release the LWLock anyway; I'd get rid of the manual
LWLockRelease, and the braces. Similarly in ReplicationSlotDrop.

+       /* acquire spinlock so we can test and set ->active safely */
+       SpinLockAcquire(&slot->mutex);
+
+       if (slot->active)
+       {
+               SpinLockRelease(&slot->mutex);
+               LWLockRelease(ReplicationSlotCtlLock);
+               ereport(ERROR,
+                               (errcode(ERRCODE_OBJECT_IN_USE),
+                                errmsg("slot \"%s\" already active", name)));
+       }
+
+       /* we definitely have the slot, no errors possible anymore */
+       slot->active = true;
+       MyReplicationSlot = slot;
+       SpinLockRelease(&slot->mutex);

This doesn't need the LWLockRelease either. It does need the
SpinLockRelease, but as I think I noted previously, the right way to
write this is probably: SpinLockAcquire(&slot->mutex); was_active =
slot->active; slot->active = true; SpinLockRelease(&slot->mutex); if
(was_active) ereport(). MyReplicatonSlot = slot.

ReplicationSlotsComputeRequiredXmin still acquires ProcArrayLock, and
the comment "Provide interlock against concurrent recomputations"
doesn't seem adequate to me. I guess the idea here is that we regard
ProcArrayLock as protecting ReplicationSlotCtl->catalog_xmin and
ReplicationSlotCtl->data_xmin, but if that's the idea then we only
need to hold the lock during the time when we actually update those
values, not the loop where we compute them. Also, if that's the
design, maybe they should be part of PROC_HDR *ProcGlobal rather than
here. It seems weird to have some of the values protected by
ProcArrayLock live in a completely different data structure managed
almost entirely by some other part of the system.

It's pretty evident that what's currently patch #4 (only peg the xmin
horizon for catalog tables during logical decoding) needs to become
patch #1, because it doesn't make any sense to apply this before we do
that. I'm still not 100% confident in that approach, but maybe I'd
better try to look at it RSN and get confident, because too much of
the rest of what you've got here hangs on that to proceed without it.
Or to put all that another way, if for any reason we decide that the
separate catalog xmin stuff is not viable, the rest of this is going
to need a lot of rework, so we'd better sort that now rather than
later.

With respect to the synchronize-slots-to-disk stuff we're arguing
about on the other thread, I think the basic design problem here is
that you assume that you can change stuff in memory and then change
stuff on disk, without either set of changes being atomic. What I
think you need to do is making atomic actions on disk correspond to
atomic state changes in memory. IOW, suppose that creating a slot
consists of two steps: mkdir() + fsync(). Then I think what you need
to do is - do the mkdir(). If it errors out, fine. If it succeeds,
the mark the slot half-created. This is just an assignment so it can
done immediately after you learn that mkdir() worked with no risk of
an intervening failure. Then, try to fsync(). If it errors out, the
slot will get left in the half-created state. If it works, then
immediately mark the slot as fully created. Now, when the next guy
comes along and looks at the slot, he can tell what he needs to do.
Specifically, if the slot is half-created, and he wants to do anything
other than remove it, he's got to fsync() it first, and if that errors
out, so be it. The next access to the slot will merely find it still
half-created and simply try the fsync() yet again.

Alternatively, since nearly everything we're trying to do here is a
two-step operation - do something and then fsync - maybe we have a
more generic fsync-pending flag, and each slot operation checks that
and retries the fsync() if it's set. But it might be situation
dependent which thing we need to fsync, since there are multiple files
involved.

Broadly, what you're trying to accomplish here is to have something
that is crash-safe but without relying on WAL, so that it can work on
standbys. If making things crash-safe without WAL were easy to do, we
probably wouldn't have WAL at all, so it stands to reason that there
are going to be some difficulties here. Making it work reliably is
going to require either inventing some special-purpose type of
write-ahead logging specific to this particular need, or some analogue
of shadow paging, or making sure that every intermediate step is
well-defined and recoverable. Right now, you're on that last path,
and it's by no means obvious to me that that's the wrong place to be,
but I think there's some work left to be done to get it there.

Calling a slot "old" or "new" looks liable to cause problems. Maybe
change those names to contain a character not allowed in a slot name,
if we're going to keep doing it that way.

I wonder if it wouldn't be better to get rid of the subdirectories for
the individual slots, and just have a file pg_replslot/$SLOTNAME, or
not. I know there are later patches that need subdirectories for
their own private data, but they could just create
pg_replslot/$SLOTNAME.dir and put whatever in it they like, without
really implicating this code that much. The advantage of that is that
there would be fewer intermediate states. The slot exists if the file
exists, and not if it doesn't. You still need half-alive and
half-dead until the fsync finishes, but you don't need to worry about
tracking both the state of the directory and the state of the file.
On startup we fsync the containing directory and all of the slot files
we find inside it and refuse to start up if that fails, but once
running filesystem failures only prevent changes; they don't kill the
system.

Patch 0004:

I'm not very confident that PROC_IN_LOGICAL_DECODING is the right way
to go here. It seems to me that excluding the xmins of backends with
slots from globalxmin consideration so that we can fold the same xmin
in by some other mechanism is kind of strange. How about letting the
xmins of such backends affect the computation as normal, and then
having one extra xmin that gets folded in that represents the minima
of the xmin of unconnected slots? When a backend with a slot
disconnects, an on_shmem_exit hook must move that value backwards if
it follows MyPgXact->xmin.

That's all for now...

...Robert

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#22Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Robert Haas (#21)
Re: Changeset Extraction v7.1

I wonder if it wouldn't be better to get rid of the subdirectories for
the individual slots, and just have a file pg_replslot/$SLOTNAME, or
not. I know there are later patches that need subdirectories for
their own private data, but they could just create
pg_replslot/$SLOTNAME.dir and put whatever in it they like, without
really implicating this code that much. The advantage of that is that
there would be fewer intermediate states. The slot exists if the file
exists, and not if it doesn't. You still need half-alive and
half-dead until the fsync finishes, but you don't need to worry about
tracking both the state of the directory and the state of the file.

Why do we need directories at all? I know there might be subsidiary
files to store stuff in separate files, but maybe we can just name files
using the slot name (or a transformation thereof) as a prefix. It
shouldn't be difficult to remove the right files whenever there's a
need, and not having to worry about a directory that might need a
separate fsync might make things easier.

On the other hand, there might still be a need to fsync the parent
directory, so maybe there is not that much gain.

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#23Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#21)
Re: Changeset Extraction v7.1

Hi,

On 2014-01-23 16:04:10 -0500, Robert Haas wrote:

Patch 0001:

+ errmsg("could not find free replication slot"),

Suggest: all replication slots are in use

That sounds better indeed.

+ elog(ERROR, "cannot aquire a slot while another slot
has been acquired");

Suggest: this backend has already acquired a replication slot

Or demote it to Assert(). I'm not really sure why this needs to be
checked in non-assert builds.

Hm. Fine with me, not sure why I went with an elog(). Maybe because I
thought output plugin authors could have the idea of using another slot
while inside one?

I also wonder if we should use the
terminology "attach" instead of "acquire"; that pairs more naturally
with "release". Then the message, if we want more than an assert,
might be "this backend is already attached to a replication slot".

I went with Acquire/Release because our locking code does so, and it
seemed sensible to be consistent. I don't have strong feelings about it.

+       if (slot == NULL)
+       {
+               LWLockRelease(ReplicationSlotCtlLock);
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                errmsg("could not find replication
slot \"%s\"", name)));
+       }

The error will release the LWLock anyway; I'd get rid of the manual
LWLockRelease, and the braces. Similarly in ReplicationSlotDrop.

Unfortunately not. Inside the walsender there's currently no
LWLockReleaseAll() for ERRORs since commands aren't run inside a
transaction command...

But maybe I should have fixed this by adding the release to
WalSndErrorCleanup() instead? That'd still leave the problematic case
that currently we try to delete a replication slot inside a CATCH when
we fail while initializing the rest of logical replication... But I
guess adding it would be a good idea independent of that.

We could also do a StartTransactionCommand() but I'd rather not, that
currently prevents code in that vicinity from doing anything it
shouldn't via various Assert()s in existing code.

+       /* acquire spinlock so we can test and set ->active safely */
+       SpinLockAcquire(&slot->mutex);
+
+       if (slot->active)
+       {
+               SpinLockRelease(&slot->mutex);
+               LWLockRelease(ReplicationSlotCtlLock);
+               ereport(ERROR,
+                               (errcode(ERRCODE_OBJECT_IN_USE),
+                                errmsg("slot \"%s\" already active", name)));
+       }
+
+       /* we definitely have the slot, no errors possible anymore */
+       slot->active = true;
+       MyReplicationSlot = slot;
+       SpinLockRelease(&slot->mutex);

This doesn't need the LWLockRelease either. It does need the
SpinLockRelease, but as I think I noted previously, the right way to
write this is probably: SpinLockAcquire(&slot->mutex); was_active =
slot->active; slot->active = true; SpinLockRelease(&slot->mutex); if
(was_active) ereport(). MyReplicatonSlot = slot.

That's not really simpler tho? But if you prefer I can go that way.

ReplicationSlotsComputeRequiredXmin still acquires ProcArrayLock, and
the comment "Provide interlock against concurrent recomputations"
doesn't seem adequate to me. I guess the idea here is that we regard
ProcArrayLock as protecting ReplicationSlotCtl->catalog_xmin and
ReplicationSlotCtl->data_xmin, but if that's the idea then we only
need to hold the lock during the time when we actually update those
values, not the loop where we compute them.

There's a comment someplace else to that end, but yes, that's
essentially the idea. I decided to take it during the whole
recomputation because we also take ProcArrayLock when creating a new
decoding slot and initially setting ->catalog_xmin. That's not strictly required
but seemed simpler that way, and the code shouldn't be very hot.
The code that initially computes the starting value for catalog_xmin
when creating a new decoding slot has to take ProcArrayLock to be safe,
that's why I though it'd be convenient to always use it for those
values.

In all other cases where we modify *_xmin we're only increasing it which
doesn't need a lock (HS feedback never has taken one, and
GetSnapshotData() modifies ->xmin while holding a shared lock), the only
potential danger is a slight delay in increasing the overall value.

Also, if that's the
design, maybe they should be part of PROC_HDR *ProcGlobal rather than
here. It seems weird to have some of the values protected by
ProcArrayLock live in a completely different data structure managed
almost entirely by some other part of the system.

Don't we already have cases of that? I seem to remember so. If you
prefer having them there, I am certainly fine with doing that. This way
they aren't allocated if slots are disabled but it's just two
TransactionIds.

It's pretty evident that what's currently patch #4 (only peg the xmin
horizon for catalog tables during logical decoding) needs to become
patch #1, because it doesn't make any sense to apply this before we do
that.

Well, the slot code and the the slot support for streaming rep are
independent from and don't use it. So they easily can come before it.

I previously had argued for committing that patch together with the main
changeset extraction commit but you, understandably so!, wanted to have
it separately for review.

[ discussion about crash safety of slots and their use of PANIC ]
Broadly, what you're trying to accomplish here is to have something
that is crash-safe but without relying on WAL, so that it can work on
standbys. If making things crash-safe without WAL were easy to do, we
probably wouldn't have WAL at all, so it stands to reason that there
are going to be some difficulties here.

My big problem here is that you're asking this code to have *higher*
guarantees than WAL ever had and currently has, not equivalent
guarantees. Even though the likelihood of hitting problems is a least a
magnitude or two smaller as we are dealing with minimal amounts of data.
All the situations that seem halfway workable in the nearby thread about
PANIC in XLogInsert() you reference are rough ideas that reduce the
likelihood of PANICs, not remove them.

I am fine with reworking things so that the first operation of several
doesn't PANIC because we still can clearly ERROR out in that case. That
should press the likelihood of problems into the utterly irrelevant
area. E.g. ERROR for the rename(oldpath, newpath) and then start a
critical section for the fsync et al.

Calling a slot "old" or "new" looks liable to cause problems. Maybe
change those names to contain a character not allowed in a slot name,
if we're going to keep doing it that way.

Hm. Fair point. slotname.old, slotname.new sounds better.

I wonder if it wouldn't be better to get rid of the subdirectories for
the individual slots, and just have a file pg_replslot/$SLOTNAME, or
not. I know there are later patches that need subdirectories for
their own private data, but they could just create
pg_replslot/$SLOTNAME.dir and put whatever in it they like, without
really implicating this code that much.

I wondered about making them plain files as well but given the need for
a directory independent from this I don't really see the advantage,
we'll need to handle them anyway during cleanup.

Patch 0004:

I'm not very confident that PROC_IN_LOGICAL_DECODING is the right way
to go here. It seems to me that excluding the xmins of backends with
slots from globalxmin consideration so that we can fold the same xmin
in by some other mechanism is kind of strange.

It's essentially copying what PROC_IN_VACUUM already does, that's where
I got the idea from.

How about letting the xmins of such backends affect the computation as normal, and then
having one extra xmin that gets folded in that represents the minima
of the xmin of unconnected slots?

That's how I had it in the beginning but it turned out that has
noticeable performance/space impact. Surprising isn't it? The reason is
that we'll intermittently use normal snapshots to look at the catalog
during decoding and they will install a xmin the current proc. So, while
that snapshot is active GetSnapshotData() will return an older xmin
preventing HOT pruning from being as efficient.

I think we *really* need to make heap_page_prune() more efficient CPU
wise someday not too far away.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#24Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#23)
12 attachment(s)
Re: Changeset Extraction v7.1

On 2014-01-24 00:32:09 +0100, Andres Freund wrote:

I am fine with reworking things so that the first operation of several
doesn't PANIC because we still can clearly ERROR out in that case. That
should press the likelihood of problems into the utterly irrelevant
area. E.g. ERROR for the rename(oldpath, newpath) and then start a
critical section for the fsync et al.

So, I've changed stuff around to PANIC only as soon as we're in a state
that's unclear.
To test stuff I've added another .so to the test_decoding contrib that
exposes mkdir/rmdir/chmod/unlink to sql to test those cases in the
contrib's sql/slot.sql. Not sure if we want to keep that, but it's
certainly helpful for now.
The required changes certainly didn't make things look nicer...

I've also changed the temporary name used when creating/dropping slots
to $slotname.tmp.

That doesn't remove PANICs but makes them even less likely. Ok?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-wal_decoding-Introduce-the-replication-slot-interfac.patch.gzapplication/x-patch-gzipDownload
0002-wal_decoding-physical-streaming-replication-walsende.patch.gzapplication/x-patch-gzipDownload
0003-wal_decoding-Introduce-changeset-extraction.patch.gzapplication/x-patch-gzipDownload
�l��R0003-wal_decoding-Introduce-changeset-extraction.patch�[ys�F���������H��d]kodY�U��Y�K�m�XC`H"�������{p�P�$��"������N�������`��M�d�������d�;4����`����}�>���Y�������?5�����@s�N#?1V�NL�����~�#��/&�����+��c���;jO�2��C�v<<8��^��k^f�_����|:�:{�z����gu���o��������$�3�(o����&U�.M��q�l^���|�U���D�*��7������o�q6�����ceh��,�f*1�Z3���
^�&$1�l�sOh���7~Na��^�� �	� ��Vy:�a<U�������K�*��!�v�2Rc� N�O��bz���6��X��8KY�a6
"��$g^�%�0Hgj��p��k�T[�G'��>�
`��0����<H���X;����v���gs�[5�?n~2��z33��Lu��7^E�M�i�>�c�����������zD���.x�:�%�{mu�<��_�T�7Qu/M�|�i�O��,��`c�L��y�B���E�,��z	rj��l�H\{���a�8�����%:�?�<
ot��&I`C�n��T6�vIz&�w���3�����xj��7���W��!sQ�\���@m�g���|
�[����*8�_[��X�|���B2S<\�$S����f�^���	��@�q�q����7M�"�6P��{}m&u���!�$>�+x���@����h@�����>��] ����o��d���#� �zt-H�758B(�^��������
�a�B� ����
��"�=�$�~��T��l�z���V�?^��dp���������W���41!X�&��Uk�4�|t}P��+���fk�%��E�6��\��c�kPu��b� �/����|�1a����	����{�@](Z�\�tytw1�-��[DY�f��k�����y�
����������� %��$�W@	�p�d��k����*\ul��u^��Zxjj��4����
����i��7[�`R����{
d���a�S|��=��]P�d��&Jw���������M��y����Lg]-�����������������Aeh�A��T���PEl`��g{{�N�8���H����?�b)��!�\�����M@E��#P.h}�R��&����M����l��d���)�|������w�4���>8�{�xg��7Co0q4Q���}��������U�U��G�����CZ0B9�F'�l$bj] �~��5Ui��lB	:E��Q/y��NS5jk�~����m����v�����_�_�@93h#8|J-����-���FGFD�� :u�3�#A��#�0�z���"��[��\y:�(
��n����T�]����8�$�]���oG���q��1���lA
���~;	(�j5�EZa��7�Wi�#c��W�bP��$l���`�zl��M`�q)��~&�5v�!����]���]��{E�u_�4������e{��9���ho��$�����6)zS�O��-�(0����9�9�F�%V;Ch '����|��������SA��9a4g3�]�n.M�
2��h?M?fi���TL�D����3�b�RxLx��C]1:�(����J|�'����-���F�4�����r>N&��I�]��<��a����&�p��w�rO�@Q���]<�l�Oi�Bv�w�9���o�v����{ z#^3�dD���f�����`�����W���\�����\���m�V"D��QV�,L�y'����g��d�Xe�u�F*^�P���
�b����E���cs��sq�������No�)�=.��1=|�k9�����pZm*V��]�QO�M�������jn/�i�-�����E�q!�������<�����,��Q�ojM����k��-��i������"�5�~����w�K�����Ws�W���V�eW��-\�lZa�8]�Y� ~p�^��_N�%v��"����
~n��a	R^"��}����}<Y���
��S�)�<������!�VN�pC����/�����H�/�v@/�t��
��B��#�}_AiME�@^F4;�C� <�l�,�9	R����-W�<<�b�\�	�7h��xY���J-06TP=�T%*��Q,��E���	�s����9F7U�n�����������Y<���Y�<G�����Y���w]��Ke�%	��Y��'�� �\7�E1%��c���<�������!H�@������<��tW�(�������*����&�1_��R�V?Q�C,����4�\�2�,E6,���R�<V��r^��o7V0S�V����G2~�~�����)�R}���������"^�����=�������]*���R��J5�*����������Np��H�,�n��f�4.�����w6"���@���+d%���W�/
NOV!W����G��
�Y4��7��9U+������|Fs�X|Y������N���Rq���Z0tY�@��r�)����t��W�&�kc9��������Q�����ago���z������0��=�R[K	�6�J��E�cP>-%�ku��<��Rq�U��Y0�"�L��CO ��������0��]��F�|����lc�q���rg3��8��O
V!_>C���P�d�H&:�F�(La��&�k�� ���ID�����n7|�F�`�Q�$�=��0�M:�����O��|:�z�3�K�:�(�$���f�9��1S����TY<�@D���^�G9)�GSRt<a�U��9���9�9��^�N�]]��U)a!��Mzk��2 �3(�:�)k���KD(�����|
���j�|�8���B�N
���������R�x�&��&�v�M�$�V��y!z��7%���K���U!�x���'���s�1�nM��:�<@18�l-��v�UC����!��i�V�XCe��|I�U�F;���5[#BH��!��:
�K��C��{�*�;�|k�� �>mB�")GE%����(`��_Q�T��X�ph�z>��SY�0����-����_L$����o�7�/<���X�p��f?���( �!��1�IJ_�qeyu�fw�a:��b��z�Ui����\��q���r���^_R*�S+��X	KE�rEu��
�����!����h�O��(����b��,J�y��#�W.x��s$�F�k����'����-QG�w_��@s������k��>����u�U����#������/��,���q���`S���}G�B���;p����#Q{���_#��j�-�7��[�3�^'�bj%@5����+`��a��d�	���x�F���4�Eg�Z���l���G��uV6�2���C4Ws{� 7��n�����5}����Nz_Y{�$�:<.�g����jZQ�)�8cL�sQa��@fs(��UKY���W�JXJ,|f@8V�JM1�wDX�H�
���tgan���O_QQ���Q��6T����X��;C�}������Y��������=���E��EFn�h�+F���~8a�[*3m���z��$��1���I���CjDc�s>������
�����Q7��PDFJ�(A�@��K��
�� m���l:cT4-N�E=@1���TP����VL�qj����tR�@���*I;Z~[=�Z�KG3m������;�J�?��h!99���.�_EWr��&����i�S����I �^��VT>4�s�G5�8	�8���K�i��G3$5]c���r��y�P��K��V��xZX���?=�9�b���+�81
������U�����ri����-2@����<:2EM&s=�!��.|3�^`"��$�����|n|����.(��r\�E�M�5�"~2-#��j��E���t��&|<��29�5Oo�s�trT����t�iv`�����i�X�~��Y���{�'&�?�y��|�748,5��[�3%��D�82�����;�7��|A!,b7�
3����"5U�\]���,��j6r�{P�%��~ zB������bP���_��&y$������ ���N�m��en���'z������4�0��1<��QF3Z��#����!G(�
�\��td������z	�����Wm���*����y�����?����q����Ko�����9�&d6�/��s&��)�)w����VAZM)U����(D��r���3����;)`��e�h��0P��4�I�5��*�B��&*�Z)���Zmq�V#����&��zPB�H�H��� �HI�p*���0�[���]1G/L�#�l�-��YV@W�i*J���e�G�i/9K$g4y6\PY��-A��q�-��p�%����:/sO��4�f��zj":����0>2s*p�����qj��NxPg�'`�����kE-e9j���s�]H/�
9 �-�$�t�O&\j���V��}�1F�g
�� ��J��:���^�m)i��E`�0��f�(��vAgB�i�;:H����NT8Z�l��)2w�i�c3�	�4+��I���������i�;��K��������)��D�4][�	�v$pF&���f� [��������D��7�
��y��U�3�����eb�P��ru�24}��Zu�R�;��VK�b~����2=�;�q�&L�!�1��UC�p��\+�T�	7�0q��$K8&:u����F�����neb��<Pln�DQ��oO/��]�C�yix�rhV;1#��-*������&�L,XS
3�,�<,�4�$�����z�H"W� ]s�	����~@4ST�|�.;���Rw��S��7������K�K ����K[�!7�6���
d� �O�k�
��D�}����}����v.cbU[��e�)�G��u��vf��������#�xu"m���hw_�b����F����NL��[/�����U'���:�L0�"rl����8&�kn(����Q)����yj�84c7t(
��S� �=���N�����������������&:�������k�d�e�N���U�zc��,���V��|��$ {�-�	������Q��r���Y�1��v��=-��.��Z:*\Z�z�T�yw)��N��(�>GD�����9�����'��'�	��I�*��>&��8@jM��
��c&�{z�F)6��b�����{������pvu��C�������������L���.Br7YsBXT��!��p�"��d���Z��uG!��c����F�W�W?\���uD�3{��m�U��l��'p����(���������g���S�t������Fo�T�|���x�v����?��w���Q�G���4?KR���d"�����+%�Q���]F��V"�Y�:mp�"��vu�4y�����A�����,79�d�nI�����
����b���p��h9x�����8������=4��3~W���.8�q[���)�%�3��/�O����I~��
��(3{�X\������eK-�L�*��G��	�����{��X[s���X;u��
�'�Rzd����A���__n,��1-��������u�y��IG�(�w�o����(���R���lc%�!�l}�h��b�_&�u�('u�t^_N$���I��vi?��o�����T&8b:����������$K���	�H �@��z�m@����MAOM�tSR��A[+%����g���%��HI6T��������%2�'���[m(�W6���5L���.���T�C����1:��@�������5R#�s(pK4f�0��=�����f+�G���OsfEM�D�`�`
����P�b�����w���Y�8�fo>�u�0��\7d.L��.���$�JS�u�>�>��R���pI�8�b�f�@�����%GW�S<K��-����l".4�\��76��
u���J��,!�C~���l��QC�����D���wz!�b>*����w	SA�@��(���jf�5�����|<�����[��{pW}�>�N�`���6�ON�NT�jd�)��A�p�+}��>�P�aq���#���K��x���_�q���s����|54��Ve���o�c�1�z���=�T���,�{l�^���O0����^^��[N�����e��f^7��z�F�2�{�H�F+�/�X~�	n��TI�utf�����jT=���<��%���iXj�Z":����.
l���|��c*�k�������Q�����}@i�2sp^e){�X�*l���.���_��^<�p	aF���/�fx2<S�)�=�����p��)�?E:��k4Fo�����C����ma�����~��������f�a�o����9�f4� 4�!r������8/yGVW�u�k�zD�
U���,�r��w>��D���+��s���1g���D:�}�����-�D�B�D��doDo�6	�����;�{��u5�bB����2��7��@�]�Zl�H!ml��V&�t��C�-��]w����X�+�!;�Mu�?Xe*F��Q
��G���k2����Eg�L.�����9���;z�u^���9�7�c��iW&���-�\CM��h�D���>K����I%��Q(k�����"q�*��q��b^=6W�av4�F�f�P�1k��=��9K~M�:��w��w'G�1���h�������>y{zbn������@g�������N_a�k�eQY�� tm���������M���p���.�+$�`���&8���-Q�Uq��Q�����s��k�v��Ax�}r��y��#rG����hc�n,���,c�d�I�����*��n.���1�
�Rs(�%�}b��������SZ$��� a���lh�]�p�e��R�9c��|��_^3Y������|Sv>�/�]M?y�q�Q���)�M?�wg��j^�T���.��`����{s���jLd(�k�zK&���� �}����]���pM���=�R���d��p�|]����"�J����n�`���!�!
�F3�w/��?F����-��o�\��`��s��}$�����������A�j{�
�;3��ak3B(!W���=A���
g��@	n����{#]t������?��up8V��"Rt�������<���Z�^�L������K��&+��-"y1�[M�^�Ld"��q����x}-<�2�m9A�'b�.e1�4���E�R���&�l��gD�,)�\�afp�����TZ�p�J+%6��,@�6:_�1
�b�������0��PcW��6/�37��M���S��!�k�j����Gi����{�-�W
����rW?������	�~N���.����N������"�"�D4J���,��(��<x�i[6�H�i0����iv�N�����n��Q�
�-s��c�>�����/�e�U�|�	�6�/9���<����!����S ��W��y#���A�Jtcx�"�nb����+��M��
8���H/�#��h���~�s��FmK5y=��y������<�2���
f�]�����X5�P�#��a_���S������8A�����=��Q���*��	C��.U�XS;hf)
�d,VRo������r��JW�V���?.�.i����fL�O�.��P�Pp*VuF37���@U4O�UE���#�T���-D��8��=��EC@C6���4�A����6��p�G!wb^Kgn8H��Q�p3��%�6k�Q"��.V�T���G?�O�����I��I����Y�V��	�WH�����q�s��U��T�x��T����[�����;��g4����t�]���
��Sb�.���O�%��uT����#����x�9
8�^���w�A�kM7��J1��D�#�w�}�������y���d�JH+�������BV�s;}���h�p�C��Z�z�h�����#v����o������V��TCC���}6����{���l

_j2��		�!���L����H��Th�}�%d]�b5�t�+3�F�)~�[�JN��Q��C�E��zH	S)�r��D�>�������1.������nZ|��
$���3��[;zN�i,��1��W�Dhv���'a���J\�8�5.W��G��#"�x@9��m����K{�����t���m���@H}r��jM�x��x)��L���|�������M�)��E���>7(	s��(�f����d>�f���A�
5������zb���Y��#�����NfS�I���2fL�o�����,��C/z��������AND����!���i���fxB��iL?�
��o�#���]as���H������x7p���'_W��;~s���y7�7���O����<��������-{����Dh�`��.�nrs�z�������s��%��e�n���_]������0�Z="�U�m%�o8�s&-�����B3R��������Dd,���*<E���Y�'n����`��w��Q�,��`z����E<���h��gIrO<h�����#�������[i����&B�-���ah�u�����X�n
Fv�����E6����K��Il�;��T��-|�h������,�[�	���E-�(Z'*���E����N�*��`����$�C)�c����� �H�#�h��Z� �I��6"�
tX��X�q+P�p�G���m�'-Yu����S���	�!lqI���+C������C+�"��*!�����x~��x��}��O�]F���e0H��8<m�1��C��X�FF�����&���Y�%�/;���b�^�\�[��r�e���%�e@���EQL������n��i����!���w�-��5U�{����!\����Cx���������V��d�2�J88���=ZMh���R�\$,�V�Q�Q"��o3:�@0{�|��jA�
�W���8�������<~�+1���w�w�w��/�0LB�VS��a�t�������	��R��Ut-�g,�t�������O�����'O��O��Z�)=G0L_����g�
|roP�l��q�����j���u��F�eK�	��)P��yD�����\�-�b	1z�{A���?!��`<
t����+Q��U
�������"Cu���n:��|�`����P����x�\;��b������;�-�a2{���'�2����0�H�;��W�O������]���C97e#�I�m��d
�i�(���yo�S��#(%�
�kP����g��Ga7,�����a'������ZI&�b)$Wc	�/~�8������gT���`����#L�v�6K(��~�=������kG�jn���n�P���h�� ��{��A\��8F1�j�nh��t������!� t�F���*/@��.h�@�bQ�I���>P�G�������:yr���K�!�Lz��l~�LAm�.�]��/�"k�S�\pD�v�< ���o�o�o�����������H� ��w�8�s�7�\�����0�r��;��^���>�����t�Q
��
B^t�k��aG����8�KJ'
i���h���{��[-�b�ca6��W��3p]&�����|I��9�j��v���q��v�������:��$(DY���3B+�����Qjh���_?���B+A+�%x����%��oE`�)q��F��i�Y#����-�0�2
��Q}��c�}s���
d�D8�w�8Bn���������Z3<\�=�#BP�-��1����;O��L����;��}�,�$�5��������'
��nt�#d�@�����=4��|F�)���1��i����8P��6�|<"h����{w�M�Z���a������d>2�I��g�.�Kp��4'��n��� �S����k��B\1V��x t���R��p�$��+B��B�9*���������4����t����\�c����������g��h3����G�vL��ya�~�*�"������~���B���Yx����R�h�$�� 	xw���(U{�e&�]k�g�a�5��["v#f5^p�,	w�R�);v�R1����L������&�V����~�K����o�	����w����>���7G����c\�����Y��5y
�����;�N��%����}�B����;f5�r�����S8��^p����SF7'�A���A�bj��1Q���oC.3�l�!���}��>9u�'���G���l<�HG+��x�9�@�*�;0d�7�����L���tC���VxP.�\?��G�Ag��WP���os�����o����o���[�9�.s�CX�G-T�k=&����|)H�
����D�EP��Nv���J���������Q���Im|�a�?,�]v�-�>��4r~~ssK�o�aH����v~�b0�Q?��F4��V�B�6�����),D9N�a�vn��n�3l���k����3���}��V;�~���������7l����C�X@S�^�A~�&�P���M)���Hm;�m��mM�S#t����!x�7II+C�&��~5�!�G��o4-�6b	J�	�~#�fFj��uZ1i�����8����3Vg}U���M����)6�Q���D�{�� ,��d`����3�������k�c�^�[���$��fD���b�?��b��(+�L^r����;�R����QJX_Y��O�l�(Br$�]��b�+�&���<�(i��8��M���IY�#��Q�4�B6A��������R����Ee�s+t<����������^3y���wO=��e�����v��"���a����x5�'KZ� .����QN ��k\�M����q'��t�P���lD[���c��o���#�sWP���-�X}���/��X��m3�D�WMI��!�L�����R�*Z��R��������]*�K��\T:!�a]T�u2��q]�/"f�w�niy��D��V���D���yu��&N7��	"U3��G����Hz�O�J��D�l���Y�7���S�l��)��-J�'����wk�/���];h�R����/���R�����X��o��3VT�.��|���������:�K�w�5��lye�����E���I�a�|�S�I��%��p����y >�D�4T������W��p\��Yc�1>RY�D:W^1���@*(p�~
���K���4&�F��::3��d����>�f��)g%�HC*��La�C��m4��)Hi>�Ii2�SQ��kq9�ats�L-`.�Ax0�;�6�T�H\�N]�m��q�a������u�	(8�7��<�Y��d*?�?*=&3�L;^��$H�"�`�Ch1�ja�K���MreB/D<'2��~� +T�)i4N��v�h'������0�W��O�)�����������N��}<I��U�
����������E�����yp����&��
�o��n��g�*o������K�wz���b��-���������]Z�|j�	J�j�fL5���c�4���'}n4��je#A��-��W9X_i�v�O�����k������;����g/N�w�W��=8k���7N���9��/�N�+-�P����a��i�+�F+_:����8��n{�����(�4��4�9��N����V�p�JZ��X�.5��.��*�d1S��}�p����.$�j��,U�GG�k���E>����������	��u����Y2I���� �_Q����+g�p�s�������'�"
��i"w_������}x�9}��l��������x���O�)��ID������������H�����������p�49y{x�>|E\�TuJ9q�;�U`vv*���@@l�l:�����Q@.�5������������-CWO���v_�.������c�b����������3���W���'��gG'���������/�<n�7�QXS#W/�����r��Y���mJf^_jS�Z�+mJ��Za[]Cp��D!���\)���6��qN�^�������+L�(5T3�D*�U[2������������tG")��p������^�����~��>:��uD�#4Z���7o�L��f��Y�V��<����@�X���=�y��]Pn����^;.�����t���fr�!Q���\��1�F,)�*����KcA���~�6�,
5�����o���$(p4E�Y��'�C�f*�giP��M����4�:����Jj��>�(����N0�C��d�0���T��@����Q�-(��$c��X���+��nN���
ah���g�E���AE	�'�{���O&�
m�Si��sl~."MD
�=��2��f�O��
R��G-[*h���yqt�0���d����~�������������c:�V.�R��w�g�&�������[L����6���16�����;�*[KKl������F�3D����)NR�n�t��������?=m�:|�X�i�"��3XV���.ry�5b����,:�
�s�H>�E�%2�~y�W��FN��In������J"�LB(e�P�w/�/���q������~��>�V�������;S�dY�|����� 
���DN�������N�K
S�VnD�
��)���A��E+n�P��b���AW�������3~!���|f�2����W��(?�-�������A����XK7kY���t��	�����WZ����AhtI<�Q�<4=�[(�A8��.�#�
�0_�t�NN�z��U�:p>f#��ZL�&K-��X�-������i
g
�^�g}`����qd����e�l��W~��h|5��������g�L8;���%f�<2��7�)�NK�c@Q���9@���bS��7��j��B��3<���W1�������l�����������b���M/�j�20|�t_����7v�{�8)�����%��"S�cS������n�"�R��T{(��;�4j�����0�����%��*b�f�r����:��z���0�|��|k�ZT�����%Z���\d�-���,���`���+�cH�������<�������N�8������L��?�O�/����u�����W|F�2�?�
;���������4[��J�����s����(���%Ih9n��v>��~��D���^Mo��P�R�}G[���)���N���kD(H��i]@k�|��*[/�5�;_bv%�l���������/1g���O��5>��%NM
��j�z�]����f�F2��jvJeH���h���)J�h3���������f4g/�0�W%,bf�=�k��}v|��[����Xg�*�Q�4�4D���GDo��T��l���4�����H_��(����T�Y��s����U�������3U��Lw���dr> ������N�� ��7eSE�����bH�+��17i��
�uszg��*�S�f�]����2R�N���Jp0���!H���`QvS�Ynz�/9�=��t���f6��������H��}7L��o��g��^z=QJ��>3�����7
&�i$i!���@������B K���{?r^mB��(DhO�P���XJ��	0	E=��|������N��58�4jD������rKBG�M����7?�]�u`�@z?��p��b|A\�%�bYfw����,�s~661�t*Y��o���j��M�
��9Ku��bFv��o�6�����N^���Y���9{)�/�I�V>��\sA7|�Mo�
F�Chc@�\e�"�d��;��.�-����g�P:+�m�`x��I)���0�|v
@1-��S-�r3�������=D-��9���U]6{M��s�W��4�4�������j�-r5#���H�2OeS�v6������:i�9�
��z�YW��[������7�6+�K��2�@mn�|U������V#������~q$���i��(���H����a�0�k�e�t|)G��g���X�� +��"�5���������E�8]1-"r�ZnE�Yp���i��������e>[Om�m)i"(�G�eE�H���
�w�v�)���F��.���>>����P�����$�rzE���v����;����s��xmm������Pb�
��K'�8S#e�;�]v���o0�m<�7+�9+��'7j��
�Q���\�yq��do�������6�U/hMM}q6���@E�U��r�:�w=$��m[BN� ,����{tx�c>K�����OTJ��O�:���|��@&�J�%��g+�z]7���{��������r6��CI������y]�7����Y���m������H����/��l�"��[��B�<[G��`����~h�Ir��]�c�k��������"b�yX��&�|��Cv����>��fLE������K�CZ|s��_
d�p���[���������f�(�P/�Y�+c����L2�,�G�������dw�@vw��~O�G����d�3�^�+K�����`�"DH�LjJ+c�>�|)�7@�����v�u��::��K�d�Y��7~��n�����>ga�c�����d-��s��;c���[+'��N��g�����"��%�j���X��������&���W�dE~���3U�(�����P���,�pK�1��~7����Q5N|�"��j�W��3����P�>�@�ZAVX�.>M�f<�FWU������)���L�� *�� �h��>��a8��� ����Sn�$�-N�8�R���a�0
V�R1�F��6�&��+.7�=_��{�ll�"�0����5i�'��+�wM����G�:Uzf��������������#�^�(6�������@��ac�a�I��U�>`\��XN�:�����nxr����
�t�|�L#��L3>��4�.���x1����]sAn���sc�Q��-i	_t�\�K1��>�kbF����&a���>��*$��/����[��<�;�^J�,%�B(��
��lx�O���H���"�7g�"����JBl�4���G'g;�W��^��DEp�6
5-s�����m����n����$�h�������������
u.��(�:�fP�}���(��x�G'Su$E�O�`u"=5��$NF�b������i��Y2�#��Y���\�����F����d�Gi�o�]8�(h�;d���j��=
�\���4��?�l���#���P�������o<���$��%���_JeTM���<�Bb���$�r�	����SFF�y0��N<c}+��f�d��� �����i�A5�X��B���v��fQ�[��bM�c����Q[b��	U:�c�N���� �(Z����u
2$C[FbO��O�:u ���l^������qy�����%o�Ov�����E�~��e%�E,�����n�9�����rEF�=��*?��i�����lPM"��r&����h�YHK2W�O�V���.f�7b���:�W�P���r���q.e��%���gnZ����a�VqUW�������>y�����B�v_� ����@xQ ^b���r�{P.��H?�Ql�&������4�VX���<z��fP��G0��j+����i>��Y�����.��z����s)�����O��%�o
�Oz����Q�z�t�^��?�6:���b��*����4�M�_���(�Y�i�:[���Vw�6��"�8�T�#�l�$�9���Q���x�R5�%�2�I9����RQ�C�|����Hp���.U��%�%pf��P�w�G#l�������]��b�!��pp�0�nd�������,���������[
f'�q���`*��x����h����v���t_�p�#���7	��
(��2-�8z��yN��.<��Q�f�z3
	��a:�������~5�4�L������Ty�Yt�����`^\Z�Ot6F}
����������%<�AG�%\���(d��O�`uz`� �k�%�5|<�.���y�`�$�K�mb��yVx�tfR��Y�j]���-I0�k)���"}�f��ePe�^�pH�s���ui�W���B����k�_�g�A�~5Gh�W���z�E�$���|���4���?O��-wU��~�X����P�q9��(CwM��{��"_8�rND��z�k>���I�.��	�e���K��UJ��7���E�,�����!{����U5�����,
��dj��`�V���t+�5*��M��Y�!+�����=	.q(����GK������s��QoE�����7�y��BL�7<��������=�=�����[n�s-8���2_�T��<���	e��S�&-��d��B�H�����K^P����w.�r������,�]�t��u��OF���2�E
�U��O�<�tf�<�)o9�+O+�G�Z|�����_�lJv�4d�������Nn�	�L�B �	�d<u�)�(�8���d�n}����?�����w�B[WD�f�E�T^�n��L�-��yJu����4�
�G
��~i-Y\����#����i�4,��������(A�.5r�6n�&���<5���C6{�o�/�_D��*_D�c��K
v,�,i/��E�ac��afbo�L�����������/��9���c�N~���,6:�9*RcK(�V�z�7�(.>p^
������y:�Y������/���P����!��wE�N����)i����'�J%��Fh����*%H���H[�G^�h���
X��O���L|��?NXHu���B�"b�!y��L�3v~���o��xz��/����
B�y�Jk��5�y�Z�P��x�,�AS����� ��gmgT�;&%�9b���s<t@|l<g=�lh����=Pi�6���ks��ScD(���#������D� 
VP^���ko�S�
�,|�^�G��������;���y�3>T(\^���H6�8�c�g9���C����$l��-+K,�����$�����]�������}����J�2S+D��a�nsf��$��%��#�+��)�>�%�_����I����zF�����������-����4$#��S�y�c��*H~�Z�~��y�c�2�6����*�����y ~�T��WZI�S����������d��gI�1�NQ��By��]��8�����������������+����4���U�Y�3����&�]Bpq>�g�!�M��O(����:C	eT[�!���#�5�$��ZKi��R�]#�2��u�R���'�������C�����hf���Y���f6�|0��GA�6�|�~�x^����gu"�������w>I�gw6��Vr��s�p�5Y��.�����h��Z��y"��E%�O����q]�9`=�����H'd����l��8��b��9��K�����'�3d,pC�@p��Z
�&C���R�oT7e�#c�d�����%�#�V"�z�����~����8c����)�G|��SB��h�����������(!�"�6}��cO	�dB\������E"B�.V��� <�(��J�b8�^��������o�{����s@3i�0����F6�B�����������g��sxt�i �d����O�g���=������aq���*b����?��������\�I�@��Qq��J��<�+�M����tSI(��f{/��EzA�*��(O���r������D2�a��d�E�|��'Ff92����J6����������F���%.^��v��Ge�_Rk]qJ�P�4$��y{<B����J��>X�MlB��w��-P�tQpk1��3������YAnq}�c���)C)6^2PK����=C�K��FK[�&��49�L
s���wo��Bh
�����="?���'��78A�A%��!u��V"6�A$��8�Q!�c�����Y�KN�=�����.�+�C���n�c�PyK�e��j���L�:�)Ry��1npF���p	����Q�h�-?Z	|Y���K��AI�����9?P���g��z���2���9�3����n�'{�wjj^,XE�6m�:Q�o��������L��!F�>jW�)9LG����@�{<�~^7�]ea����J{��j�6 ���G5����t:��� �`��91M������qaT��nW6kHw��h[$�%��E�'��~O���{9�$�n)_�H�F���8�!�hwI���_�avbX���&��T���
����J��t����
���'��92w�+<'��>�O���QFH�|B�[�j���%u�!a��#Y�����]�{��>i��	��c �j��pX	w
��hD��m���g6M�r|�]���%w'��d��mYEy�z��_3�bJl&�����l���DZ�ath�t�2��$A�*c��Y Z������D;Zo~�������4�n�]K��m*����t���m<Y�@����'N�R�ee2��J�2����U)S	�I�w�Hw[��H$+)�}��'g������:��C@�K�y�"B4������aPt~9��a����\zf�N��9N��G�L!���^���fR��n�U)�g&�
�nZ��<A�*v�
�r= �?��P���m� rW�r�-�W�7���eV�2���6�U��i�������o�sT�8���^!U���Y4���U7�U����o�8Zs
���Q>)��Jdla+7v������Q��|����
5B���{�2�j��M�� U+�,������b��������PK}I�W��xI"\dln���R[}���(�v.��E����w�����-�+���	� &�����Lw`*���P�����2�.C����xF���JIQ�/,c����(��E���Dld��p���tF�&��e��G�U��3��1T�=� ��'��j>��$��ZI@����$��YU?���+x�8��r����}�c�BH����7��b)�EbB5��������:
%��j�-���#�����:��n4|;��'�{A�UOt.%5��A^��D*l���?�nv_x����zMhsL�]�����-]d��o(�W�H�}�rc<�w�������x��}<�d�:Cy4�������3P�U��'��w='�n�{��Z���-����`�$��s�| ��J5���������B��CX�!�.	�����0�o=��w�C�F:�P�b�_��c����s�<�l�1J��DK b���A����=Gk.��K��r��-LI�|��i������W;�Gg�0!���h�_VlnJ(��(H���y��\���7�4��~����v��]��<x�r���h�t�����r���Y�M��������/}���{<C���t0h���T��l���z���&)��!HEqf����
��xlq��Tf!k!5JQQ+��
OP���.��9����s������)X��"�(��2��z�"����$8�w�������r8��~��I6��5Sr�?��a��|!�������Te=��f��F
H�7F����R���K@)�����VF��s"%��F�G�h4�Xh���p��F�2�<}���'�_������W�`�F��F�Q�C�'��b����������o�>�;��
���m�	
�<sY�M��%�mh�^���_/�I��Fh�A�g���S@9'!��6���4��W�-��`J�1*�Q��Yp[m� Qw��?�b�9e�y`l�������@�l�cpA��$�]�#*�����}L�A���}�V�Z�� iD�s:v*bu���_E��Q,U��0n3c�l�d+#�g���s�_)��4�O?"
9��>fie3��D������5t�?�����	�`�("�4=��v 26���X�A��m�/�ms�$��jMG���z�^eI��5[���A����������i����K59^:�N��K��2s$&�K6@5��U���v7���Tv���&*y�m-�H�����R�mh�<rh�%
&���2I"�����-�C��Q�Q���B`4�z�~gl1x�N��o���ZI��(�,u@�-�8j�"15��&�JD;���g,q�
��vM���Kh�Wj������ct���j�r?����|v�x��U�����V���uo��Xee�{gQv�{�.W�&*�D����-B�����<���Q�5���W"�W2�����|�e3_`5�����K���F�j�jxF	��	�������%�n��k�\W1y�	�U�y�7��=N�r
{������u�NJs�M-������}��Y��7�T�,��%lW%����N��%�YR��z�KzF��
�;��������9���'��c{�k?b^,�k���nr���mu%���'H��u1W���H�^$(+�z��<�vp$��pK����G�����(�B��-W���j<��p���������M)O�r�E<n[=��[�E��J��K#���S��B���G]�zTpkG��O$?[�Ig�����uXRIP5$�vf�Y:��1�,������?�[�w���=������yg#z��3�<�"�A�xN(�d{�� ��2����cvF�[���)&&�8S/�	�!{L��U��d@l F���G��LA�.��h�Z4.�jl����^���*bA	�t��Y�U����,���;y�
��E$�zx�����'������n+����S�:4lAF-���J�&�O{4G,���M-�c���
U���Q�`�d�'��� &���	y|]3�����`5m:��G};&���f��< $D���>�?X���;r~��o`X>U��,g<����Y��Q40�Eb���T���jT*�M�������=<��D�o��A�7���������Uc��$��n��E)j����c�s�e�[j����������=��9m����m�p^��&����j��O�v��>z]?�������]������'��0XI���l��t�F���"������X��?��4�[��/�c��I�2J�n�&�)U���U�u��8����������qXE�,DL73d8������������[��-kH_L��� RP�lI�R:��/V�9���JV�MF"���B?���^V�yeV��~�5E��^:���E�9+�U�|��:/����p���)�{�����������t<���C:/��(���^��#s����I�}��[+|����u����MW�.�X��AWKp��BJIM�����	�6_������x�������}��%u���d��_�F>�@�0�+���u���|��.�����U�p�P��+��%\�4���� ]�.���J�f�6�s%�7�'v�C1�H~�9y�wr�����R�>�w��������g#�&�t�v�����iGX�[�_��9��C5�����m��V��] +���#��w��P��'&_��#�q���i~��<=����{:L��d����-��O���@l���Qd#S]�M��[x@�5D���9(c�:��{~���tf����G����bN�z��������<IL���	F*5��I��i�#%�����d�f������EW[	���|�V���}�������I�<>c�Mrn���|8���AJ���u"vojd�
P�D�;������LK{/�
�V%D�Tj�'� ���&N���������X18J_���>�p�������Z:�.�	����C�`���GT�����f@��R{��{�(��i�0���h�-�h ELZK�aF��B�����y��o��+f�w��<��<Z���/LC��y�����T���9'����7;��_���V���dK��8"P����x0�a7�+���`\d���]����tO�/����_�l1uU��(�Ej���I6�oy��s�wtx�������/��;'iq�j������g4���xd\4��-����lu��R�����@��q=d��tZ�*�b3>Rj��������_�k=��4�
h�9�����a}?~�k�6���4Tu(����4D���z����4��[.yc^��f5�Hg�����������Y�����tW3�Kg9����\����%_��iO�kvz��?`?n^����_'���)
���.�kbY\��CF�q=�/_(��?����}>��!1@s����i%o9�{��0���V_��R/�O���Z�J��-��-@���U_�U���,7*���`<�h��i6K������
���a��8a�T���Q����F�����o�����(fST��I���c����;7"`����;���SVF�zk@4Qs�H������/��m��;�'�����"��C����v$�IsV,�����g��},���ZT<���!�������hC�
k0�����|>`-c<��#'�)���$�lv9vUj���J���M.:��`�C�B#��?�wh@0�H���5�����	C�.�� �/�=\U�4<�F����S��S	e�$��rv��z5�QV�tv{]�<I�\G.�����ti�Iz��8�u�e������Xp�,�����{!a�
�A;v��K;33
�N�������f��`_���u
��l*z����s�B�#w�|�BB-Q��00}���$�Vg
�9�������
Ia�^�h9�4|�W	%��]DO����n#W�}OU��H�g��\�z������;��G���gh5�)��YE�c�>���q��/����)w_��������0�3�w����l�k^�l�x�����c����/�*�%]�zu���2��?82r����O��2S����uo��#��!��N��`d����a-�V���R	��4%�����p�Y�
[09f���4�����=
���FQ�x�;NK��B��Ub=����!�7���#u�p�
��.'��3t}(#%S�9ol�e�(1s#g�4�W�g�n!�
���OhR���YE���������EF���5g�^�u��JAF7��Y�����I�x�D>2#;��P~��������EE���&t����cF:�Go����S5�)L�i*��<E�7]�Y�9Dn,�������i�4��A�i���<�\�S�*1���isFn4��7Z8SV9���|4z��������I	�)E�4�}>��{�i(�v�N��L����`���^���"F
g�� aw���}�����r���!�0�6?��aj�`�H�Q*�'1���rO[\�r�%��;�8N���q������q(��Z�K1�/��5��G���U��m��U��z���(�~���Z��:%��a��1����������
��S�ts��>�m���vO�;g�O��5����Yr__n�^�X�>��c����j�_�i��0c(��]i�����e��`M��H�����9�?{{r���9{�FP������R�������6E[Z�����s��s����g��sg��?���/p�t����^Pj�6�k�S����~{m�~��[�O�)A�`?�lH
�J���@��G�.��e�t.��p_J��%�o:QJ%���nK�*P�i6��L�0z�4J7��!���#��|�	A
��u�6����� ��)��W%�U���R���^v�pBW���3G���s��u�]
`�E�����	����}#�Z����Vyh~�[p�Wa����sp��tZ����j;r��ts��}C���Ff����������J�C����n�����UK*�HN��*u�"=�x�P����qV��������3oS�F��c��9�PKj��j�%�1��&	�|��-([y&i��&�Y���Z�M]��n�O���A>�p::A,E�rT9'�5�.�x��vNNv���u�O�\����pr�9�k�i�6<`,�`Ie�T����1.��F���<Z�D����Y(���t,�#9����"����4�s��9��n1M?%�'v��C'���A���O��g��y�y�p�h�y��y�����9���ayl����2����� a�����E�G�g�����Z����F���I��-}��l<�E������{�v�qO}+_I�J�`����n��H���J^m4�&��������\E�����Y�������a%A#s�|�p��K�Wq�����^K&��j���� `�o(�Z���}����J���F6q9|x������"�8�h�M��Wa��P�|��i�|z�p����}����>���B�@����A��O~1� pD(+���Y6qj�|4�_�l��Q?��R��@���B-���������t@��v�N�Z�#��E,^R����m����0��%���e�.��������)�����2��cAn��v�T���������������[F�(k�*]P!���x���Q�P�44�������}����e�]�Z1C��
;����6
Lp|e�,�j����R�n���SN2��a�6IuCa�V5�X�hb��x-�����������b}��R���-���Q`��V������]B5B�4�Y+�~�y���n������������{��4�������a�L���}�^B�+�N����rn�/�{z�(���T_/��C��r��C�5K�d����x��4^�`�|BU�D��t����.r���������MS�1����]�d����Y�@KkZv��9&�C�r�5���G��d^=����u��A2P���j���$�
��yy����x�KV���xi�6`��T�T�+�������H�Af	YD�H�_8���+��5�~����E92�Z�e�5����m�w�M��&l�+;I
c��.�i����Z������y5Vs���������O��7���t�.�+%���X)����^����V����y��O�>��w��-��f��[%�)�M	?����y�7�����9<:�?�w�����%�����}�������!.H!L.���`u��4f~_s��Q\V!��������n^L��$U��"���lH�66�p�b�����k����%A���1P�	���G���6Z���_[���oF0�Dv�0D�"G�-��.o�6�������Z�A%R-�4�M���H^/�{O���KHE��IW�}a�0C#b�R�����Xr	mt��Wv�0�1�`�"k�7-�h�����3� }`#V�"���c(�[Ci)��.]���frDF����I�I1�0��1�������X�&Q������\=(�1�����\	�����.�}#IQ
	�*�3�6f�M �j,p*u���2�c���	qI&C���*���,E�t��+v�~p������l�W1]f\DZ�#b�����cS8m�$	j�Fy�H{H%`)�b����������8��)o������	3�w{�����I� �1d_�S�U*��1��i�e&��u�/���d�
�1O�4�mla�Iy��9N��vFj�����M�2>�s,M�Qo�f67�A�Z���ZnnW�r>��o`FSF�#��]S����b-����>����	�J�8$�MQY��q���<ny�	
�����T��vsq���V6������`>���dk��t�ENJ�/.��b������u�Gc��T�K��k�����b����_X��:�E��G���
�s�e��Lx�YR;�l����/*"m�
�],��3Kg��z�N#��Y��0�&N���iFfTbu�"�o�>���&�4����-����o��Jk��Q����V���l=H�>a��E�{Y�$;w�c�!�'U���H�F��Rn��b&�;����-�J?��/n��2�bbu7��=f(+���|s�����|��V�w�����	��d	^5L��?
�U�����v��5������V��*
�W��2����9�����������{;g�[{��g���r�;�w�n�����Q���5������E�
��9���
9%98����~v����6[�1z���Y�6g��#5��DF��qY`tL�u&�~9�HK�����C���d�O��s*9�8.vB��L��TG^�������T|G��b�d#�`)8�?:��?��x����g�����}��9�9��B��?�K�����+<����G�||�������N{o����������S3�m!�m�e�-�Zf��a�������N&,W�^��^h���P���_\������6veFJnW���A�����C_"_��`m������FIvz�����f����C�1L��Py����u9:j�o�E{�
�c�R�h\�������|��[]K��Q���`k=�Y����JW��o���W��/tbj��M��
$���
��nT�
n��B�f��$�y�YI��Z�k
].�&�~9�k�$%X#|4�������%S����(������H�8}'���s������������/�9*��f��������~���]��,�����>�f���Q2�f;�F6���������N��m;��c��
>�29i����s�#��L��db�Cn�����]����\���jQ~v��5)04���#�B��+���O8;[CHLp�	*0M��tjxS�Nn	��d�K�I���m(�{a�oN�a
	e>�nZY5ZzZ|VK�����-�F�f�_��f�	"}8��Y�����)a��tq����%e�-sNp#d�q8���R�[�;��n������GI]5bt�0M����������o?qsv5
@C����rB��Y�D?����-���������.<B��FG��+n��j���~O�Q�Mkx^�M��)4F~<���O��	��{����x�n�,m�>�#t'>S7^�"�Pj�%G����{�(�:7�+Y��%�ud���=� n��;nm�|.��3�`�"#X�u�{�_�4���Dr���Mpz�U���8��_	;K���
#���GyqYO�\��3���)���%�����Y�&��Se!���$g���TR%;g50��l�����"S���z�V@9�/.���@j�U��T�$�����8��$/9!�����������S�,�'7���V�<��������^/�'�K[O���s�U|���)���[�=�
���n�[lQO�KG��{6/$~.�KZ�Y�)��~rv�sz&"��-�F�L%��������IC�J;����^�D�t6���Q������R~��Z�p�}��������{WKw$���{�FO�[p!j���_��� ��jk�d���?V�n5]��<�]�N������wN���/�&)��t������Jo�N=���������5X�:��s�P���M�,�L
C��d%�'�z?Nf�����`�%�jA1���6�P�}[,�_��l�]�m1��}��bU[UG�Q�)"�C!�D7����=����|�������P�_F-&`*�V���0W����1[�������{�|�	��z�L��>��!�&��3m(P1����d	��1;�����m���Q�J�
����!	��SA���9�m!�����!�B�{�����N����C��5c��I�����7��.C�Mk�)���O9�N��9�Q�-�]��������$��S�����5�l�C�D�����3/�c}.2���Y���M������t��A�g��Y-T5��aOn#N�%:�L�wgx���"Lp�t���S�]���s&��Q�S���_��K��#*�!��x�!�~>���X;x:��b�U�26�Y�JSXk���s��B�?0�5{�G��lc��xx�V�����A�En.���s���h�������,��l��u�y���=^�����U�1��o���t�G��(�B����U�(��g����0�}���x2+{qT%�dO)�+cxu���qh�A���SC�%��oa�e�����?�O��g<b)t��4�6G�-C�6=H�n��y��l}"����'R���8: �H����s���t��R�t|y�����N��r�Vg?3�=���G�_�~Jj\+�������f>��k76���_�~���;�N�>m��?���y{h��������6����>d�p���;�z��?���1����|��Hc��ut��)��R�
��5��������~�ctYV��m�?����t[w��)��.�R^-T�;����%K���%����@���x�9o����Y2C���l?��8+�+?��9=�y����d��}aF7��t;�����������W#�<&l�@�����
�~�z���5�N�J��Qg�y�����[���o�Z���`������x��5��n�A�Jhp���rW89�Ish�$�vn*�Z�����mKA7���:j�������c'����P�mVS�lK
}����\#�}��d�%�v��
~��d{�����XoO�;;�`��ro�B����s�}���E����X�%n8����J&����Y���}�~���,�����U9�%�*�����PI._�����$r}��V+3�����P.w_t����E��=�J���P�e9����{v�������������s�Q ����Zb������0�qV _��Of�[�Ev�6l�?���P�B��$�;�J
�W%�r�Y�D_����q(eUe�	�n���� �jYD��:����U"���*7�p�<�(Q0��N<sg����.~�&Lu�R�^V��_)Q3��b=6�d-�eTQ����
yL�������+��D�(
Tk�x���
6OD����x=,��se�%1[��h�>������j�p�k�1����.H=l�I�����fJ��h�'�;i�����QM7�����G�'�4~������f����=�	�S�r��C�!��[��m4���Ji;_�����y6@6�9P�b�o�������$��r�B-��Z���4K��K�6���P�:����dh�f<r����`����+]���x �&?����e}��m�6�rtgzg�	^x"�V���
�	F	
��h/a�#Q8-W2��Xv'fA)X[?M�gU�8�Z���&�<���H��RF�V<6��7j�:tl.p�x����t#z"><�(.������j���Y��t�x&�5���q��A��[H���#�9�V��@����������c)����2n�'���v�Z�����9�P�)0��\.����!nS���@����M'�3�t��cq3�N���Y�����B!��xURTGH\&�
v�Y: =2�}1�	V�JX�.!��.�G\��������V���y]����e�M�����2�����zs����23���;V�U���-����C�b�7�k�de���-q�]�+F���cE����,)���4�K�Pz����Im��}�p������w�a�STY�j��R��K4����h��g8k�*�N6����GC�/S��&���C\�Q'�c�$�l��N�<�"FX|�!��/�[J��1e��q5����$R��}x�pkv/������kJ�0A�s��JP��=�NB��Y���y����=i�t�����c�2��!��	t��j�I#F3HP9���Z�#W!}2���C�txi���(�\$�H��O"�f�@��e��BuSk�L+(=���H��f6�?�m��1H�OM;���L��8�e�R�AAy���%�.���l��3�2�	������D����|���|,�w���n�5Z���+c����|J�-QN��(�-u����DG3m��.���9(�2Zi_� P��4��q`�>
0��TSH��I�%�����uO�������{9G�P������ �|�R�43x-@7��)A���L"��|F�`�"�'#��.,R��=�z���2������@��P��$V���{�wl��~B
~������?D�#N#���d�z��
x�?�}�A�I�<cR@�J����@v �j����R��uw���t�B���������t�]����������,�
]p�����=p"�M��~�(��~Pg�� ����c�z��R�)U ���������RfbW�Y���-����q@�N^�i�q��hP0�@)/W�cc(5����{���q�8��
����0��|q�{�ja7��C�3���a�|/<PB�g����J��\T�<�
H$���2�N�WDK�`cb:����Hj�z>�D����=.:)|�x{�a)�pI�����Ma�W��^��W�u�J�m_�z6�_���=�������q�7�"����!b�-��T��	o�h
7�1���3�#��i��~DC�����*��E��NN�f������.��7P�/l2��~��G*�$�,�/S)!��b��I}E+i��pZ�A���K��j�}�W��V��
e�t>�1 ��_B��b�������d�J
������'��T1U����a��:;��;O���,r��$wX_"M<{� <�Q������-�d0V��Wd%w�M����,���J<c�-�{6�V 4�`�'���L��8a�4Qd�gFe(�xnV��8�\�s�@�>�[�������OI�&]}���R!�57��yOq��}�W��[eI�h�
�.<K�QG�m���3�"�r��OY��@ �2���1,����D�����f+��NB�������M��e�\h������'LV�������W�����]�l�|V�eK�K�GXG���~�p��;e��y��`8��C*���6k�g,��20����;�w��u��,�����m����?[r������w,�5�-�b��|�wyc6�M��@��^�][M2 ���'�?�dWK�7����,}
�)N�%�^���q���W�����h|�����������0�a����������&��R�4� l����&aC8�r[��D!�*M% �v�#��A���\2^��=p���{	Ws�_������ll�[�H�#�������A��lx��D�1���gT��
�s��N����$3�N�)��I����B��� w��f��������T���&��n�^��=:?/���X�+�v)��g�dj$����J�N.�
����*�>������������MD�k�����-���5c��-5�8*�=������p}c.8L�:G����W6�����?<�?<c>��F*�������jY���Y����2�q���?���|5��J���}��QB��X �����,0�x�Eq�8��b�&C�"��&U�s�VI�Z��� h��mC��>]�R�W�x���p��V����YN-X���pZZh�|�mG)�[��a���lr���u�����50?��yT�����N��
�����Q�Z�c�|m�"?�Y.&��XaN���V �u$��NH��P��u���=[�b�NlHnfj�G����+����#V����%�m_�WD�Ifv�=@)�(�F��*r#*H<b�d~�����&�D� ��S���
���y6~HFf%����z����j��FU��2<Su�Fd/��rZ�����>?N�vi]�������x��
�ap�������?�57��X�4�@�K��(�iX���%u�`g�&�tc��}-8M��1��?���z���S%������#4���2��������adx1��|>�H)�R���n���i2I��v��e�������'-���~5��j^��JYN8������p��q������7��7��k���������2����EK]�eE�/G��@��O��-v�3e��%�U%I�$c�����]es��SY����"$`-D����BC��b������������?+�d�Y3�O�b��U��[����`�vS��&q�u>�b��K7�|��-a������RV���H����y1�,["�a0�t��3���k
�^�����@���N��i������d�a��>�5�S������5!���A%MK��G�?#�������%�W^D#��l��"c7���$�0��>����I)��6$z���:z�����I	)��u&+�����S���YI���7��x�j����Q8�8��e�4(7������)�U�'2�v��8����V�9G����pCv_V��E��e��Rk�w� ���2�
�"��c3�����N�E�m[�B�r%��m�CL����fQU%����A��{H|>'}�s��|A�QW*��k�bW$4�0���7�����x����g"�������tE5�b�Sia)�Y�T�u#-��{9M:�V�����"�P���@#kN-W�QS�
|J3W!N�^�~��6�e��a�87�{�����Z��0��uO�<�����H~V�XVZ���Z$�_M�2^��U�go"[�[�C�*[D����JY��+ ���hJ�%���C�
������lC�w�a�rK��"��<��
�&��V�xW#��L�
!j��y����h�|D����I*_�P����`����O�~_��Y��{fj��1=������R��a�����xx�+��*	��f�y��.x��q]1���s�J��uw�`�z������I��=��\2=��(�96Zy�>�~�?����1��}T���%���sw�AK{U�� ��u�:�]�_��H�$x0:kyb5��X�p��x&��\@P�>@Hx�����r�B���!4L�n$m���������p������"��,��6��L�s��X�U@$�������4�H���\;U������t�HV*�=����,��G��f��s��Mv���Q�->�zJ)��w,c"���Zp��@>�����z��8b28e�A���`�(���
�s#l��X�p#��&�5`sD��+��Ri�6�3��f��������	��\�_FG?f�d���4�������p����'ot^O��V0k��se����B3�����b,@t�,J"�n6S��J=YvcR�G�J�U�|>�)m�-lKl���LW��VG�ks��K-�B�g����H���7��An��%�����1���������B�K�;�B��62�X����"�b��=Z���D���q^����5�Al��M���pa�9��x��+'}3AB����C
�S�$h��r)������pj��!)�.G���07������4fu�}�\��I��N�������F��eH������E�)E��B��#�=��B��f��x� S������\�W�gg���>���F#%m�.�G]�������s`#����Y>��pr�w}��7J�
}^���������1
%i-���:D�/������7�3t�<<����S�tN:�,0Y�!bV���o�[��U)�h{A�oB6�j�y,�����(�6��x��^�/��^�9����9$�����@�%�[b�� �hw W3n
���b�Z���}���@�JR��B��N�F��\
8����d!@�q[GV�9������Wc
~V�������G;G�3��[N(��U������V�+�|>��C�Ppyj�S+������D�0�����W����4h447u;�9��[DV��6(������l�4+�����[��,�x}�����8����.!��K�����0��u�S����y��d���$H\0%��Pz�b>���V�TA6��:�bF��=$�8C�]/�TD�I%(�j�#T<�J�H�%iU-��\s�%�"m��x���d��1��N�� 9=y��}����nejE������_�	�����>+{����w�M�/�n
?��Ev��>�t��n�������\T���p<	�6�wF����
o��(# �a��1/�������b|5�U��������������!C�'���>w�2bbxp�`�KLj��,jS��i��9�
k/�
��k���OsZ�qM�9��Gy���c���L���7��p�:������A�mh�����/�����YLz���������C/����A�
Xl�SP�F:$�PE��,����u�]���Z[�c��Yt��-���m`�?��*xb=cT�|$�"kkS ��V�Am&���Z����*6�22*&�tY�V�f�}�yyt����o����&���������zoH�����#}O2W85�gEo�O��e�1������9N�����mj��_�����
#��']��#�`���������}v��p�����v�pw�N���onbh���\�Mp�E�vI_�����ZW���k��5�7��E��+��$�<���@�P)�<���G���������En*���Y���[�l���KP�pH�L�)c��7��"�q$�i>[<bI��O�G���_���.!�����P����E����
W��65^h���pfc��U,H
�GAdW�Y �>M��{bc1|�M�	b�f/��aU1��k���Y��|��[�(V�t����._=�����)-\���L�S�E�<�n�[�^��cE������]��mf����F*D�
��T���2�?����1n����aQ�)EmO�v;�5�lj����C'��qq/*���Q3���"��	�Z#���gh���]}��U<;���������J�-T�30�U�w�x��M�x�Iz8������f;Hf��h==+Q���������k�QXC~l�+�����w4�_fo�3(R.�c���7�������w
; �V�[���N�}�zsY���H��nl���e��h�/Ud7�7�a	�������y�G�th��o������y��L�Pu�5�i�&Z��S�
;��U`g�� �X�d��MH4+�L3���Ld�J�(��V��`cA0�T!��*L����Cn����KL�����a��;]r$�&0M�(X0����x�i���2%�MSs�
:�Q6��Zb���m�K�7����G�m��h�nR�vi�+I�cz�?0�v�E6�JKd/5�Wa$Y:����fE�����g���3��p�v��Y2����A��Zy����z�Y���W!�#=6��������k��m���h���d�3
3"���M"e�8����tye�\:�P�
������=���A�l�-�
�Mj��vY��q���,5���B}6��]��������,��~�������OI�F"S�I�I<%�@����@\^��!�Q�/@5���Q?�R���$��2���(`d���U��/T���nW/U�����������4"�:(����
,���I~�����T��f�T�\�����%;i����=�'���6�.��	r�D7.t�a��4*(���� ���IoL�8�r���tPu��<qH���L9��*��Z<��k39B��Uv(�TO����������$�l���1[i����&��O��I������B�K��S7��|��3����v(���(*z�m�J������I�Y>�:�f���P�&�TI�r�����i&�|���������O=���� ��B��.3J��n���������|�8_�*)g�f���0Z�c��8�W`Es��\��T"�y6\���R0�7�c������2����_���}�;nX#�\I2�� ,)R0��
O)�}$xs��UI�X��9E��bvYih��������e9}\�rA��+)�`%>f	��v{l�D8H��vHe�������F_�����8^$|�q�0����N�08��t7��R�F����s���x��'|��G#��;<����f��Q��g��	�g4�QVyf���a��I�y3wm��G�_%��~�<^���+���]�X������u�C�o�����s6w�|�z���E��%xZ�+>wI���x��0=^���`	�o��#�<(�I���H!� Y
�;��V�?#b���dR�%�+�4D�9w�6����6��
r�oM�j:��r�?[��-%tR|~�h����&��8�E)P��:l������L����ZSn���bnG�����:�4jG��7��� u<��uq�aL�E~L�tH	`�1�(6n�)xY����G�&�f��+����XZ)�m,��\�(&����m�0�i��Ih�v�����i��a��.�����B6�c�A�2>��<1�`�b���"Z��W���[��50�0�_���V��%y�S�	s�����f�F� s+(x������~�N?��J
M*�QXd�����\�a���
�w3Q��V��F������[�*? ]���+���>j������r5E�+�D�0l���S�q����[,�?O���<��NC��Ti�^�l[���T�3�F(U#��l&o�n����!-*[qy�lz�W)������U��'� jn�1Z6�����^"�V���;?��_5������R���%�$hJ����P�g~��D>:�&��_]�K4K��I���� ��f!5�����~))I��J���9\���,����5����cuq������-=����������yP�����B�&���������D��)�������$����Q�H1��G3qk��G��UiS-7���M_$��������d/{��}�h������K�S�	�<��-A'���A��4+�^eW�2������t
��
���A��69�`c�&�&E���u6�~m�5l1��}6����g@��]���/���������x�%<���%��}.g�����I�s�j7������q
�4��M ,e	�9���	������kA{A07�
nay�dY���gp&G��Z2�6���\�uU/�E	���0����-�4���q^�;��"�t��F]��F;^��R��O96��1�5L���z���z0�j4�P��k�� ���{���N���
�����)4�L�E�k�����'KLi���KeS����&�%��
K�Bn52���'-|>/(�o=�
���j�J��!D����z��yh���o�@k���ND�����r_��_�����
�DvA_�NZZ7)R6��kgc���_��c���IJm6Z�G(�&�7#��u"����	��\r�R�g���9�
` nhHT�[��6�u�j��"d�����	Z`�j|R8E	��o�b?�"MN���~����o�hH��rX^s����Y���x�s$�i��g64��{
��M��(a�	��\���`#��_��������'\��]�*uTky�Db9�
���>D��}�"���F��sX�i4��`^O@=$������_���1���*���l�t�|+��Xd�fG1�'PNZ�����b'��ap�9��n<P0W-l������{����������W������\���Oo���T&��FJz���c�G��zv�.$ �ExI�G� �`@��-m@��,o�lB{K��z���)�"f~F���WL�Q�D�E(}](����p#����1�r�2b���p�ipz`��x��=��9K~5�;9:<���s|��g�<~�y�>�9�K��i�}��@���w��f��~���
�+�p�	#4�
��g^)�hFT��j�� ~�y��R��V���S��T�=�b�����(`�rF/�!��W���6>
��<���N��"�|�/E��aM������h�������X���5m�oK���?8��p92�`s�En��v��:����;�&��]W.)�����p!�_�1����U���������t��������!���H~�&�����w���������YR�)�P��	O�w��@������Eu�Q��T�X"*���%�CH�
���k
$��o���bQ}�v�<�����G���j&,�^���W�<	��"���'{"=8�A�-��Wz~Vzzy��t�����ke$#�2Yg�����R�#0�.��r{�6rbx����1����X���
�J
�������75��h������C��1�1���b�4�(	�J^���T�a����~�A���������<-�kY�OD�y�&�m�I+�,���������
��,S������[��M��H��,���>���x8��L�t���
�����`�<�p�,�Y6K�sU,��ng�%�:�<������������X`s�Xu��� ����0��!��
����0fT���"�z$xhN\�L�[3V�&Ss�����H�������b%��sRn3i������������PA�a��6hoq��v�rO	1C3|]��dH��_$Vv�br�
��o�h&��6eG��VK��+1�<_9M	%(#B���8 5��m�<���W\2���������?��23OK�����Z[�$r5�2n���H	��e�i$S���/kn��ZH����{10K�X�7E���*�@�\����Z�#{�epT��!UZ�r$�v�"����
:�U���F��F���-��*N�8�� ��:N�i����*�t��u,���#���e���Tt�]�������������x*���=E���bc,�c�/u1;����+����a/	��"����~)2��!-���x��F�������A��E{S
:([���!K,��Vo���z���zwC�~�>���g^�dT7,�m�k�3Ln��L���I���r�`{��8�����]$I	Ap��"s��hd5/�=y���!�	����
����~
,�>KL8��q���Bh��J�h�d�5�G��x	�j6�
'^6��;�"�On�m��E).|Vn��+b�1#�AB��RQ��	���OPN���5)A�d���s�2X@���(�fM'<u���������7o�MJ�r���~��5�I,�������`�}��N��w[Iu��-pdX�}���$����j�?�\.��(�}�mr����u�w/�s�i�*o��M8���ShwA��� J���{��g�r+a�O�r {$�-, �����X��1�T����x���R�nZ�>��Q��>Q����U��b3

XM���06�K�<�.s��}��w=��r[x����Yd<��tm
Xy��[����X\9��1��t){SNa�
q>�7�H�D��%�b�J��7j���K�Q��~v������������{9O_��u���xm����h��M�k����?N����>��9+�����9����(�h&
z{�^	N>�>�_���J�;m��~�!P��HA?!:�W^�����}GZ�$��-�`����7Z�/pk�Iq���~B���Xs|�z��W�*:�(]���v� *������Jg:��G(m.D�&@"=�I��������:D0�h�6��k����"�.���+�/�$g���Go>���Zeh����x�k����2������W�A��FEl�WV)�B~p���c������Q���Ltw�W���k�]������>���>&`�UH���p��P[w���q�LQ�
[��T���AM5�V��F�hM0|�)\!��^V��P��+�*���4�1����m�<���\`T��Z/��-B��V�/���W���?-���Q�?����7����\�&K�)�[T��0�0aM?J��\��_3��>������'+~�\�����@�Y�mo��:cl]{�+��j��W�^����'A+(og�Y��w	�G�a�)�f��u������'�����u��J^��b�\w������'�x7("_P��^F!]��-9�������nBs�,���D+�� �1D�t(6��MC����/����U�}o[yD.�cu2�zu2g���m	8^��tl�`lu<������D��tw�g�
�Y�C����'�=�f�_;������3�1r�@�50�X�s�8���	$�a�����R�(,���Gz|��_�^U�c>�>�tk��$��Gw+���Pv��M�s��~f_c�������+�_�O*�e���Ao)�G=QX*���-�gH���RXm�oe�L��t	%k���89�yq����wv��}�t�c�����h�Ut��~�Cp0Q(�-�����R�	���n�������n����J"]��Ff��1���V��'m�K����+Y��fG�Tj�3��2K��v#0������u�F,L�K|�p�v�vJ����t���K�#��H�V��	�c�%w��_����]AH���s���_���6E�G�H���}�~��]NpE���\`����i�J
�i��g5D"��S�E����h"�V_����H�U��F����^|���&�,!���w��F�g�#��_?��k�Fr�K|{r�a��1!��^����w���}�@m��� ����Y<=u^q����m3�,����������A�9x��������z�����`�� �`]5|���y�;o�������C�����Pyr��,��v�A�@U@���B���Q� ��::#/V����.��d����tl�~���Lj����9�&�^�Y�)vyuH�.�t��s:�����=���Y��]|F6�`��A�#�f�A
G�-a��{
<C~Yj����� nE���Q�)�0zAj4G�Z��GL��	����G�_A�[E������0�QM+}��4��={Em[<��%��ki��
G�#����|�}��kg�9V�l�	 ,o]V������Ei{Q}���u;�(��_+J���/x%m�Cm�b���T��W-����l\)sdG2�d��d�H%������Fiy��6C>�S���*f�P���.F���Bu�
�~Cl�b�n��e��a'j%����qNz�8��%�{Q4I���
M���ci��4L��B�i&��@n�F�T��i�+Y�y����z��h0��ri6l���U��{j/��m�|��!���M��f�J�v^9J�,�|&����?RU��&�������da���w��>�6�0���o�:>���b�9��f<I��-z�=�������;?�v&)����g��,��FL�e������	�@g��.7�7nk����++�aw4�Q�BnR[ g�O�2�f����t�@�	�����&�d��S�x���Z�;��+4�5�j�jL���=_���4�<��i/#��+�>8�O�����,S��{im��6t�

�,��M��a��@�[���w����8d
�2�5nv��h���(��z��x?5,��;��l����B���;(�:���fL�-��(>�9=�9{{�\�#l9Y�����A	�T:����t���5h�����!�����bDr�����Z��~9�Z"'�E����H��Rf*���E?
F���T���	X�n-�������	,��E3��^��u�X\Tb�I�!����9/�n>�gs7������I6�������s�p�=���E�4H*�#</(�K�8Z�hw^rU��Uz]�B�9���WZ����qR��"4�����d� �����=Zl�v�$���
��i��(l��Z�c�T����IFF�+���T����H����6K������L�PdCoh����oA��e����|�'I�M�U*'��y��<������W��Z��$���Cuv���-��p%#���z-�(�)u ��Z	l��jK"uQqP�����1�VH�F�(�����d��L��

�~b�
h����GWQ�1�������
A=*$��y�'���	�1�J��t���P
N����d1�R>���h(��zMc&����_�����}'c�����H7l&���(l�@K4��pmdP�9v.����hj�I��;�jN���DH�_�^a��]3N�N�.�:�y�)��f���g�oq5�����-f�����,�rM/������]f����-����M,����hAZI���$U�����^�ub��
R;��
��tn�7<�
WSh��v���0���H#�<����������%�h//PF\�h�>�yA�m�%��(�H��P��I��,H��o �8|��[�]Y��L�1�j�E��ZQ��v������ee��a	�����~�����-&�E�����(VM>!���0����L7�I�;�`XO�I�9jr�{���N?�O����K62b�';Hy=�|�&����_�����;^�/P�����M):�C����d|������iv���Ah# ���O]?��Zo�����3��k��DM�[�}%4_�?`1��`�t!��T�mH��#��h��\li�9��>����(gIJ euX�+a�$��lV�v�f����i�IVe���QG���7�X;1�Q%�iv>��5I�}���2��@V�e��������P0�A��|��*��6�g����%�?��6���k�@P�b&g��e�x!t�����ClE�
��Q�Se���c��
z�>.�xv�j��W�qw�Xt}b�9��	w�8����+�|��s_aK��zO��uR��'��|"���0St��S�:?����O��;���
"4��5_��"���� �Q�Jr]I�����b��B������7�IdU?g���T��1���L����Eq?_��
�[d>�b6G�5U'V	�b�`v��o�`^A�)����}�����&��L|!�VYIeIC����Q���H}+:�J�:�����3����m�	j�.�v%A���y'��D|�,����g�����"����i�U��t�^���������$��h�7���J5�P_�f��"	lIW�lz�4�8�_4��*���#��x����.
i��$�������4�"A����x@��5��,��nN;���B��jT��e7k�����i���y����ng�L�)W��)��~�4���G�<�<�$=(?����];^����,TY9�c�6�1�:��,*�c�H����oi���x�T��S|)�Y�\��l��!r`F�1�4@C�����Nn�-#��! y����s�.�L�~wL��]p!R?�F�?)�L�\CF@���H��h"��R�M��zi�^k�"�;��X;��H��K4��ls-f�����lL��=��)f��|�{G����q.���?�,;����?z��W��E�A��%��?y�&�F�f.n9�?+5�V�ttm���U{w��s����}��yyt�f��1�{�V-�%��Mk��["����z�m$������C�gB�h��A��0�
���2������:�Q���4>6h����x��4�����F�������N@�{,z��F0�����|��y=����T�I��k�
���>�@Ng\0�G:��6��au��N��\���]��f�qs���5N�]����0*0~���J���\�r��4X����,-r��
�%��
�\r�lt1���!��v�F���~��Mf��[��-����b�A'���g�0�!��fx��v��.<
���VRCk�$��,������ IF��~��xAQ�"p3�W�����������hX�jb���u��y�W&�:^I\�����|��6�r�j�ex�=�k��]#�����'���\b���*��7mHLrih%L�`���N�y������`b��U;�R3���Tl� ����Y��.���dK�aG��3�F�R�Z�m��3�i("w�]P��OP�n�u
�1"g������p�O�}�>f#B�y}M���5
"��u��"Gg�EG9|����-��l8.i��2M�/i�i�<e�L4����n	�����!��?�}�GM�'H�u��#�R��
3/:_����
$�C����$K�$QI�����l<U�Z�y>z�5&Etc�)^���$f���!��J���"�9-����
�o���VW��5��|-�o������u�m'�0��	���V)�� fJ�2��rT�s��4�#_8`�G2��L��^t�u��o'&�H-�}u�[D���l�pUzR[��^-���3�n?�YU�	bu�D���%��K���sspml\���n��� �H�5uI[��na�Hx��%��<�nH�m��J?z��7����>%����O���������d��}�Bh����o����d�Q�Q��q����~����~��R��o�5s
�G����f�!A'�HA��JhE1�s,Es�iaDiW���.��t2���SzS�q������S��.��B�-��}�}M'�\p������^�ZJ}��o��C_�)t�+um�3���}5V��@`uS�w�	��Y��#|���RC���ww�����$t��hV]4"������.�Ao����}�������<\T<���k����LA���y���+��]��M�����5��ZS^�#��M����8��|�D�I-E=�1�l��.�<�C�����t���������{���)0o�����D��1��,|AF�������jU�1�p������v����4�����&1g
��L�����$g4�R��P���<g�F���\t�n�����h��u��mL��R����Sk�s��J�G?{�U���&�����@"b��gI/8D��
�nZ� ���f�D��4�
m��r���Y��GF�PhT ��H���	�m�G�X��t����G�l>*rC(�O$�� .�e�V��j��9Jy>�l����(����<%y8�e���3#)Z����8��y>��8j�")�,/�d��V�������T3�~��x�C������YZ(�c\s��/eL�����q�^*�9����iJ�:M_��-K��GM��f)MNN�6'���|�OQ�0+l�����F����0�J��,�a>H����F��e���sp��n���z���c�����������������X���D�H�e|�
�~��#��ZS8��r����<�T�C�����f])�"w�^4�b���"���Tif
Q�:jr��:8��q=0�����'��O�/G�Jh�������57�Sb���+q��V����=����w��V�X�9��)���Y-(�A"���TmX�zN?�l�
�sA_��J)l��S$�����ZNn������ H��>�
0--�R������9�
oA�A���#�y�I����G��g-`y��wwF�r�'���`9�����"^;�r�(�b��i�8��&q���x���a���������(
�h�s�b���Q:�Wt_lf��s����9�[�t^����F(X��AO��m}���n#�4�
+����2�Q}&��n����`'�^���z�|>bN�:��j7z�����O6��n%��bf����$������iy0��21�������/��;���N���_T��
�r'<�B�r������?�����e������9�t�o~���o�_���L�[�HN��Of}����k����UZ�h����'B6R��[�����[�)����4,������K���E�c|o���-iM1s��7Yw~q���R,	��.:�zcP���2�Uo�-r>��/D��!����Km�ts��<%6J0,c3�j��q�A*\c �hlc�������BN��G/gU�qT�p/^�KO��/��=e�:=|�'5��vB�kK�;n�h�V��6�?��$�GN���F"���7��mb�����i���n����j�3���PTXs��^��N�J������h�#�e���&�R�Zhlq6A����C����pqm{D@������s���AGt�XHq�T��t�>%S(p����&� I~����+���B�����3�lK��4r����Y�#��VH���Br8��X���=��,u3�f^�l�
�8ag���:���$�������;�N����/�]H)[��u��J�g��vEo�����!�-~���2��L����`��&��n��R�S����!�&��gIO6?����wA�V6��\y0l��\L�����Q8���k|T\fP���������g��GT`t����}zfd��n�����"���8)��	�.@���{`n��0�����%N�PM�
@$�s��S\��i���E��G9c���8p��n�����&V�BR�B���W:�im'�x%eZ1��j�W��oY~6���RD��#R;�!	�_	I�B*�M���Qk��je�F�l��R�]#Y���������:g.��)�4�t����L}	��-�<mQ9�J�-�I�`=���$-��e����Y`D��S�b3Q�2�1ki;W�|��L�V3�"<�R��J���iA�a���j���:Y�K��ML?�����M-r���p�9�����Y�<0�z��/�xJ5K8�a�l���4����P0�����F�F} |���}�32v���pC�$�q_, ���YN�aSc7��V�H�}	�d�70z�3�5=$�n>���L>��t99Eu
��������g����dfa9+��yC�Y��0Ep.���ff�jj4�)����������Xj�?p�n=�
$�i�x6��6cE���tfJ������`G��E���L���x^huld_�=�����	��h<���V����<�.�]g�7�
�������dl�q��=<38Bs�$P��uj����i����D��v�_^�oj76��A|���>j��.N����}�q����#<E��K����--���?��6M��Z��~�8�|��FG����1���%���N�ss��VoO��fW���$$;���X�e6@%
7{8U�j���Y���(87��ZJ:�����[z��W�:����S��Z]y6]H���)�WJ��R"�v��;:s/��
�
��1kU�UU?���U�I:����&�E��������-�e����h��}.�x�C1���b��c�����f3��.���e%5��_��ny���AU�����]������y{p�y�>���g�������y�����"�����
���f���s>[�%(!��m�`�}n�q�������\X����G�7���,����I��^'��cv���e���=����yV�$���6����O~`u'�vss�����%���V�\�����fM�j%i/F��T��czQ2�����-��Q���2���s��
	V��8��?+��E��l�t�L��
����(�x����j�`�@RGZ2tG�l�,���+�-U68��2w�W^�p�j���F�kB��S�".�Y��Jv�)���Fc������:���h���FT�H���������K�r�f��"Y�sKZ�!8r�I
iZ�%6W��ZG��g.��T�"�'���pa�-��=��\�������2./�!�N��b����B"�)"�;�
Je��iv��uy�8I�T�!�m��-�,��d����7Rj�pt.��u�J*���Zk���h��LJ�P���%�O-���*��$�V�?z(�RV
�~1�����E^��Ht����|N��R�N91�B���p�������>�������������C���~�'��O�d�]sn���2�H�*`�bFV-�TbQd8���k2� >F���{,�U���3@��E�Aj�������b.�X�y��f�X��)pp��n#[�a=��D�;�Es�>Oe6|�1WL'3>�}	����s��1���R���#���f�Aw��
�����{�vqcCC������1c�/$�Wu[.*=�T{����������m������T���a�����E���^��6{��k����7"\
kM'���)�)�1�2i���d~*�`��t���y����_U
uR��QgIM|���/�������GgJ*a�M�����=�k&�_�5��/=��k66��c6 w��������PKV�7��Q����p����=���B��;D�o��J�y�O�����Q�)�!�l�g1#���%����\j0<�����m2'0�nKv�:�;-f������H0����0L���r��C�a�e'���wO���0���5��Z�cQ�!A_�����eM�t�e(N������W�yct�����{���< [��:�W�"sTGX��b��v%���uK�l��S	��?����Nm/�A^0+�$�i��Yc��^
X��>a4?��W+ ���y!�^����P�"M�*��L�`��]�}? ,6�P�%5��M��.�E@��K2�:?R�t�#����&8"��������9�>m(=�>����Vm�UX���������7fD��D�
��s��P����h���ua�!�AqH���Ub�e%�>�~jV8�'�Z�.=Ay�A;N,�]T�6+3.���}��@�}N�k%%�3o0pd���0z�5K#`+e���g�B��n�.���-���;��F�yPa�pD������P���C�,E6����|���7�����u��T91k�C�(���cPF�M���FV���P��������j���������|��,q�]����PXj��(2%=&|����p��+�&�OF�e��j	�/���&/��Rd$������d��tgW��"����(�Ce�FHv��J��uIw����P��k��bY(c|*R��]����~���l.g��%���^
����$+��s����0j'����k�15*�7�-�,6�Jg���I��7U$|\O��u\�F�tA�]������z(��!5N���Ox�����;�����j��j��d����MF^
}�7E����f�^pDW���09�:���>�v��oIpI���*�L�q��7����������n�Os	���]x8�z?��q�o{A����?�8�&�5Q[�{HHs�:b1��.�������#>�$E6yS#��Q�S!����4�lCg$x����d���s������,8��|�]�H�x��7�s���CU���;{����0E~�1G��m�����$ �F��D%r�#�����70Gj��-�S�-���x��fs��!R���	$/�e�W�$��i4.�R�����P��g^g�Q��h5����BE�\�~�F���L����N�{�Z0��g}����(���${7��'��E�E��)����]�Er��D@$@qV)��s���$��V�q�k��G���x�Q�%Ucsg�3=��h��Go��R�'���JX;	f�������
��&J��u��2Ng�,+\�:GH��`6���pX�"��rii�����a��*��U:�����n�����
�#���n�	��Y=��&�	��d�Qe�k�~��n����]/���\���9y�
�+��^e�F.��p�X�cx�GE�H��:��V+��_��:��l)�FBV|���+�~�������E��6a��$����(��,S5';��P�.��!X��\/b�/�S�4��s���������B�J�#�l&;�+���$�����_�P�w��RNT��Z)%�����*��y�vf���l�n[�����#-Ikr)�=pIRa�<��u������1��������t\6��2j������-�{I����Ak!���A�7b2������*���,�w�)�5&�xk����Hh�*'���m�g�T4�`=��<@��Q}LrX<�
j��0��
�wD�5�|�Jv%��D�J-��3�pP�Q�&����T����LH�|��>W<�|.4�^g3�c�%9Q��������T�r["��������`�8|����=� &��R�b�i�����D�{��a�-g�+hAb��J�9Y�� ��o�h���b��j!��["P�s�Y�B���$������\����6'���_c�]8:s.����&w�fL#������eq�����6�F��+�������@1\�	y�)���e:�J��|T��P��
�����#5�{�����*���
��+��]q�ro�����3��U����_�6fKQZ�5��O�/���}*]��
�\]�P�6�A��-��!���D�A��4��&��^3��%����E#�!�����hI?F�����=��vZ��\��!�Ac����g�aQ>�S��j(N����/GY�3�/H��<���)�/��U���CZ�����*�h�e���N:����&�&#�����0����?�O�g�����/ =��k��:%y�^�0AVj��Q�}8��)6���Q�g�f�s�6�'�-��k�]pRX�����O_��������@��N�KL�������?��8J���gq,4�<L�C�Be��5������!D�%3��fr�rC���%y������f`y���F5�~�p��Qa�lR��j6u��$eAN�Vc$"�W^epR�%���~
R�G�8��Xz��<�`�@�����1�Fh��^:�"r�k���	A�?o��������X�������bT�5�B%[�p��t����'y����Gzp�"E���.>�d����+Z���0M_��SO���?� �A�"��nX���uqM�?���.���
'�c�{��2���&�M��`SsL���?��`��s�p=�
L6sP7(�~�W2��x0�4�>�]��B��Q0�}����jR��~��8��s�?�5p�t��G��N�]f�g���V)`F��f�S���$4*��f^q��Gb�<�Lk�j������B.Q��;����bR>'l<�iZAz����b(��B�a�r��������
����N.�yhxZ�A����%���9����_�~��R����M����E�}v�d��|����2\�����o���(+����]����L��������2������`)sV�+�TwI1b�����s�N��Y�IC��N�V�i���+��64�!��
�~5�1���[_��Z��n+i��re���=O���U'�����a�+�JE�U?����>��LW���Es�~!w4�_*�T\�nIo7BK9��6j�O~�=�%�.K}�����Cw�A>���g�(Z�ur;���Y!%�T��9����}+Y[�]<���DY���?uA����[�D�[p����g����y�+36��3����I��X.R��D-h���D������`��dK�of*(r �6�5����q*�D�����/5����B��W��+% d	�
��,Xv*����nvEG
9?p�k�2^1W�Q[b����`��XB!BfZA���]1������d%�f%K���x�Aa���b>��$����*)U���kM���'�	�u�m���!(ij������P
����^S���fZ(���XV����s��f#���#��b�{.4�T3�.H�T83�H!��'���Y�"���Mw����S�����_�E�����>��)s��>�	`��X8[�	��5,�5�A�%j\�~����,�E�u')NF���E@?�_�������������z�*�0���A�����,d;KS�i���j
ar�Sk�y(�7����H�i�wSSO7C�B��Mz����o����Y����a�����Bv�Y�S����gB@�.��w��4����y��7�����>-~����+��?1�zY�?[��9��F����j�0t\��@{8,�]	4�BM�&T���e�mI�vd7E��ib>�`����2{Y�@[>tm�%��~y=^;1J�)$J ��*0Nu��X�$���`��v���dV�J���
��@�Z�R��+!�0V��z#r&P:�r>�rs��V�O�[��������*�^��vL�q�EO^��<	��]�,0v��/"��xZ��l�v�U���R�p���a39��A���nm?b���>����*��dO}*���C�B����
1��J����n�R��\h ��[�H�B��Y`��x�����3hJ��>���v���H6.rB��f��<���r�\��~�����I���Z{�����FY��|8IN�r*nV��E��sHR)a�P��$�V�QaH�e�s��
��d�)���K��,h��*q$)���������	�%��#Q���U�yk���DN4��u��1���w�G�����Q�	�%w�W�#��)$xw:������]=�����������K7����_����4��s)��/������m)������[��Wm����`���&�* c���zs�����4���S`_���'Y��l��C�VUS�?+��$zY�&�
�v������g�~�r�>'����C��xs��lk�g���#��A2����2.���]���X���hvG���Z�4v���s�����W2�}��S*��H��"J��y��GS.������~�+L���(Y���Ra��y��E���U,(�t$���}�������hd�����ml���8B��i�D�W^%��jW�D� *3:Zs}awc��R\W@��W����;����O���e�H,SEP	L�I��Y���8�80pe!�u�"9�Ri�^=�E����������?+LUFt���A�����7��3
�J��������N�/�Z���h�kW	�U�f�J��_S>�V�Y9� �{�d�>�0��?G���� �%;��RV�����L+:T���@i�&��j_�������R�����
#N�y�������{EGA�f��(���/l����'4�6�>��$1���\)�w�����cT�S���_���$:�����=F��\%���j>��/���B6�@U������H�&rA�s���^h��i�
>J��)�c-6d��C9�_��k�lD�Q6�:���}��,����f�Jne��R�T�"u�<N�r�������m]��`��,���2�~_K
�/���b�H��VtAo�����V$&|��i�tv��Kq�?W�L������5��|���Su���HU�P+�����\E�|=�D���R�5w� ����r?��>���|H$_�����"��,	���v��|�DiB�+G���z����M�_������M���(���2K�[^�v�a�e��9o�-g]���CO�%1&r�q�n�C�~%:X����G��5�A������l��\��t���
%�7����ugR�OpE�U^�y�S��
��g(�L��-2�
M��t�
�/!%�W:����O`I��+���vR�-�u������������T�w�K�iR���V6����.�R%j�~�<����u3W��H�_���4��9V28�_e�#Z0sW������GcQ�E�&k��NOB�q��Q+�����/�>��dse��2
�fc|_���{�8"N������^���Xhn���[�>���fK�s8"���7eF�W_*��x��_Z������j�����'��V]
������[?W	��������l�xB6q���H����f�:��/����M����J��
����g�@
��������<JR!���s}~K�T�����2�	+_��M�'�a�.�JNT��N��x��Dc��+����Cl8���]�QL{�~����������k)�]B�kf��2���"��'�X��^�P>f}$��7�,�<'�/����N=�Js<�m�8�C���@��]*bumt�*���&�4F}t�}������������~�t�6��w�.&����a�&T���g��(��-��D��{K���1t���6,���$9|�#����q&���o���\���������-��Q�/�<�>�����L>*��������S����3��g���S�f�	�l#����M3o��|)u�z��&����������R�X���^�}�
�*�#j��L�c���3��e����_�|&��J]V;����lV�^�
�<���G? �$�����j]�ZL�r�g��*9p�
�o�[�� �P%�Bq6X���O&���$9���i!pN+n$p����2Z!�B}]^T�,l�������"���V�������,R�$����f�yr8m���JO�0�L���%O\��/�#<2Q�`���?��X�������������UH�v4G�Q��X������C)nb&�zK���w������j>���u�a�h���s�0����CZc��DV
m�.O�,W���h�j^^Y'�� -���%W����Jh�`3�����]�R
��y��GS�U^h�U��\��*S�o�fm�3,�3#q
1M����cC6�d#��� ���#��NS��5�g�����
Brr���J�Y�H|F`�I��B�����y������m�0�����5��N(����{��eG����u^��y'�.'/U
�9F�K*���h�I�3��B�'���%_�����!���?S�6{<k^����e*����y��Fb)�F��>�~I����������L��B`���������#�o_
�����������(�������*)'����l���_�� �����G���z�%c��{����&�u�`���<����0�N(<m$�]l!)�E@�=����{E���dZ����2�����YG�
�����6`8��R6�Yw[�������G0���������H�/`l���<���$��G0���F��N���P�#s�"+���1�I?��:�>��2��:��`�yHZ\����T<��D<�K���`��p������r��fzx��Rc$���i� � 0F��P�`j�%���:��z��Oo����9Wb*+L��KFq�����18}�
h��+�d�v�]�GXj��O�Io�am���TU�Iu;������+2�9��aj��Gk�.�y4�3�ms}�0�#������i�
��K�[��������'��j:bm�,'O�e��k�
?I�#R7�F?�d�?����'TPt���0�:��y��/��7��{ ��E�7��K��v�X]C����
�)��4�_H����9A��mn����f(���/z�2|K�_���LA�:����A6��]n����)s��������d����Bt,������ByV��+@��?���2��_���2G�����lWV���Z��h��G���W�����o�<���q����ON�G��co��b�n����L�}�,O>[��B4i�;�)H���#��J��N7�"���4A[S�'�l�������z���&V�w��M���1d����n�_��o����U"�����T�*�uY4����}��}h������Q��'�������[R��v|�����`�Y�c��Z����Q�7�+i��:�9���oX�
'��������W�;g����Enp�x�a�$�����������mD�u�o�Wq�j�����T��O��j����/����IU�#Ea���-�R(X��~8���.dD{+I�g�0�uiR��(�HZv�(��(I��L������HO
�,U!��9�N7�lo�
d0#���P�*�9��N(K;�%��Gfx����e��#G	�=��
�/C]��R����^e3#��f�
P+�.:�����.F����&~�>�2���|d��~I�����|<�^L�)�_<����1�hY�#��x�������~L�U�m:�	��Q�|������T9��%H0���I1��V���J��,w���L��fBBA*�8:��}K�"6�h9�[���QdJ��C�iAHU����#���R�1��E/�,x�y
P���A�N��T�Q2#0�g���cT�I
�l��?�T���h"�� >�9��0������J�f���T�	�lQ�6kkc�)�gU�����qW��)���3��18�W*�HM��	����tZ��sf��p�rf����$��
�d�jxt:s��%c�\�����R��	23B�Li�����y�fzr��iE�`wH���,iQ�@�L�~��Z��SU(�=2�:��@p�}���i��]�{�
�Z��v��������(��52�(���>9��p���������`U��<s\��};2����x
#/.�L�3��h9��M�+���jJ����"��B��jdS�m���
f�����YN%5���-{��8h��e!+���w��U-��t�	>�)��o���$�������
�W:"���Cb-8$!1�]���������+�j/V
�BkQ�&E�����VPz�"�����v����d
,�����������I�H����Yg�d��'
}X-
����7�5�������G�-W���������xSk�a-��J�k����j/�����1|��(r��vN�����V�s�w�Oxg`�#���	�;T�T��U�]e}+��7�s��0�B,�����}����O�����R�M\�t@A��\�7Hm��� J�n_r���
��#�ZRWW�S6|��K��@��82��8����<nO�uDudz��s��j���{@�;9:<�����U�E�p��/�+������s�����E�����Q0�D��,�E�r�Fi>�3Xf�t.��Tc���,��s���R�����C�s;��I<Vf��vY��������0>�M�: !��a �2�P�F��Mt�w�#rz���Q���I�J�h�%�������"�^*�������|s�]BYcA+W���'��]N�#.l���g��
U
d #lr���q�����J��lmw��0�.�$&3��Uc�����
�S�
�uw/��?��J��� Y�!���=��-l�����	����\e
�)�m��{M7,ji3���y�X�U�a����a���B�8�wG;%��T�^h���V�$�������(��4W�������a��
�x5(���3�H���M�q)m�I�H��^��{��'S�����d����"[��������%����v��-�m�t:[�t�q=����?��;k�0���zG���<}d���ZY#^���:'{���:1�����=`M�+H7�V��9�2��KQ����C�K����Il��r���
R��;����4	�\���W��U?d�L
v-����������MV��Tt��R��ez��z&��aLah�����'�H���*]�%UyR��;=���>ITP��K+��T����,u���{�$���U�sa�~�\bF����c���`uv�EWx����gy"�#���U��s�q�B�Cd,Y%�V��(q��n������Q���-��y��lw����Zb��]�=n���q��3�T�����
xC�Y�z��q��*��V�{}�/z�~U��:9�C�=3oyAX8����z�.�kF�9��nJ�0���eH�-����
���Lf�|eSa,�'�@�3f����[��Q���(�qTQ{������@(DwS�W���&���
*GY�9C7�6>�f��-�X!��v�c6G�C�
g��|���0$4��\��=P�������gYfs����1��s-�����a���jS{o2<�2���#^m���sX(���b���m�RR����C���Z��[�a�����!!�Ktm%=)27��c��Qy��1+�1
�����W���:[.���ca�����Q��e�0��F�o�s�m'!~Z-��X95��� �{�<.�wQ�IT���lZ:!���z�,9����.Ski���m��#�������jS���X�������D�w�� ga���0F�[���<�-YKr3VZ�j��!Xc��� �tU���C=;U�s�M"���Q_&�y��(?+��x���.J��Ii.���?�;:~��>��U�y��?l���{i�UF��D�@%R��j�y�
���,�\
���w�1'��>&������3�V�G��aF/N�����8lr������rG8��t6�q�����L~=i�s�Y7����#<�S��>�ae4P�]"x�f��p.	���`�K#g����|���6�{��;bUw����|&����f�����>!#�,P��O��n��Ro�V�������S#���!�n
����%��Hl7�(��@��
����K���K#F!��K{�2���k��G�%����c������pt��*��d6��m���e��3lF�|�H��N�o�$��j�?�
����<���O	�6����"�L��\�f/��<m�]����%���7���[�.���K��/�m������8�L����N����M{���k�y����w7�6)�Y1N��'����Q�z�D���/Y��_<mP
GL8������i�}z���!w���EX��)d���.I���b>H�����?V�F]�w���	�F�L�6r�XOFC;�R	�<���{	7��$�#l��7\��0������\�������Ch��M$���&�JS����1V��A��JQ���#�����{�(j>A?�����m��b���c����v�3�������\������h����vK�bM�8�r
*@u�u���pC�q��^�,�]"[[��[9$A�{q+�
v�E��+k^X�����)>�b�9��dc���[���q����V>�m!��*�n���*O�#
�S����������������>M���}��7��}m����+~�_�5�x��w_��&����s
a�;x�
�`���	���}#aCF�"E�SE�)q�0�1r�9UG�C4'}pDIe�]�8�pj�����;�g����nH�_O8�A����wv��}���3��o�I�Ga�>���F�����h�TZ2+&c���A?����l��"!�����9b�}{��!��B*'5'�Buk�`����L�Q;�5�����B�?lj�wu,��]�G'i�:B�w�m��Z_q��`��o0^
,��w(_�O�� j�^��x�C}���5��$����9'�xQ����K1c��9�a��ePCg�G������#����xH��Cx������?<z�z�5v(K��<����<K����L�s�-�t���]p��i�����m�����Z$U<!�2���py���-VH�yln��-��1jUr�d���a�������;Y������U���K�l'����{e���
����"i�+Ws[��{,�Y����?Ym��������
�T�n�	1fH�d}C���2�v��;�$�F�wf]6����n��Rs~n��!���Rt0����}�������n��SJ-Y�p8���M�Z��>��aO3���5s���[O���}��*������z"���Qj�;<����6�	E�q��sbl�Z�3TA�]-����:O����<-�aj�o%�K�����qsh������sEg
%�)�{�$��0���c�� &�lL�!pF�����G�R)d���S*��h���B$�3�e=���x��n6�I�y���IfZ ���������Yb���HM'��aRS����8�X���+1+]y��+��g�,<�/3�,(�>�
Iafnp�63�6I��;��E�A�fg������r��j��������!?�^��>��5�o�C�UKX�'�.�7���N�)$�Dtl��D�@�����/�{R�*y��108�Qw�Q�� ������c������_�uyq������N"�2���%,H��(��y���_���H0W���K>���`nw0�~��E��Q���x)��f��y�*I6����P��Q��f��9#T%F?����/�M�����6�cTsr���8S ���b����w���;'�{���8\+��l�����$���������}
I_h��O����6�~]�P������|]:�?�t�?�m��e���3S�tk�����v"m��~���I�����\���w�/{���p�����.���,�- AeRek��i�����1��D��k�L��=�7�J���������[����A|:�p�l��B ��)��������6X'$I�_@*�Q(4����ES���S���U�n��Z��l0�C>��Y�������*e��J��9��Cpr��?�Cm���s��l>���|��b�	'��G�������{(���iYH�Qnkh���$@�r:E�*D�%�	d�����
�?�8wbgA��tb��H�>Jj��2���{k����T���T�:���:���O�!V��;� `�|���%�T�B/1@��G�L4�w%y0��"��L'�I�E_�wJ�)e�d�|��1h�,������f���*
w����i2��XUX�l
��K`AxU��0�*��Vh�-���,P�'5a=��|
�&�8{� �6��{�a2�`n�L&���B$fkSK}y��Y�&y��������Uc#�JVD����������w�=�C���=�������������U�4����!y�����`|q�O�H	U�������I�,�R��\��'&#���	mS�>���l���$�-x��%{"jk�s�(O�43����vZa�*��8�n�@��7v&���d��RJ��"���c��p�D:��O����Uu��z�=[�������N�pc�@E�B����
*�F�����a���0��������G���;���<��o2���L�����A�&�}��;�677c}4��m;��"���F�d���,baI=/02����A4��"�NyB��7�<��<{������]�@=��Q�����}���}���1N��M������#d�w���_f���B9�������%���4�Oq	��L�U����2@2D��3h�5�i��o��7�@�/0���>W������k��.��<���0Kz3�6��='g9M���hZ�������@bTi���T3����k!����D:1,p]B����C0�$T���Z���Sg{��^����V(��ya}~{5�6�@,�p�������z�����w�G�}�_���f��� ��{2G��bE���(�����f���������a�����������k��@�3=,?���"�@q]pOc7�/��0�|�-H���B������F��557�t7�y"�Cr����+����LB	�Fxgl�O��	�����dT@,�^���v&s�+�'�gA�Q��u�N�P795�������x�X����,������?��U���R�9�%mj6RH/�a
16��7Hr����t����0?�&$.6l�:�-��T ��%
U��������y��7D�[�$����`����h3�^?�V�1�]@�e������u�*Iy]�7n���?w�O����Ru����h���O����;���w���0�7�=I����u�G��X
u"o�#8��BT�K���S;/Bg��(QLO0���j��c[�������if0�u��0.6����]�mF��`Lo�������=�%��-@�����k�������[��?Z`0�-��hE��N�������������Z�
C�R��.5�U�����7*Sy���u�`���gM��T��L��u(������t�g����%�.��k����^i��(���rP'�7���Tt�R<D��A&4wO�>��=}�C������
�:��.@q;��4���;����m<��;�q?��w����V��mrNsd�����@�1J�)V�T��2.�vi��,�z�m�:�^\.��hK�C��=z�����*�K$�Z(@��H2g�c+]��nc�6��5j��4��-y3���������A~�bL����B�4�3� )J�*���u�pWZ��`b��
��P�>%�[X
��� ^2J��rg����i
-`� ���F�F�L���I!6aXQ�z�,����@�3:,):���a�������^0�G��#	���-�6=��;��&fk���[��BwMj�sW7��A��pn��E?��Ci�����E��v�Mq�ScM<*�F��"�&������S� S��`�����������g~�t
��	@����������~����f(��z��p���\�����Ke�(,Ru1�$4_�.+Dz�=���S
�����"Q9��g��S{L{�n��!9�$"!��n�0�La�NM��8�IFI��l�R��^����>Y���eSXf9i4��D��S6m$��,��i�f37�?����_�v���������5���F�����|���8���P�0��S�V��q�Lz{t���
���I���,�������b�.��v_�O��c(�G�VVb)�)�%O1�d)[Yb1A�����%�#b-I����}��������<z��ZRj��VRz���SP��_�����\{���.��y�8��������m�9����N�Wnf#�>�Wn��g�M1j�1gm��%Elv_d���e��:e$^3�����3�?�5���V�<�Kn1)�m��YU�1�R�Y�<�����[��`���{X�h��P�M�?�=�!;�
�*y����'��[eW��k����Y�������[����^��J;B�X��!�
�����P�rZ�N���N}nF7�����Kt���<3a��s��^�_f/����G����I�1QV��������wA��WwF��o���/���b�V�����7j�����l�����]��Vbh��L�=O=����%	,8�%muf�Q_���H�7��s�$�_��,Y�vG�Y_*_�\�z �E�8m��8R�O�������C��9��42Gag��,��f�Z	'������Rs'�]{��������+�sD/��d��f�^�0�����7���������|G~h�1���3��K��e�F���S�o��/O�t�0��&O���Ybx�}3��!Ja
�-n_�aO����(�gi1"Wdl5KA��A�q��P�1e]�S��G���#E��0�����r
0[)�!u�G���-��=2.�R�l�u�k/�������G�@����
����W��K�h=���;��7G?��u��_�^�l*�
?���%�)�C>8!7��������J�41�f��&C��K��	B��D�BB���? 8��r�l���=$����?�KH:�_A�4���:�|��M�6�-���F��Id��5�4�)&-J��R�c����?�F��1R����(f%��5�8A�.�d�������C�������q�Rf)�U���u������j�����^6�<��9]��a�T�:I���{�E��g�PDDUE�i�
s�6�Roz��tdW���8���T�\E�����p��"���h�=�#F�lx��#%s]�.��Q�[ bf\����G�����!�-rn��r��R�$8M�W����G#����c��h��@��Z�n��2��<"^%
�Y�����Z�_�a��Z�n�c�k"-�eR��H��SF7���Wi��d���_r���gj~�����1�ZGsp�(u��C��O��/�vk ��{���2����{,���ye�%2�;�0�\�����=O�����P4��������g�?���7��$�4$x��2MZ)l��n=�bR�E�A�
���?�E���L`7m
�Y��S��:�	v�{B��n�h1p�:���\T�`+D���U����"~�]Z���*�50B��|�yC.6�����M�`!z�%���P�b3n(���r�(x;J>�0��7O��Z�5��b�[�k	���I"�iF��]�
�O����-Z��L�_�b%���'%e���� �����w1N8��'���A�Q�?on$lU�@�$����������������9h��p��J����,�)y���k���x��v�v�lV��W���p]���d�C4���9[~�x�C���R���<�?��=����G'	%�l�=��9�G�
E}����%+��i���������pd�����>�S���'1,�O����@'M�R��W��,��;��d�o{�(B���T=������e�/���"�����E��'��*�q��������!�����_o�V;�C��9�o���7o�gg�{��8�*Gvx\{���������W���v�;*�8*���v2&��5�G�z�5-kB7:��+"�y�<�N�E���e:�F���V����RGj���y��c8��[~:���u6N���C��L��LL�k�$*��ai�]��'d� [������l�=��c�%�-qbK���!-f,!UT��p�
���9�����Q9!j ���e��y��MC�p!f�X�����s�mP���J`Px�#���B-'��Q����/|��]�U$���g$��SW�~���z�{\|+>mK���W������#3���$"mES���s��`z!������ �%��Q�e/��,ne���6����P�y�k%ro��f�r:V���;T�Xh](6�3%t��(�3�Ek�,<�S�5T��
E:��l���1�-��8��\�
�&��e�w�-���l9�����W !�=FH��B`�E�9���0����F8��#�3�qD@U�l#�6%g2�ln��=��r��gq��m��.IA����%>�v��������P��U
��������$�,�#�F\A@F&A����5q�u���i0M<x]^�_B�IQ:K�B�=���>|XZ�����l�V�Co�w������f�K���s������v���u���D������j���Kq��|:	��A�)#�z� �0�����Z�x<2����B�!��i��U/��:Zy.���|�����_
����Z�i;��H���=��(%���[����X�i;
p��4��A�
�����]K�����
����s|/~��ys3����k�z��(����w��R�����w?diws��=M=���G���["w���!G��6�T�b�5�\��Wg�'k@!����pa����	21?6���l8�kf'����~�UP���Q�]O8��:��%!98��a���/e="������D?~��w_��:�q3��1L�74���`#�8F[#)���{99ai�����2���L��G��������?'f�86gcm���x�]F�z���#�;���d�y�yy�������������{����}����6�����;���8~������7=Y��[3���G��_?����9o�k�_B��yY /�O�E���N��]���&� �����Ws�Y��"i��%��1+5��:B���m����c���T�
��1jL�W,��}b'�z�Ko�u����|�$�	n�����������6����������$����l�]����y:e���?����L/*����h>��(�u8Gb�FC���X�Y���t�J:��&��t�\�����.^��n9(�Z	
q6G�`�������q|�(�FK���C���(5z]��kY2�pe��a������,IV�7������{�uR����������b�*oR��G�S�s��`�~�|����	��XOn��'7���J��;�=uew�C��!�I�5)�&���-G18J��"�AS�R������������Ts������#se���g��P�H�>Fg�7@~}����V�&���xy����B*��Z����5w�D��,{�O1�Z�}��QZ$�e��7�E��	?p
{=��>��P������L�S\��a��-K�+�y4���I��D��B�s�]��A���5��x2nn��w	hSL�J��J�
���R���������I>y���Q�Y)���89����?�Dw7w�0�3M�������H�0�}�)g�D)nP�u2<1�;[2�.���g]Y:��E����r'��~T�r��p7��W�
Bz�� C3���������������!0�^=�U��-2�9�L��-3Q���R(�4��l��ZG��G���I����d�DNa��������M�>���)���(Q�
�MS������=�-�!�R�����pbe�r��/�D��#[4������a�PO|�"���������k��
�����,d$��b��@`L�EA�I��TWKjA?��-��I������ok!��J�XR�����N������l�jv���n=\��Z��f��n�'h+|2{2aU�d���ws�Yi����e�����n(��o���ak8�j����~��v���L:	�Z D��� �
�n�A�� a'�:Xeo�����,�cT(�n@/)�1RT�,_S� �rI�Fv�$�:Q�������4f��\���Q
�
�y��aW��v��%x��������O���:*wW�����������%�wrBY��^p���RXT�����a#:h����u�Uy	�eUL�����>�,�l`���n������^&��28�I�m�q�`��2�j������
�b�����a3�b�CLB�P���P����\�v;A��AddW=��?#�#�
��!��[�V�qT��� ��������N&��K�7�y:xx�'��Pj9C�.D��%��?_�����q�U'��V�������8���I5����C��h:����~#�0Ms$�Tc����������Q���C�&����1LS�x�0��a�12�0<+�Ky�VY�S��f����F��b�f�W��k�t����5�Cr�A-N2*}�S{��):q`�3����!�{���q��3d��/�
;$��)ASU�
���h5��[�t�Db	�O�>�������$�^�������9�_i�(�[Gq�8����7\wV��������vP2l���k�����D�,�fY��*t��x�����1�
�9}2��S$;����#�PI� �'4�0Z�V�6�4n��j��'h`�0���G>��7���V�C%��G2�Hf�z
�un9)6N��Ssn�X���d?��H�h��{\q��%�TPO��	p"����Z��E����E�/��
�[�{���]���p[���?�����&u�|�������
��G�S��S�~G�����N���f*�mA��v{�f�,�r��EQ�`
�NQ�~�������A���>�,�x�$�h:{�'m�j��M�H6�����h������E�Q3���)��c@?��#�5g���3 ^y:�L�����$����R+�z���j��D���^���.?���$�����Z�Yi��Z���p�}�k06N}����]�[�����fi��c��B�r��E�����	�����w/8�{�]��g�����m-Q��[������[��l��x�����*;����v�����*�=`
,�$���%f��@�_|_�F($A�?DHQ����6����N���d ����U��^*KoV_��J8�P�`��j�L,j`�
9���H���&�@zq[ha=�fc���N��	v`�Z��s��O#���M����&� ��J�3�3'G�I�&;ENh���O��
�b�����v`]�X[!�d��v;Y�%s/Y��`Y�z/ZG(������VY`�?h��,�F������II��_+�7D��,Vc�jJ�I��|H��`{F��+/�����N�����4����K����KB�}|��=�n����O������.��g*�����l�����	$v�P.Dh��m�h4�M����UN��[��A����[��`�L������@��!�����"��[��L�Q�9���r��y�f>$4�.�9W��Q���7bZFI����`��5N���Q���=Y�"r�1�����j���y�/:�}����0�%�:�a���l��s��Ps
�����"��O������2[������5�q����b��G<9Q�FA8�N������!����%��D��Q�
��	W$����Q�-��������'�/+\����"�l�w�><���f@=_�i��`�%i�J8�|#�5���G�)�#���h�Hf�$����sW"���tt���4W��:�x����-���q8�K�I����Z�fc=�����3G���g�����(et���U,�Q4�������y�������[s�^�.Z��.b1N�����$��vD�����:}���'�\����9�[.
0E&�!��)#������
\��rN�lWrM;����/���)6u.}���
�>vi��#�������yc��?hd��JM
6@��m1��E(�:�x~o�ul8.s��R�)�c���/b��3!~�X�g���;�	��U�m�����q���d�|�>+H&�&,�`���wx��������/��E�h���ogb/�z� ��F���}����h�{�����f�{��;������s��#3��t���MK�����������$j�X��Y�L>�a����X!��p�L~��l�=p|<�gC0{s���6-g��mY�����e%q�[�z\���2�O�A��M���M�=	�R���M�3,���D�rJ���+��|m���������
�K�I"��S
b�y��bQ��\��������`-���� >�R��(�vJ�jT��i\���0x�&�T�XA��lV��M�_���_��=|�pqoR���8���xqhE+����'��.�Q�
V��&�'I�B����4#B��^"��,z�r��Id������	�e����3\���K�����>���(�t�	h@��~�@Y���os�NP�&#�_T� �#
_>)���@1��M��}������s��)���+�6��(��Q�=�AK�Q(9�?��i ��}�V[��������"���^�����	�������E�Bt��s"��xG�lkU�P���.����'��*��#�]PI��*x�l��ef�Wx��)����i�H�;$�Qh���H���t����J��!��M�j��J�Bqs�	x�Y[|P����|C�	��j�1K��L���
���i������A��q�Yu<�����d����RI����b��B^W���X�U������-vB�
c `�P}��j����7�$�$���X����/�?h��A��{HS���~2�$yq����a��;o�rp��:��(����u��G���*�g�;�'F�1�$���%���%���'
HF��_R�96��L��Q7�Z��=��ip������7p��[��D�����,��0s����p<�v�ra������3�d�!�$��gC���P@I�q�z���+3�y�d�����!j4`/���5�X�?������n�?}��O/�28���f�t82���u��������3����n_�,At���p�~e=s�������v�����G�<U�����IE��e�O�����{�B9�]��Ig=DtdaP�������/,(M0x��;� @X���v2b.��S�JT>
�l"�)��B���B��@\��@� v�@f�m$	`�o�
�5���C�Kg�ix(�k����i��G�[������}���	�l����+X��J��&3s�<���(a��r+�e��2�I� 9��R�Xal��e��V���e"K�uf��wA�;o�Y�-�K�4��{�8���)���G�&����r[I)
y#��9N�g�}c� 5�����K����.���{�g�R����k��]B�f�_s��sG���7XPE�u��W�1��d����ox�Ty<C���+N�!�/�o�	���'�_>�@@>�['.�M�Q�L���,B$m�9L�4fHk\�	����&X�B���4��nG��nw���i"�Z�$�\��P��W4�y��t9���!�
�
��x�W^���nD`�6�w��\\�*�h�6k���qp���'@���hJ1��Oq<�i
���M�@?�e�8��R��(�� E����@�z�KeZ5��H�aL4���BCg�NZ�+���V4jRP���YiP"�6�+�t��h�
��m�WXV���>�k�o��#�^����P3�����J(���I:�}J��x_�ya����v�^T�De�����Nw��j8]P��DM��L��M�*7$Ieh~FoT��x�$,�F ����Qb�Y��5�:��{�9V:hh�wW���8�#`R������;�4F�J�Xh,�U[6:.��;Lx0��fW�/s��%�����<����������������E����R��n\��q|r���������4�A������c���DpZEh+��>X%�N���2E���;Y�`~��>EG.S=-�;)�=��zC'K���"���%�BI���Me
������o����.�Uqy������x.�_C�����]
�`��T+#�.�c��,R��8"�O(82��,E�
4�8�v):���4��:Q>�bs���x�����-�PA�\����/�#�e���UA�@{����0������6RH���f�i��;��?h��a�(=&I�cf���8a�������,���W�:9=F��1�����=�E,t3�"P��}
�q��ua�������P�*dF����{�TQ���A�y�d�V������'xg �%0jf�=D�yI�����11�P����������2h��m0�����8���[�]�\t��,���04�b	�#���+i�R�b=�(T�0	�.��U:��	���;a���ai��-�L8n������e�!5�]�ebw��|��B���:�z@�n{/�RU�����Mf���2J�����x&��
��G���2U�3�\
�%�6���Z��R�r�<@��~�����(�B�lV�w��&O=(fI�@�VX"���������Y��S2.�w�0�DKi��R�A+�k��FYg�w\szu��7@����n<������3<�T(rtz+k�p���
���VE[�:5�Z���Eu���N����r�Y���dM54��2�Z�A�����*m������s����1����B
�����d���+.l�2%����K�0X�4����P��1��.}aik�B���L�{���x����'����+��"*V����3����q��m�.����T+Y������~��e�Y�ww� �2�Fr��x��"z�t�19��k���F~O���i������4������y�����t���0����w�����v?�@��,xP��f��T���S��2J�%�Q��1TDm����R���]X�
e��ai8Z'q�E��Z%�����<�)#N��_����i�q�T#��5��@^*����+J���b(����k��$`���d�F���?�
�����~v?�9�������C��Pd8Tg���T�:�4�����rK)�n4��#;BM6tG6^���1����e����
�r_'�w���n���c��8�$8��=�������
�������H�DTG�����o�'8)��5n��h�F�M�Z�{E���m!1J.D�0^����
8��C�]�z]t�6 $c,o�3Bv�xe�;(����<Ta9���r�v=y����auE�o�����xp����c3J:Z�3����t):��`Ts��qeT@�����&�N��%���b�kZ��vh�w?'Sof?Y�������,��=Q�>rN�	k���wd���Efp�F����M�G���p�D���E�5�J���z(�_�G1���"6-�E����\��Tlh%��
v�gi��8dJ�;�D�/���Nb�T]I
�)�������a�?��k���Q}x�,G�.�P$��i0G����ql6r����	`/b�'�!P���-��YZhMfi�� �
�
��4���xM���J��O�!��$�fT����@F} '�������Bz�('+QTD9Yr|�_9J��A�t���m���"�Y:�����K��H��q�8��j�x�Z���,�|	��``t+'�N���D�[�
�y��b/��e��)n`h(� 
��9;z%��4�?E���yy!T��R���sv�������~>%X�9�(�_��y<��*���y:���������GA���������$�\�0�wS�Z���l`�G��Zmx��x��P�U�
�^���x�W�������5�X������"���=�F��XH��A@Mp��7p!dzpH01/�`>�=�X��bP����'�
\x����K�O����w<8��Z��V��(�H;wq��BcfP�{�N`F�>~���m�UZq|`t�y���� U�5�r������f��6y��R�w1�/6Pa:Y���,(y�w��[����1���j�����h�L��es�S������'�����Q�2��68��	n�M������O��6�dI��y����(��<�����I1vsy����~���~'�4����V;hqs�lnd�����1��������w.����n:w�=[u��?Y=�_#�
����<���x)*���������.&
�0�r�)\�!�-mU����N�(���R��xRD"Y�o��Ym2������ 
lr�����i h����~��#�zYLx��\7��A��`�|v��m����?�Cg2Nf�8G-8Y�����{������8���Y^����� ��]o���9�?��:6�d������?�%�/e0��k��Qv�:��!7c<��_)n���1'\���dcQH1�z��P,f��C��	zA4r����`s�K�t�)4fa�w'����'~ ?o\w�[�'���u���P����Y�VSA���q�[�JB��1����������y:���~�^�U�����%�b�_��wY���{�����S�C�~~(%�f�����#\���{%�52�_�D����0��������XX��y&�������Eu��G�F\��8�1(s����t�����yv
J��w>���4�tS$��s��tS�>D�PF��(�e������� W�������{	�����q~m7��Wmb��(4Z}�u@2��i����E0}����(v���l����'�\�E�����fO���H��wN������9��16o������"��M�dY6��F�c0KX#�=�]g�9��O��y��������jmY�!����ZJ��x_�����b��cJ@G�����$�x�\��(>9{��B�<���,���0����e���6��f��;���79e��?h`@����Q��������"|�^l�_��Q|�<f���E�L+�����,w��N�����EO|v.���
�:���~��0��$F�����i���"M����s�7��n�@d���p���lF���W?n�a;�[u�������S�Z����'���{��q�M�k:�\��l������z��vP���0�����l��d
0004-wal_decoding-Only-peg-the-xmin-horizon-for-catalog-t.patch.gzapplication/x-patch-gzipDownload
0005-wal_decoding-Allow-walsenders-to-connect-to-a-specif.patch.gzapplication/x-patch-gzipDownload
0006-wal_decoding-logical-changeset-extraction-walsender-.patch.gzapplication/x-patch-gzipDownload
�l��R0006-wal_decoding-logical-changeset-extraction-walsender-.patch�[kW����l~E%�;`���icO0����Y���T����Z����>����e[&$w�|��^�KU����9%�'�X������[�9�������{��-7�Cy��qo�p[J)>D���Xl��V���[����9����Kd*���������:��8�`��'+gN&��'�YbG�I�7����������h�6[��~~�O�fG��O�w���������	lO�����G"�n}�	�;r�[��L�/Y����Cbj*CO&+�3�W�������4q7n��7 BK�o�6q��a�}b�j6YWl��������%��9��
rOV��������Gt�-�jQEA����f�$������f���m��1��EI
��=��XR���i���2�'��++�?���[?��Sdv��Y+t�/�pg��������������������
����U��[�-��_���'���
;v�T�0�<��W��,Q���_\
V
@���Ojn4��W�fFoP����H3'����M$tY�� ���D���O���;��������=�������jD���y(#%���C�Q�`��������y��w���4\�
� ��2�Z1���j�mUzK�����In�s�YrR�C�0��@&��:��Dsss��'��6q�"j����x��(��Gt��,�WhL�[�7��R{�������=���em*f��+�j5w����@���x#^l�'/^�c]�WC`�~�M1���x-�����c�:�����{u�^&����[<���7x�{{�J���{���f9������Z��M��c������M��;w��/[�(�_;�Cd�����w/��af�����Ds��]3^!��)I����z���~L��!iz��gm"�mmmZ����<23���.x����t?t.����}u��b�����|�
�������0.K�]j�GZ��d����i_zb6,(n��c�1���bK��F�z�&�g�d�N�w���h�V�I���A���c���~�y^�4Q��qz[���Y�Wx�x�?��������[F�}b�d\�1���?f�O4D�J!
�#?3����G�T�s��l4����N��u,����!��Z���u�������G���w8Xm�mY-1�Y���Q�H$��U/?����:Qs�9k��j�/���jV�V���UL|�m5g�mN��wd�d�7��Y�Q<��W��Xm�N�`7M���|���v�
�{���n���>��,Y�Bsm��������_�h�{I'�A����9R��N���\X�M'=���)�[��E������X��g	�2����5��x�����ar�:aH����a�r����fi�?�i��n�����������t����'vv-$:�����|;�+�t�x���y���	STx��������e������'�',./;&���	���03��n��4������(u�����%{c?�#F�7e!�_sO��%����K�I\��G&�$���<t�G�����~�=r�t����@�x�1*����aRZ���
�#����pT�"�W��@J�C�E���sT��n��P�a����)=�[Mbxu�H� E6BR����'��V����k;��(�O�d�x8���N��D��-�O�`A�LR1��C�$&$��+p���� �b���>�<?�D�v�h��v&n���w���x����i�\{;�l�$�S���em�@�����^I�?IS|��r�C��{YZ^�BY���G�#���ldM��v�/&�?c5�{�%���l��0�FtU���2��)m�`��z�����:�ryza�����U�i��'/�p��=q�d�:����2-�����_��
c��g�������_k�p�3��F1m	�������h�S���h.�
�v�p��� �(�Hg	�����}y��i���������5��G�����%3I[�#lS�x
�%�{+3��w39�t�F+��=�>�4*OQY)/�����'q�D�<������C��GU�R��<OK���g6��Sn����?�[Y)���D�����K�Q&~�>�L���p��MK#��Ke���#�)�<�6�kDH'��?��eqa�*Z���0�������T�Q��W�#oE��wo�(8^�9�x}�g��m!�)�0S�cE���"!��2��D�B��Jy\�W���<Kio{g�����=�]�r>��T�Jl�_���� �d�W|�5T;(��s�`G�t��8������6�O,����@Z�P�zgo��������K�~�?�,*RJ�:���@����* �?v��u��AY������\����S���O��d�����������x��"_����
��j�����������^���N��_����C��A�����=UaQ&rl��!�j����������������PSC���B����u36�����I���E8A���Y0!�Hs]�0����N6r�uqE�������e�"�gr9>�3��Qo|��H���_����������1��@��t��l��JT�%9��5�8(�(
��i��Kh���k	 m0�{{\N��Y��?�2�0�3
�W���x����A�s��{��9��[	���W�J|(;��&�a�|��B�D?��Vf��}M!�`��"�������E&� ��	������ut��k\t�^��%C$1�����8�r��f�A�:C8~v%�P�9�h�36�B����0�6�K�&��;��;~�����H��'�������E�}����gN�a�O��������e�	
+�z�M(p�����������$D�����3�]$�y8/��V�lmV��\���?t��x`��Rr8D������/�x�i�,T;g$%�h
h>�2�����������T<h�[���7�z����(05U��t���Fv�.T��5�T�h��<���'���Ckg�\�g0-���(�<}��m��Rx(���`��S�8��q�������I�n�$'?R[�q
���Y�M��x��*��UW����(��l�?��_l)�������������S����[�57���}��j�Z�%�Emk����U��y��0��kq�����U:��F�>�B��<����Zm���Z������2y�i`�C+pT|�@`[��S�@zN����o���������1m�0�������p5!
��t>�Y9N8����=O��^4C�9��������mMO�J%c�#���=x���T���,�M�%Zk�s�_0�*���c~��aL!|�H}h /���s�o�D�^p��jTPn�'c�������T�#���.a����u�����*YV�����L��~���z�N	n�\��XY���:�r^�������:
l�X+�.�.���j����sr�4WI)1O��5aO�y��1��!~�16���f�4�W���4��?���Q���C
y�Na��W�BOt/�I7D	� ��E]cJ�I���%%p?Nu,V��}��z�m�~��	�$�=��x��L�<Q<7w����
B+�i�L�)cY�tz��<��Gy���)#D������oQ6��4F�FQ����G�	��lXq@�7a�\�Zb��*V��7��<i����n�[��b=������Qu�W�2��Qg�^�o~/����c!���{t$���q�V�N�X�C~B�K�������a�
<a��1U���';�������%=��)�yS}�W���}�l)(���������G�_uCL�yV����r$\��.<���d��qq)'��3�b�"���yFH���������E�F���s}}*B��Q��������qI��kM�0�� ���Hj�(��2O�h)�-�x,�v'�<A@�X+�=�k%
�R����$!hLaP��b�R�xM!�_5�0QC�c?�@Me��+5q�d��^����~XJu��+��e��z��'������moKN������
���W��*��>�i��P��G���C���?����Hh��A94���G��l_]���VQo�F%~��dc]���C����g��[��[��H�XY%��#�	�	��T,E.r�����\��C�Y�>�P����[���t_H�?|��XU�H1�p�{w����B[����V�/��\�D�B�R�)���a���S��{Ao����
��h�*![M<4�����J�M�BL���)>��H�{��J`��p7�� ���o��N����Tm�<������$�w�:�`Eu�i�������
�\2��Z�k#x�v�2�0�LV���N�16ls�2V���I�����x��>`-P�����#�P�	�Y�������n.���	[��F��l����n�Bm� ���N���oeB(&3��
,n3�
=�{��,��S7�18��A��%U�k����,Z+/Q��	�2{��;K��)�,
���%"�nv�n��-l�{����+'{�w��[��qTk�,e�G�U�9WY1�f���J���0��i}�[��jW7'��A��:$�c��	� ������#j��.��j0���7js�����.UwqZl=�?e������IP�~|\�Z�nJ��BE)C���R�l�o�
�V��q�fK���'����V��D�8~@��#!�fc��1�5y���W����&��������l��NN�zRsF(��2Qw��n]-�0]���9����{�N�@�����w7���=�upJ}X���;���"�LJ�L�jL{7U/q7Fm��9�e��m�,WS��ZM��Z�]���>�����A���x=��K�p����C2��C��U��0/������f��L$�u6|@v�p2wTeP1��J�~���d����n�GwHu�����'��������x�V*8�S X/��R���O[�e��+j�!H����,_��Rm��G�#`I��Sc����H#?�
�E1l�+�U58���@@p��<�Z����gR���O����}A]	��������?�p��%�g���;������U�}g`�u���.:j��uN����������Nw<���(&IgW�K}��LW��2�����X0+KL*�������1��h�"l)�KU��7��f����yC(��������z�0�M��cnPN�������r�K�f[�vr�������GJ��3����q�L�)������r��\��"|������|��u����b6�th0�����^I���=������C�`�p�\ V��|+����t�^MP=�����S!(�7�$��Vp��`�^�j,_����
c�1����������R+���$��_����yI+vI$���| V8T�����t"��-��:-��S�w�����5T<�
�
�U���2PB8�B�nmYoK��{�\�����%{r�;�,O�
{[���
�3W��k]���5���UU	�L�U�j��	r
�#�u�����t��Q� �K��x��+���h��s�K���I:�aS����=i��)�B��?�z&�GV:���0Sy���g���7�0�]���*����z9����8����m�<<�������BTOjE�a���ln��i�����u�w~7
��S���a4��oi$TD�aaH�U����wP����~/�fDtH%��[-�)��f��O����%.���V~J�y^Z�v�g~xZ���9Vp�!������m�r?�����-��F����)�����SnP{bEU�������_uW���E���`S�K$1Z�HiS ���@������B�h1���F������d�}��mH��v�s�����*=���9�QD��'����Z"?�y�\��Q�$��e>�s�
��L/t�4 ����j���M��y�=��S���r#�������.K�����N�
f�I��Y���*��OI���C�a~�g�>2��=����������p��xE�=
�;A��X�2
�/;����;E^e8��)2^�!b����

�3�cs��6�!�2�9�ACd��q��o��Dj�[�YQ?
��$�� �.�NN���k��g
��B?�~X?������.��9�}�����"������o����W�%���3.@�g���`q����o�����U�g(�u	9[��������&�
��e�zX7�z�+������3$���VF��9���r�~�dy��y��ha\��l��W^�~�K���b$oG�bIEF�| '#C�r��P(��~!q����4|RO�kz`�0�T�m���84��a�U����*����`J������[<s+G��������)K�f���12�	`����?���=,���0&�1�?=���"��
�:5.4SB�

�^���[��:�������O����y;d�#�%8��lMw�N����&8F,�9��N�q�|���.��	�u��+�2��V\D��4����j�������!aJ�[�9�OOV�)��w3�-lA�������2�����vh�<�Z+�
c��Eh������}U^Z��[��k��ClO1�e��`�(v�m�gq<Y��&+�6���6#p�{GR�xmx$,k*�$bO�L�����W��s�;
[���.V-����>%lR(=���YtV���u��vV�B�R �:�;;�{k���,D�?#����K�;p �rm���f
�s���,��������J�!g��
���"����Y��N��mG��F������#`������.U;��N
I��iI��	=��YGA��Cg�MNC�9�y���R3�2k�����PnR����	#0�d���H[�g>� ��a��7/�h��*fEzd�GYa�}���V��	�;�d%NIp����[�I�m�����1~W|�8W'�p��M��9n�"'�2�A�B����-�b�\5�u�;��WO?����?O=`v��\��k��f�4��jS7�n\�[A�fUC��&�n��.�?�.�^����f����]�H/^�U�Y�vZL����&BK�,L����JZ��������������Z��u��$pF�X�����h2��f�l���J��!�w����2�C{���^%Z?t����By)��K}��1���Qo�5��7�]�\wY���s��z�gs���S�(�]���H���(�j��~���B�?��{����K����az������l\G!r�������ZAl���H��p���s�����k^�D���s3��'��r����;Z���]:���fj�mG�=�n��@$�)>�����2��oO��!��TM�zl��X�?�t/'F�>U�����
�P��&���4 �P�D�U�2�$Q&���'E?���r���q��������~Q,���RG�������U�3���l��a��y�d��r������K�e",	O�y�E�$������>z2��:r��i.�	����?v9�k���Xk(���FO�m����-}�;~�_e}y�Pz��H���y	���y�2t?��������~���Q�;6����P��i!�>+�j9���("�#����emv������ ~F�J�t��b��Lyu����x>v���H:��L�A�:��}���*���9pZ���m����XJ�������d`$�L*y�WF�+�R���N�B��Y���w�	�NJM�������GJC��i$���.����0�w����;)���6F8�����#_O�*r������U���H��Jxb����oS���o��t$���x����[fp����6Zi��i�p�N!��k��Z�c��Vd�u20��H^_����\ie�u*H��d}X�USI����)�mB)�F��Y�J}m���U�l��4�[E�B\|yR�,��&P���	��KX���0e-|o�9_�I&X��Kh@V~v��@����b!�m�Q��.��0�|�|6���y�0����b�}B+���dw��?Tf�z`�
�\(��e�-���6�S	������$THb�yytK$��s��	�J���q�\��\���'���7��`��D��]���"��Md?'�������qp���������X��-�^����������	E��ob;6e����$�6��������(����I���y�����������C���g}����f���{�Qg
0007-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gzapplication/x-patch-gzipDownload
0008-wal_decoding-test_decoding-Add-a-simple-decoding-mod.patch.gzapplication/x-patch-gzipDownload
0009-wal_decoding-design-document-v2.4-and-snapshot-build.patch.gzapplication/x-patch-gzipDownload
�l��R0009-wal_decoding-design-document-v2.4-and-snapshot-build.patch�[iWG���_Q�/mH`0;'2('�qr|<>�������[�2������E����Kb[t�r�.�]���4��<�<+y�?>9���NN�����'��Qo�������'��u�[5�c��?��E�����0�S�����c_<���O2���[�_��8�����o�Cq�<L������xp�L4�{����|�����xw=�;�E��t{��b)���?���+Lc�'^�8�~�P`K�c9��$k�q�4�2V,�;O�v��:��c������j���$����������e'��	�� ��������{-��$����8���t6��
�^�:�����o�/�*�<������ hu-������gx�Z���~��m/U���_	�����+��M�7������D��� �����F����*�� ��G�/�t:G'����#�]_-�q�
������'��oA�i�O?5��n{��[�$������K0���P!��r�����)n�} ;q��lJF���x�|�b6,�>���B�
�����b2g[x�&��L��Y2�fI�f�-����r���/2���*�A8�n+:^5� ��8��4�s�	|�����]��"-��Ou&��y(q��l%�Jd� �sw�X)_c�$������X�$����r&3��_�c3�$��J�UI��d�x�w37��.}�2o���<�!�4���A4��v�$���P�r,-c�dX�RM�&��>��,�f"��=�c��@@m�=ad�i�m����H�u�-�z�KfRLU�R��� =O�r]�
����<\��4�8M�	v�����aq�8\	�-f����#Y�������2BjV$J�6���2@x�0����k9�A��K�`�)G'�5H��2���,�{�&��*��s��I�C�BZ�t����/�u�A�C3���N+r�R%$�d����P�S�P@�_�5,+��R#>@��@)�OY����[h�L�Y�����b���,���n��,���#�v�t����r����%��?������I�S�_�|�6�/�nD��*1����~�wp�������r
�2v_C'XgaJ:�Lbo%�<%VZUT03�"�A�/���}5���)�N"(�K�A����VkH�s��!�*9%:�qj'����Q�=1�h;��di���8X�`6�A��.8�R�$f}��X�
�"Z�2!EUi���|��4p(�l^?��c�d���&�:;� ��c���AaL�
eB�ZWB3���$v;�������L�W�|:���pl'OIIy��H�!�_��(����Y���d���m��m�|U[	/OS���
��=`��YH�������MLmt'7����-��0�WXg�����IA�J�B������6�l(�
�W�G���X�������#0
bHB��3�"_���	�Y�	�#�?�^�V��s�$hU�wW�r p"xJ�$��%~��n��x��@QDr�Xw|�^�����|O`jfNoij4���0n'c���q��Is������f��hz	H����y�L�|�7���B�tH��<C��$O�����K@Dl�
0;�`������/�5�%����7�ETd9p�^T-�zQ�`2
("�H�ad�7�:�L0�$ri����^%� 80���������18e�D������ flM;]���ll��<�5i��o
m��|Q��[,9Q�gp��Q���f�A0�TiFx���L�&�~��m�9��D��!|nm��F�h����?�����ZX�E���_0�C�}	���#E�GcL�,j�o�` 2��T�/�����CrE��hU�h	{�'L\�����]��W�7K���n@�*���T1�05<�,:�~S0����S���>s:3�u{�PJ��G�������jS���+����>C2A&�����,�:�en�%�`�������d��2.O(�c���)���P��z������r��:��r#�a�qH�������x}&����	e��9� [A�����pB�soY����IQ���
���33904 ��s�l���2I����}�f����P�q��S�X_�S�Jz(*���,E�NG��Z��:�c��8��V��@��|�B%:���t�
�m�Og&yp�W�v�S��p&(���������I�j����Hb"��(���d(!�2g��4��Oh�q�;��;D�� >�l���Ed����#��Ef��J���q����ny+�s�\aV' 
����%t\�p����d�#�����*s�J��=�z���;��	aH&<����a$%��\�*����K-�o���>��=���
NQ����peb=	%f�3 �������3�dj���;��$�@l�)dSx��"���{��e����GT��3�X�t<zKD�B���*���9���r�
6 ����U��=��l���pe�V�\��������j&�iJi��6oV�Hk��KBB�*Y�A�����EF��J�Sm�>������.g~!�y�P+�c�*���F�3��m��d�kSm�FM���-iw�����D��4�N{��P�|��\��|�����g�[*��Py.+:�����m�%��8�,><"{g�h�h6�R�,N�HH��&	r6��������ow��v���G>�@���=c��b0(��4u@��Z�1�D����j)�U]5Bz�-��pyU��`��.!��0L8��M�=��?�>Z"F"O�Ds�JOEvE2$;[�E>8R�wJ��1�b���&E	J`jw!>�<-��LAT`�����t��oT����i��*J��9�woD*9T���_�������K��|m�Z*WD2��]K[�b3+�(��k�`����%�����M081�L������y�����	.\%��[�)����)i0vH�5S�L8��j�r<�&T�b�*����u�O�xA]"��U����%U%�,~�fkZ��C%�`J����X���AQS��K:�,~���G���T�g���T�&g�p�BZh����0lm�:����T�r��6m��-��B�BYX���"�������Z�B.�t��D��Z�e��A;ejJ�+��pR�"��9f9
��a*��s�h�]�Dr�����+6�F��;>c���{�a� ���~�����]��?�����KeZ�f�dB��r�/�D�Ksa���0�����	p��v(�j�k���j��{����G�����tu��-���b�����yvt����������nn�|���c
S���S�7��]���.�h]���I�R��%��?>P�.E��-��������G��a�.��n9OG�pV���[)'ZV�V~��.�?��F�Y�������]�y(�<lU��K��k��vMO�gv"����&����>�xd��7_l��DA�������������U{�����$3�����aYT.�:���}�~�M����4�x[�9���u5���������}�xP��h�-.T��o���3|��|�M���^�E|�(A�h���������_����w���sEq[�q���v���6��Fz_�o6,�9��(1(����������g�M>j������y���'��8
����X��#i<l����fQ1&�^�P0#]L��i��uU��� 6��	��r����R�	��}���M�%���f���N�D�Nk�Qzn�9��#��:�\����lf�H[k�	Q�H�#�z@�`���
�[�&t��5����-LL���;��e&����� W�������6�������'�*�6�t��i%�T������l�4\C����,�AE���k(j���	��;K�6�C`zo�F��'��m�8�����R�L)�i1����@L"�;����iU�P�zQV�8�g!�L�nwm���C}&mz!l�������r�4�(���E�Ns�����B���,�m�b�\��dTRF�d"�ML%eGD�r�@G�f����;���:*G-Y^\����e�{�50��:�mVZ��RuY�%W��zm^�u�[d6����og���xz6/���+��,#Kn�;��,���`h9��S��+e�j4����
d�T�����fTv	!:�eY�&���G=(`�k���Z��)�;Rs�
�%��f�`��L�%t
p�����aX�(�{�.��2�.�� �������.��.
���YW���
��YI>,��m� ��r�S�����
����$��"�U�d���Jh��.���������������q�}D��m
g������,�u��N�5�X����n)Q:V��g3o��:9�Z���"�F���X�U�7U�ZM���%�A���J������o�U�����!�D6GV�
B�i*�ew�a���p��/�T�$/�Wt!�n�PG6�6�1��[0�T�������,���r7�l����0�K���-h"�i&���8������S�5Ui�UT�ia&6�z�a@Y���� ���3w.�<�c���Tt��qR�F���;t��u~����NF�AH��"N�g���T���r���2���8��
�H��J|-����C*h�|��?��)���4�����8��\��k#}���F��������)�/��X�:`�eTq�m���	��9	p�D�m<�	!���v��k����f*��������~�A���j���M��!�J�C��D����2]��:�+o��J'����:w����C��������23���bYS5�6k[��rl[4L�����d���v��
�'}\��E�nd��[e���s��aB�D\Q�����4�������F��~%�%��/c���(�����s��ARon��)c k��f�����]�;8��6�.�����R	M���23$��%��\B3�_�?�	�sGE�$�E����J���zvv105s����I�����3G����Ww������G3-z|j���G���%i�7���6�7W/���������ft&v&;��h��:����7���H�
_^�x5��B=��+;C��/o��w�W�vr�yvsum'��,F�����V�?�C�������N����|�a|0�u��R7��������W��w��mX�I������o�_o����0Mf���A��\����I����[9��%V���j�n-����������x�k���������^�>�c6�L/�F7��+�gg������K1�|������-	�� -q��+}W>]�oW��u��u[������aJ:� F��)�=�d�Sfam3\������1����"��9�
���{`U�;��q�16��.��G��2�Mi�8��R�������3��m"�9|�p��HL$��bu9�������G����?�Gd��������F��}3����=����_�� *��cQ���ul�x���5������QliV�����w{�N�������rtp�l�l�vxs	.�`��>0J��!YNl�@�;���A����)�;�������-��J"���d���A�a�~�~����������>���W,v��b���`N��������);���}������'�-p�o�Uo��C�]���o$��xZ�bGl������ZfH�<i��j.e�_�%��� �}�����%���8d+�e������7�&E7�mrf����b������������_�f[��_n1����sV{0U_����U���=[���+�|U��z�m�w�Wf���������DT��G��	��Y���bT����Fu�A��(��C��kG+�mQ�������6�#�y�+:;$�������9��s(R�#y�x��$�@#�!&��woU��R���l�h�~k�Zn�j��$@QrL���y�Uw�Q�������tch����xN�������Y����y��}O��6��>�^/�H1�l����w�����ll���P�:�04�!N�p��i�F�_Y�v��8��
�1E��D��x)mN�lk]L�W1'�;�������_������b��%a���7��<<=<����~�1���))I�w�����O�G���f�>�%V��k�D��A�{C������!O��M��Q���O�����y�4�b~�F����J ��m�~�nM�f���=��^��oj����,�[���g�usR"��Q qx"���@�����p*� MAo���)�Z���P�=��l��],(���i���=�g?��N���S������z�)�h�$����\b��z��2�0y�)y
��'����.�mf2�����Q)��|��!�u��)�������c��#���,����~��"A`$V6g��d���rrL������'7r���x���/����TIU��3��@w��^�B[���s+x���g�YM��Q,��s��}>�FG����<��������abC��i��
���
��y���}\A0�k�YV�xdW������Q���k[��YU�$��H��}m1�R (e�k�����%8�zb V�
T��p_��)Lr���� ����%@8F��c&���j�U��D/`�1������4G8D,��p�M���1���_��,�����*��.���W��n��R?�\F�L��
3��rRJ�T�r7�$?�o,�je�����2����[w7��O��N��x���)�����5�~�`����eq���G/,/��~�������x�R ;��S�����d�3O��)��G#�Z�,�1�����'>?[�c���4��=���Z�0�H�Mlo$(Im:$�g�@��	 QA�k�,�W�I�h�����0C`;�4R�\-�o|c�=8>���H��_��$Qv��W����H��r/��`T�y�X���p�����p�����F�4Yt���mMHr�_���M���'f=����M* ��#g7��	;�d2u�Lhn"ee����+�OC���1���y��F�Y 4d��o�(w�2�Zz!��s7��Bg�x��� ������P��������q�B�U��S� ��V�R�0��X���
$D�i+�F����fS�*���okl��SI��r]�&xMhb���!h������7�����v�����=I��P�A�&R<�85���G7�[w�YHS�,��X��!4m������x7�h4���5@�J��R��<��������!Noz�H�"bV�m�9�dN��v+$O ���X�cM�_��9�������0�X�,H����]���`�<F���
D�f��M)f�=:e���6���*�^���8C�j���<�J�\��� zs���8E�[��B��[K8_<�$�g��X\C��JW	�D��=v��1���*A������Cb��j��7r"���2E���$���I__��m�zy$H2����R��%������I�f���*]?��@�����������������Q�2��n���\�����)�L�x���n���),����'�@��c~��I�s���s/Q����k������z8��Oj��3��f2������I��h	B������������C#�Wo�a"�q��n+�o�3"��lN����2��tF/��b�9-O
�_�G*���zb��&(F�P�G��sk�4�P�\s��x�}q�K?{
 ��v	:L
g�������*b����r�C9+���������LtM9 �J��N5�2�#w�+	��Y��&m5/�Q ���J_v�1(�� O������.���e��$��������O!�8�x������xy|2�=���4�cRQ��|zui|q�<�m�T�3����z����-\������
�$�I�X7�e��r��+�����l�����&���K�(��SU��b�c��j���dN�>��K�	1�������%��7
w�(��<�'���!Cj�?�2��WF)��: �����)z�0
2��x#����8��K>6O�@��Y�����*�0
�a=Mn�������i��7Gg���[Z��8�����1;��i�54a�)F�s��6_��r�:�W�e����M�x$5�$��Gz	S��/��	��'���"B3����F��U;Nb(e���V5���^#���B)m&���������d��M%�%����KOnDS�=�w��wj��-�3��x_���)�:���
/� ��XMU���7�z��1aK�x
%��M�/��'u	�����,�~�O�(w�twF��T"�;dvy.���[�QI���r�6��1Z���A`F+�;�����&N��j&��|zvD@�iL������������.>�)�IH@�7�@]�9}2H`��H�3��>��c��O5���N�L�;9^A������5]���q����7���@�c �*�]kN9��}�d
sm\r����0��D]�-CG�������)��������z������\�i�H�]M{���M��.'�n%$�"V3INZ���p���hp�����OO^$������4;�=Xi��*�������|�n`]���� ��g5�q��6�~��������~�����������������-O�����O�'���g���w�|��U�����{��$����G��+=X]������L�|�F�V��/�eCR��/om`]��'�A������o����U�+CMV��`@���t�m;��7|V�Y8�<�}q��;�]�A�[x�}�D�z�4��f����������F=��
�}p����-y(�}�~�;����n�i+���:r������u�#���VgZbp7�g8	�,M��=R�T�p\sH]Im�����D#jLy��'7�Q�f���?��������	��:q�9Hbg`����?�d������Z����_��f����"/|���������~d! �8�����u�q��s�~�7f�����Ow��f�?�z_l�6G�|;�b�>������i�Pm�~e!��/�^uZ�s�,�r��p[��mx���������a��v6��-]�R�h6��>��u�#�.�]����fY�"sOd�}�l}���l9r�M��ybck�?}t���U�V�������������������*���Q	)�B	�u��Pg�*�WtR^�WW7Qy�Y����,rh	97v���r�n�7(���,��u����l@Eot��n� �^Q��8]�����<��T�h�@,���s�
@����3�����e!�>��Z��3��@��Gk
����?�o�bJ����v�.�Bd>w��E01	��]�5�(I�d�h��V����� �+1��tQX����}-��P�
>�t�I�-��L��l8��GIV��t�i��Z\�$_��BL�	r`K��_�o��6�?�=P�9��Ph��'n�J������Z�
�\O����m���\��3�u���z��Ci���^��j�xC�:�$�hs�����w��IPF)��y�
�
����7��-^F �d�x������J� �s�1��[��������������}q$�������=dH
4���w���W���n�����nSK�E���������S�C�@*1D���4�	�����G/��6��{|��M���N��S)�/�T�5��I>u��Vv	�q�L�R���\CR��+����P4�v��]��B�������\M�N}�g^��rqf������H�4���f1�Q�Bq��^�y���;alF����|�G��v����/��-b��v���{�J��Y;e��(u��]��:��Z6vJ��'_�@�0  ���b������$_@��5
����<��%��H1��O��w �9��.b{�1n!� ���@B����P�^$��se�����?�t�������`���05��U���S������r=��������d��7��Y�{���V.��&!,,�/DQ��������0���:��h}O��X�?���4��^x�8!�����Y-7c���V�Rr$�j�����������pP(���u;�(_ND$�3&��{)�)���yg����]�L����!�����T�%\�)�"�o��4..��7J��%���&�IR�g�y<�����]{(���X���+��H��w-��o1O�R�|9�{C��������A����
5M�1b���$���rF�P
�p�+6J����h�H)$���e1F�  ���ot�u���G��Y'LS+���g��5!�VP���%b����>�J$9������T�E�]9���!�KE�����=K� 
�I:��0��rg@���%��f����A�U<��GA��%���i>WR����6)�i��D�����i�����A����� �����7�����if9�"��y�=m�H)����$'�Z��`!p_bL������y��I��cT�Ro}M����������l������l�������Oop�J#���u��`��;���!��RtmC�^(�a�x�}�Lk���{PMs	���	|Z���I9)%`w�C���y}x���������w����UU2�(p&����c�CD�y�I��������7-�m���d���%%��[B
&���z��T��#yw��\�\�5t��10q�'�m�j��'�$���F�?���-t���g�n?vi�/m�H�{�&H�l����R���
�PB+(���~bX���E;+o!��1�+�u�M�m�0cu�U��������5t�����:���
��"R?^���y��-`YQ�sa
�h�s���sQ6Z�����%M\y*9J�M�����mZK8�������5���A��el-��y����4���Uc�bZ��u��/���w�s>9=GfQ�{^A>�@�/���:`�x �#!T�a�w�y��G/H� lTaT���NM��wD7D���{-�A�^��z{2`���Q����U��s�~�qE�S�)F�����{i���0y�2{1�����u������2����=-�h9M�#��`#�1��2*3�eZ����$w7���\�(B��=/^�EENL2��h����H��)�,��pk�����l#If�W��"�VsO5�4;����������}��\� ��g-(>�Y���~P��lp����������xA�O�lFSuT���T�	���d����$�2�wC�K��u"�����[�"����I�GV�!~��%������Z�AJc��+c��_�##�X;;E��U����
+�_��I�_y�8h-���x����Zz��k'�G���d-�^���������f������y&x,���Z���G5����<m�3��������G��INy(����"`����4^����L���7��'G~�Fnp������K��?���7�)^\�l���>��bI��e�p�*�N�3�p"1������c'�md��aRsP-1�R��Zj��l:V��W8����G�Q��+v�Q,�"�M�T�yb\ :�$+�Owg��o�y^ ��9s������S>C��5��d�'�'A.�>/N�Fg+�������2JwT��=9L �6s	��Ag_+�4�Hq����r���@��:���I]T�
�������_Pk~�V��2��b��f�M��(�� K���k0]���7��p(�e�/$��-�f�;n~9��Hq\� ��ex�����^K)����r�a�hVkv���Vh������<�y�b�����[BXv��<ucY���S�t�d���)AJ�����DO�E��F�����s���,�r�d���@��!T�i����s�?%�lQ�|]X�)��D��*����^';4ugx��SP7�V ���B�G��$�,y#�#�bc:#|"�7��Llt������`T67!1���{V��04��je1s�RB�������Q�N}� m�d�����'�����>���/w������8)���V�����M�w���������Z�c�����D��?\g�@Lu�.�k�f�$!��/��������d^��v�����Q��8�����Q��1Y&��II�$���lC�2�)�����"������b�H����Cs!�B��!dg�fw������PG�#B�:�Q�au�6�r�,N�lGM���-_�����1n��k\�9�d_��e5�p)q�-���!_������t��o�	z��K�����J��E������X�$R��6h<��L���0���v<��������T�J�p�K��C�I�n��O�k��o�u�%a x���n��H��q��Hn�hT������&����y�FF�p������T}ID�xJ#Ov�X% Y��0P���B��r��_��X:����>*.�)i��X�s�"��[�=�/&������34���'Bj��Tb3Q��he����~��i!�)��(&�X����������N�,��+ERT�
������xQ�.H ���^Z�o	����t>U"h�s�k������1��h�����g����y�
(��P�s���:''��|���p�AB1�]�����������wv����TKD�
�;P� ��W',k"�Zw�,S�(ctND�4p����BDDRT����b��>2��QAh�����I���a/��|�*�z�]K���(J��X�v-��w[��>g(�=�	��g���O/�&*a�O�M�k��V�a�q1�4�Wum����d���$B:�F����:���QB�����JjP�k���O(��8�jf<s�ZjV��=���^�K��n��]3m_;�6�Z�>�D$��^�13��c������0\H��N+`2ec�B���K��d��7E+RJLc.^�\S��nC�l{�l�~���7���AT�]������
0010-wal_decoding-Documentation-for-replication-slots-and.patch.gzapplication/x-patch-gzipDownload
0011-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gzapplication/x-patch-gzipDownload
0012-slot-hack-up-pg_receivexlog-support.patch.gzapplication/x-patch-gzipDownload
#25Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#23)
Re: Changeset Extraction v7.1

On Thu, Jan 23, 2014 at 6:32 PM, Andres Freund <andres@2ndquadrant.com> wrote:

I also wonder if we should use the
terminology "attach" instead of "acquire"; that pairs more naturally
with "release". Then the message, if we want more than an assert,
might be "this backend is already attached to a replication slot".

I went with Acquire/Release because our locking code does so, and it
seemed sensible to be consistent. I don't have strong feelings about it.

Yeah, but I think a slot is not really the same thing as a lock.
Acquire/release might be OK. In some of my recent code I used
attach/detach, which feels a little more natural to me for something
like this, so I lean that direction.

Unfortunately not. Inside the walsender there's currently no
LWLockReleaseAll() for ERRORs since commands aren't run inside a
transaction command...

But maybe I should have fixed this by adding the release to
WalSndErrorCleanup() instead? That'd still leave the problematic case
that currently we try to delete a replication slot inside a CATCH when
we fail while initializing the rest of logical replication... But I
guess adding it would be a good idea independent of that.

+1. I think that if we can't rely on error handling to clean up the
same things everywhere, it's gonna be a mess. People won't be able to
keep track of which error cleanup is engaged in which code paths, and
screw-ups will result when old code paths are called from new call
sites.

We could also do a StartTransactionCommand() but I'd rather not, that
currently prevents code in that vicinity from doing anything it
shouldn't via various Assert()s in existing code.

Like what? I mean, I'm OK with having a partial error-handling
environment if that's all we need, but I think it's a bad plan to the
extent that the code here needs to be aware of error-handling
differences versus expectations elsewhere in our code.

This doesn't need the LWLockRelease either. It does need the
SpinLockRelease, but as I think I noted previously, the right way to
write this is probably: SpinLockAcquire(&slot->mutex); was_active =
slot->active; slot->active = true; SpinLockRelease(&slot->mutex); if
(was_active) ereport(). MyReplicatonSlot = slot.

That's not really simpler tho? But if you prefer I can go that way.

It avoids a branch while holding the lock, and it puts the
SpinLockAcquire/Release pair much closer together, so it's easier to
visually verify that the lock is released in all cases.

ReplicationSlotsComputeRequiredXmin still acquires ProcArrayLock, and
the comment "Provide interlock against concurrent recomputations"
doesn't seem adequate to me. I guess the idea here is that we regard
ProcArrayLock as protecting ReplicationSlotCtl->catalog_xmin and
ReplicationSlotCtl->data_xmin, but if that's the idea then we only
need to hold the lock during the time when we actually update those
values, not the loop where we compute them.

There's a comment someplace else to that end, but yes, that's
essentially the idea. I decided to take it during the whole
recomputation because we also take ProcArrayLock when creating a new
decoding slot and initially setting ->catalog_xmin. That's not strictly required
but seemed simpler that way, and the code shouldn't be very hot.
The code that initially computes the starting value for catalog_xmin
when creating a new decoding slot has to take ProcArrayLock to be safe,
that's why I though it'd be convenient to always use it for those
values.

I don't really see why it's simpler that way. It's clearer what the
point of the lock is if you only hold it for the operations that need
to be protected by that lock.

In all other cases where we modify *_xmin we're only increasing it which
doesn't need a lock (HS feedback never has taken one, and
GetSnapshotData() modifies ->xmin while holding a shared lock), the only
potential danger is a slight delay in increasing the overall value.

Right. We might want to comment such places.

Also, if that's the
design, maybe they should be part of PROC_HDR *ProcGlobal rather than
here. It seems weird to have some of the values protected by
ProcArrayLock live in a completely different data structure managed
almost entirely by some other part of the system.

Don't we already have cases of that? I seem to remember so. If you
prefer having them there, I am certainly fine with doing that. This way
they aren't allocated if slots are disabled but it's just two
TransactionIds.

Let's go for it, unless we think of a reason not to.

It's pretty evident that what's currently patch #4 (only peg the xmin
horizon for catalog tables during logical decoding) needs to become
patch #1, because it doesn't make any sense to apply this before we do
that.

Well, the slot code and the the slot support for streaming rep are
independent from and don't use it. So they easily can come before it.

But this code is riddled with places where you track a catalog xmin
and a data xmin separately. The only point of doing it that way is to
support a division that hasn't been made yet.

[ discussion about crash safety of slots and their use of PANIC ]
Broadly, what you're trying to accomplish here is to have something
that is crash-safe but without relying on WAL, so that it can work on
standbys. If making things crash-safe without WAL were easy to do, we
probably wouldn't have WAL at all, so it stands to reason that there
are going to be some difficulties here.

My big problem here is that you're asking this code to have *higher*
guarantees than WAL ever had and currently has, not equivalent
guarantees. Even though the likelihood of hitting problems is a least a
magnitude or two smaller as we are dealing with minimal amounts of data.
All the situations that seem halfway workable in the nearby thread about
PANIC in XLogInsert() you reference are rough ideas that reduce the
likelihood of PANICs, not remove them.

I am fine with reworking things so that the first operation of several
doesn't PANIC because we still can clearly ERROR out in that case. That
should press the likelihood of problems into the utterly irrelevant
area. E.g. ERROR for the rename(oldpath, newpath) and then start a
critical section for the fsync et al.

I have zero confidence that it's OK to treat fsync() as an operation
that won't fail. Linux documents EIO as a plausible error return, for
example. (And really, how could it not?)

Calling a slot "old" or "new" looks liable to cause problems. Maybe
change those names to contain a character not allowed in a slot name,
if we're going to keep doing it that way.

I wondered about making them plain files as well but given the need for
a directory independent from this I don't really see the advantage,
we'll need to handle them anyway during cleanup.

Yeah, sure, but if it makes for fewer in-between states, it might be worth it.

How about letting the xmins of such backends affect the computation as normal, and then
having one extra xmin that gets folded in that represents the minima
of the xmin of unconnected slots?

That's how I had it in the beginning but it turned out that has
noticeable performance/space impact. Surprising isn't it? The reason is
that we'll intermittently use normal snapshots to look at the catalog
during decoding and they will install a xmin the current proc. So, while
that snapshot is active GetSnapshotData() will return an older xmin
preventing HOT pruning from being as efficient.

Hrm, so you still need the flag, to indicate whether the xmin should
be included when we're computing a globalxmin for pruning of a
non-catalog table. But that doesn't necessarily mean that the value
has to live in the slot rather than the PGXACT, does it? It might be
for the best the way you have it, but it does look kind of weird. Not
sure yet.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#26Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#25)
Re: Changeset Extraction v7.1

On 2014-01-24 12:10:50 -0500, Robert Haas wrote:

Unfortunately not. Inside the walsender there's currently no
LWLockReleaseAll() for ERRORs since commands aren't run inside a
transaction command...

But maybe I should have fixed this by adding the release to
WalSndErrorCleanup() instead? That'd still leave the problematic case
that currently we try to delete a replication slot inside a CATCH when
we fail while initializing the rest of logical replication... But I
guess adding it would be a good idea independent of that.

+1. I think that if we can't rely on error handling to clean up the
same things everywhere, it's gonna be a mess. People won't be able to
keep track of which error cleanup is engaged in which code paths, and
screw-ups will result when old code paths are called from new call
sites.

Ok, I'll additionally add it there.

We could also do a StartTransactionCommand() but I'd rather not, that
currently prevents code in that vicinity from doing anything it
shouldn't via various Assert()s in existing code.

Like what? I mean, I'm OK with having a partial error-handling
environment if that's all we need, but I think it's a bad plan to the
extent that the code here needs to be aware of error-handling
differences versus expectations elsewhere in our code.

Catalog lookups, building a snapshot, xid assignment, whatnot. All that
shouldn't happen in the locations creating/dropping a slot.
I think we should at some point separate parts of the error handling out
of xact.c. Currently its repeated slightly differently over logs of
places (check e.g. the callsites for LWLockReleaseAll), that's not
robust. But that's a project for another day.

Note that the actual decoding *does* happen inside a TransactionCommand,
as it'd be failure prone to copy all the cleanup logic. And we need to
have most of the normal cleanup code.

I don't really see why it's simpler that way. It's clearer what the
point of the lock is if you only hold it for the operations that need
to be protected by that lock.

In all other cases where we modify *_xmin we're only increasing it which
doesn't need a lock (HS feedback never has taken one, and
GetSnapshotData() modifies ->xmin while holding a shared lock), the only
potential danger is a slight delay in increasing the overall value.

Right. We might want to comment such places.

Don't we already have cases of that? I seem to remember so. If you
prefer having them there, I am certainly fine with doing that. This way
they aren't allocated if slots are disabled but it's just two
TransactionIds.

Let's go for it, unless we think of a reason not to.

ok on those counts.

It's pretty evident that what's currently patch #4 (only peg the xmin
horizon for catalog tables during logical decoding) needs to become
patch #1, because it doesn't make any sense to apply this before we do
that.

Well, the slot code and the the slot support for streaming rep are
independent from and don't use it. So they easily can come before it.

But this code is riddled with places where you track a catalog xmin
and a data xmin separately. The only point of doing it that way is to
support a division that hasn't been made yet.

If you think it will make stuff more manageable I can try separating all
lines dealing with catalog_xmin into another patch as long as data_xmin
doesn't have to be renamed.
That said, I don't really think it's a big problem that the division
hasn't been made, essentially the meaning is different, even if we don't
take advantage of it yet. data_xmin is there for streaming replication
where we need to prevent all removal, catalog_xmin is there for
changeset extraction.

I have zero confidence that it's OK to treat fsync() as an operation
that won't fail. Linux documents EIO as a plausible error return, for
example. (And really, how could it not?)

But quite fundamentally having a the most basic persistency building
block fail is something you can't really handle safely. Note that
issue_xlog_fsync() has always (and I wager, will always) treated that as
a PANIC.
I don't recall many complaints about that for WAL. All of the ones I
found in a quick search were like "oh, the fs invalidated my fd because
of corruption". And few.

Calling a slot "old" or "new" looks liable to cause problems. Maybe
change those names to contain a character not allowed in a slot name,
if we're going to keep doing it that way.

I wondered about making them plain files as well but given the need for
a directory independent from this I don't really see the advantage,
we'll need to handle them anyway during cleanup.

Yeah, sure, but if it makes for fewer in-between states, it might be worth it.

I don't think it'd make anything simpler with the new version of the
code. Agreed?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#27Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#26)
Re: Changeset Extraction v7.1

On Fri, Jan 24, 2014 at 12:49 PM, Andres Freund <andres@2ndquadrant.com> wrote:

But this code is riddled with places where you track a catalog xmin
and a data xmin separately. The only point of doing it that way is to
support a division that hasn't been made yet.

If you think it will make stuff more manageable I can try separating all
lines dealing with catalog_xmin into another patch as long as data_xmin
doesn't have to be renamed.
That said, I don't really think it's a big problem that the division
hasn't been made, essentially the meaning is different, even if we don't
take advantage of it yet. data_xmin is there for streaming replication
where we need to prevent all removal, catalog_xmin is there for
changeset extraction.

I spent some more time studying the 0001 and 0002 patches this
afternoon, with a side dish of 0004. I'm leaning toward thinking we
should go ahead and make that division. I'm also wondering about
whether we've got the right naming here. AFAICT, it's not the case
that we're going to use the "catalog xmin" for catalogs and the "data
xmin" for non-catalogs. Rather, the "catalog xmin" is going to always
be included in globalxmin calculations, so IOW it should just be
called "xmin". The "data xmin" is going to be included only for
non-catalog tables. I guess "data" is a reasonable antonym for
catalog, but I'm slightly tempted to propose
RecentGlobalNonCatalogXmin and similar. Maybe that's too ugly to
live, but I can see someone failing to guess what the exact
distinction is between "xmin" and "data xmin", and I bet they'd be a
lot less likely to misguess if we wrote "non catalog".

It's interesting (though not immediately relevant) to speculate about
how we might extend this to fine-grained xmin tracking more generally.
The design sketch that comes to mind (and I think parts of this have
been proposed before) is to have a means by which backends can promise
not to lock any more tables except under a new snapshot. At the read
committed isolation level, or in any single-statement transaction,
backends can so promise whenever (a) all tables mentioned in the query
have been locked and (b) all functions to be invoked during the query
via the fmgr interface promise (e.g. via function labeling) that they
won't directly or indirectly do such a thing. If they break their
promise, we detect it and ereport(ERROR). Backends that have made
such a guarantee can be ignored for global-xmin calculations that
don't involve the tables they have locked. One idea is to keep a hash
table keyed by <dboid, reloid> with some limited number of entries in
shared memory; it caches the table-specific xmin, a usage counter, and
a flag indicating whether the cached xmin might be stale. In order to
promise not to lock any new tables, backends must make or update
entries for all the tables they already have locked in this hash
table; if there aren't enough entries, they're not allowed to promise.
Thus, backends wishing to prune can use the cached xmin value if it's
present (optionally updating it if it's stale) and the minimum of the
xmins of the backends that haven't made a promise if it isn't. This
is a bit hairy though; access to the shared hash table had better be
*really* fast, and we'd better not need to recompute the cached value
too often.

Anyway, whether we end up pursuing something like that or not, I think
I'm persuaded that this particular optimization won't really be a
problem for hypothetical future work in this area; and also that it's
a good idea to do this much now specifically for logical decoding.

I have zero confidence that it's OK to treat fsync() as an operation
that won't fail. Linux documents EIO as a plausible error return, for
example. (And really, how could it not?)

But quite fundamentally having a the most basic persistency building
block fail is something you can't really handle safely. Note that
issue_xlog_fsync() has always (and I wager, will always) treated that as
a PANIC.
I don't recall many complaints about that for WAL. All of the ones I
found in a quick search were like "oh, the fs invalidated my fd because
of corruption". And few.

Well, you have a point. And certainly this version looks much better
than the previous version in terms of the likelihood of PANIC
occurring in practice. But I wonder if we couldn't cut it down even
further without too much effort. Suppose we define a slot to exist
if, and only if, the state file exists. A directory without a state
file is subject to arbitrary removal. Then we can proceed as follows:

- mkdir() the directory.
- open() state.tmp
- write() state.tmp
- close() state.tmp
- fsync() parent directory, directory and state.tmp
- rename() state.tmp to state
- fsync() state

If any step except the last one fails, no problem. The next startup
can nuke the leftovers; any future attempt to create a slot with the
name can ignore an EEXIST failure from mkdir() and procedure just as
above. Only a failure of the very last fsync is a PANIC. In some
ways I think this'd be simpler than what you've got now, because we'd
eliminate the dance with renaming the directory as well as the state
file; only the state file matters.

To drop a slot, just unlink the state file and fsync() the directory.
If the unlink fails, it's just an error. If the fsync() fails, it's a
PANIC. Once the state file is gone, removing everything else is only
an ERROR, and you don't even need to fsync() it again.

To update a slot, open, write, close, and fsync state.tmp, then rename
it to state and fsync() again. None of these steps need PANIC; hold
off on updating the values in memory until they're all done. If any
step fails, the attempt to update the slot fails, but either memory
and disk are still consistent, or the disk has an xmin newer than
memory, but still legal. On restart, when restoring slots, fsync()
each state file, dying horribly if we can't, and remove any
directories that don't contain one.

As compared with what you have here, this eliminates the risk of PANIC
entirely for slot updates, which is good because those will be quite
frequent. For creating or dropping a slot, it doesn't quite eliminate
the risk entirely but only one fsync() call per create or drop is at
risk. We still risk startup time failures, but that's unavoidable
anyway if the data we need can't be read; the chances of blowing up a
running system are very low.

Looking over patch 0002, I see that there's code to allow a walsender
to create or drop a physical replication slot. Also, if we've
acquired a replication slot, there's code to update it, and code to
make sure we disconnect from it, but there's no code to acquire it. I
think maybe the hunk in StartReplication() is supposed to be calling
ReplicationSlotAcquire() instead of ReplicationSlotRelease(), which
(ahem) makes one wonder how thoroughly this code has been tested.
There's also no provision for walsender (or pg_receivexlog?) to send
the new SLOT option to walreceiver, which seems somewhat necessary.
I'm tempted to suggest also adding something to src/bin/scripts to
create and drop slots, though I suppose we could just recommend psql
-c 'CREATE_REPLICATION_SLOT SLOT zippy PHYSICAL' 'replication=true'.

(BTW, isn't that kind of a strange syntax, with the word SLOT
appearing twice? I think we could drop the second one.)

It also occurred to me that we need documentation for all of this; I
see that's in patch 0010, but I haven't reviewed it in detail yet.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#28Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#27)
Re: Changeset Extraction v7.1

Hi Robert, all,

On 2014-01-24 20:38:11 -0500, Robert Haas wrote:

On Fri, Jan 24, 2014 at 12:49 PM, Andres Freund <andres@2ndquadrant.com> wrote:

But this code is riddled with places where you track a catalog xmin
and a data xmin separately. The only point of doing it that way is to
support a division that hasn't been made yet.

If you think it will make stuff more manageable I can try separating all
lines dealing with catalog_xmin into another patch as long as data_xmin
doesn't have to be renamed.
That said, I don't really think it's a big problem that the division
hasn't been made, essentially the meaning is different, even if we don't
take advantage of it yet. data_xmin is there for streaming replication
where we need to prevent all removal, catalog_xmin is there for
changeset extraction.

I spent some more time studying the 0001 and 0002 patches this
afternoon, with a side dish of 0004. I'm leaning toward thinking we
should go ahead and make that division.

Ok.

I'm also wondering about
whether we've got the right naming here. AFAICT, it's not the case
that we're going to use the "catalog xmin" for catalogs and the "data
xmin" for non-catalogs. Rather, the "catalog xmin" is going to always
be included in globalxmin calculations, so IOW it should just be
called "xmin".

Well, not really. That's true for GetSnapshotData(), but not for
GetOldestXmin() where we calculate an xmin *not* including the catalog
xmin. And the data_xmin is always used, regardless of
catalog/non_catalog, we peg the xmin further for catalog tables, based
on that value.
The reason for doing things this way is that it makes all current usages
of RecentGlobalXmin safe, since that is the more conservative
value. Only in inspected location we can use RecentGlobalDataXmin which
*does* include data_xmin but *not* catalog_xmin.

It's interesting (though not immediately relevant) to speculate about
how we might extend this to fine-grained xmin tracking more generally.
[musings for another time]

Yea, I have wondered about that as well. I think the easiest thing would
be to to compute RecentGlobalDataXmin in a database specific manner
since by definition it will *not* include shared tables. We do that
already for GetOldestXmin() but that's not used for heap pruning. I'd
quickly tested that some months back and it gave significant speedups
for two pgbenches in two databases.

I have zero confidence that it's OK to treat fsync() as an operation
that won't fail. Linux documents EIO as a plausible error return, for
example. (And really, how could it not?)

But quite fundamentally having a the most basic persistency building
block fail is something you can't really handle safely. Note that
issue_xlog_fsync() has always (and I wager, will always) treated that as
a PANIC.
I don't recall many complaints about that for WAL. All of the ones I
found in a quick search were like "oh, the fs invalidated my fd because
of corruption". And few.

Well, you have a point. And certainly this version looks much better
than the previous version in terms of the likelihood of PANIC
occurring in practice. But I wonder if we couldn't cut it down even
further without too much effort. Suppose we define a slot to exist
if, and only if, the state file exists. A directory without a state
file is subject to arbitrary removal. Then we can proceed as follows:

- mkdir() the directory.
- open() state.tmp
- write() state.tmp
- close() state.tmp
- fsync() parent directory, directory and state.tmp
- rename() state.tmp to state
- fsync() state

If any step except the last one fails, no problem. The next startup
can nuke the leftovers; any future attempt to create a slot with the
name can ignore an EEXIST failure from mkdir() and procedure just as
above. Only a failure of the very last fsync is a PANIC. In some
ways I think this'd be simpler than what you've got now, because we'd
eliminate the dance with renaming the directory as well as the state
file; only the state file matters.

Hm. I think this is pretty exactly what happens in the current patch,
right? There's an additional fsync() of the parent directory at the end,
but that's it.

To drop a slot, just unlink the state file and fsync() the directory.
If the unlink fails, it's just an error. If the fsync() fails, it's a
PANIC. Once the state file is gone, removing everything else is only
an ERROR, and you don't even need to fsync() it again.

Well, the patch as is renames the directory first and fsyncs that. Only
a failure in fsyncing is punishable by PANIC, if rmtree() on the temp
directory file fails it generates WARNINGs, that's it.

To update a slot, open, write, close, and fsync state.tmp, then rename
it to state and fsync() again. None of these steps need PANIC; hold
off on updating the values in memory until they're all done. If any
step fails, the attempt to update the slot fails, but either memory
and disk are still consistent, or the disk has an xmin newer than
memory, but still legal. On restart, when restoring slots, fsync()
each state file, dying horribly if we can't, and remove any
directories that don't contain one.

That's again pretty similar to what happens, only that we panic if the
fsync()ing fails. And I think that's correct.

I still think worrying over this to this degree is a waste of
effort. There's much hotter places that could be inspected to that
detail than this.

Looking over patch 0002, I see that there's code to allow a walsender
to create or drop a physical replication slot. Also, if we've
acquired a replication slot, there's code to update it, and code to
make sure we disconnect from it, but there's no code to acquire it. I
think maybe the hunk in StartReplication() is supposed to be calling
ReplicationSlotAcquire() instead of ReplicationSlotRelease(),

Uh. You had me worried here for a minute or two, a hunk or two earlier
than the ReplicationSlotRelease() you mention. What probably confused
you is that StartReplication only returns once all streaming is
finished. Not my idea...

static void
StartReplication(StartReplicationCmd *cmd)
{
...
if (cmd->slotname)
ReplicationSlotAcquire(cmd->slotname);
...
...
/* this is where we'll actually loop busily */
WalSndLoop(XLogSendPhysical);
...
if (cmd->slotname)
ReplicationSlotRelease();
...
}

which
(ahem) makes one wonder how thoroughly this code has been tested.

It's actually tested as of a week ago or so. Both with pg_receivexlog
and a hacked up walreceiver. That's how I noticed
a472ae1e4e2bf5fb71ac655d38d1e35df4c1c966 ;). Because it did *not* work
properly in the beginning... But it didn't end up being my code. Hah!

There's also no provision for walsender (or pg_receivexlog?) to send
the new SLOT option to walreceiver, which seems somewhat necessary.

There's a hacked up pg_receivexlog in the last commit in the series. I
haven't included the hack for walreceiver as it was too embarassing for
the public eye.

I really, really don't want to focus on polishing up the receiver side
for this before the basics of changeset extraction are done. I've very,
very reluctantly agreed to generalize the slot concept for streaming rep
now, but I said all along that I won't do the client work till the
changeset extraction stuff is done. There is a good deal of UI design
work to be done, and I don't think I have the capacity to tackle that
right now.

I'm tempted to suggest also adding something to src/bin/scripts to
create and drop slots, though I suppose we could just recommend psql
-c 'CREATE_REPLICATION_SLOT SLOT zippy PHYSICAL' 'replication=true'.

There's an SQL function for doing so. In, err, the wrong patch:
postgres=# \df create_physical_replication_slot
List of functions
Schema | Name | Result data type | Argument data types | Type
------------+----------------------------------+------------------+----------------------------------------------------------+--------
pg_catalog | create_physical_replication_slot | record | slotname name, OUT slotname text, OUT xlog_position text | normal
(1 row)

will move it. Not sure if we need the slotname as an OUT value as well,
it's helpful as part of the additional return types for creating a
decoding slot, but here...

Not sure if there's still a reason for a separate commandline utility?

(BTW, isn't that kind of a strange syntax, with the word SLOT
appearing twice? I think we could drop the second one.)

Well, that's what I'd suggested on the mailinglist, so I didn't change
it. It will definitely be a separate SLOT slot_name for
START_REPLICATION, that's pretty much the only reason for keeping it
separate for CREATE/DROP. Don't care which way we go in the end.

It also occurred to me that we need documentation for all of this; I
see that's in patch 0010, but I haven't reviewed it in detail yet.

The streaming rep part is scantily documented since that's pending the
clientside work, but the changeset extraction part should be documented
to some degree... Craig worked on my initial docs and seemed to be able
to make enough sense of it, so I hope it's not in a totally bad state.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#29Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#28)
Re: Changeset Extraction v7.1

On Sat, Jan 25, 2014 at 5:25 PM, Andres Freund <andres@2ndquadrant.com> wrote:

Looking over patch 0002, I see that there's code to allow a walsender
to create or drop a physical replication slot. Also, if we've
acquired a replication slot, there's code to update it, and code to
make sure we disconnect from it, but there's no code to acquire it. I
think maybe the hunk in StartReplication() is supposed to be calling
ReplicationSlotAcquire() instead of ReplicationSlotRelease(),

Uh. You had me worried here for a minute or two, a hunk or two earlier
than the ReplicationSlotRelease() you mention. What probably confused
you is that StartReplication only returns once all streaming is
finished. Not my idea...

No, what confuses me is that there's no call to
ReplicationSlotAcquire() in patch 0001 or patch 0002.... the function
is added but not called.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#30Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#28)
Re: Changeset Extraction v7.1

On Sat, Jan 25, 2014 at 5:25 PM, Andres Freund <andres@2ndquadrant.com> wrote:

I'm also wondering about
whether we've got the right naming here. AFAICT, it's not the case
that we're going to use the "catalog xmin" for catalogs and the "data
xmin" for non-catalogs. Rather, the "catalog xmin" is going to always
be included in globalxmin calculations, so IOW it should just be
called "xmin".

Well, not really. That's true for GetSnapshotData(), but not for
GetOldestXmin() where we calculate an xmin *not* including the catalog
xmin. And the data_xmin is always used, regardless of
catalog/non_catalog, we peg the xmin further for catalog tables, based
on that value.
The reason for doing things this way is that it makes all current usages
of RecentGlobalXmin safe, since that is the more conservative
value. Only in inspected location we can use RecentGlobalDataXmin which
*does* include data_xmin but *not* catalog_xmin.

Well, OK, so I guess I'm turned around. But I guess my point is - if
one of data_xmin and catalog_xmin is really just xmin, then I think it
would be more clear to call that one "xmin".

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#31Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#1)
12 attachment(s)
Re: Changeset Extraction v7.3

Hi,

Here's the next version of the patchset. The following changes have been
made:
* move xmin pegging and more logic responsibility to procarray.c
* split all support for changeset extraction from the initial slot patch
* always register an before_shmem_exit handler when
max_replication_slots is registered, not just while a slot is acquired
* move some patch hunks to earlier patches, especially the
ReplicationSlotAcquire() call for physical rep that accidentally
slipped and the SQL accessible slot manipulation functions
* minor stuff

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-wal_decoding-Introduce-the-replication-slot-interfac.patch.gzapplication/x-patch-gzipDownload
0002-wal_decoding-physical-streaming-replication-walsende.patch.gzapplication/x-patch-gzipDownload
0003-wal_decoding-Introduce-changeset-extraction.patch.gzapplication/x-patch-gzipDownload
����R0003-wal_decoding-Introduce-changeset-extraction.patch�[{WG��[�5��X�I�a�
�/v�����99:�������tu���}�VU?%��p#u��u����$����?��������?����������Q�������8�j.����;����������8��Di�&QY��J����d"��p�W/��d�NOW����= <������^��k_g�_����_���������q/�����������$�3O	o*���*�!M��q�n�L-�H��T"C�N�O��Y���W�(�U�L��2T�~xS�(����B�i�
^-��2)t�3�i��9��,-�]Gr>���'�)�������z� .]2i6�
y+#1R��4�} ���
�y,��r,��t��bf� ��q"Aq��Y��T�y��w��b��	v��#�`����,H���X��F��v���'u�{1Z���8!�NU<Q���W�x�i��O�H%�x'�n�S��m .�(�����d��x/���g�i�k���*���k���R��J��@v������D��S�V\�"�h���/ANE�������b�E0��@���~��&��8��;����J�P{kk�-t���T��H�w�J��9��D��w�����!uV)�\�,m?��Mf_{��>��i_��b_�����c�d�x�i�wG/t�fC�����uH1h@B��1z�3�&M�[+@������������h��w��[5`�+6]
��c���{?�-VD���g������w�����
?�"�Y��}�m��{��bp�(������r�h��;B���x*��*���5���3��G����jE�xh��p�����`������I"M��^s�2(�r������	\Z�����]I_j��56-�&*�uh�oZ�M��b��-w+we���l)�:8��9l�pA����e@�m��m���We�+gC�~�e���U�eg����5P�t�`e������'C����L���iY��ZJ��W�t��6@I�{�O�467���?z��0C���@	�h�1����@��s$]
��e	��GOZ8�i�Ion����4Y)R���*MX�<l(���9���A}Sc�����#�B:����=�_xl��n~��)�2I����e��G^���O�MGz����5_E�N��+_��v�t���L�����@�d����#�Ri���_v6�Q�!e�y�����TQ��`@=T_O�=��K?�p�{�ht��Z���p�R���������������@k���`k���`K>�����XlmMPH��o�G�o.i�)>yx��������v����De��i��?e�[HB{�>��!���V2��C�����U���H��'2KP��]���
�m�VKl���`,:���|������j�v6���71PN���R��jF^�w�T��%������S��������p��xC
���z���P�Fi�����j~"S�O@e&}��B'ql{
|��4Z��l'�VS��L�����k����2���c��H|�����:"�R�.��A���E'���W����0H�HB�3Rj�}�`���v����
�l�������[��c��C6A�F�x��Q6[?mo�� 7q1A�L���2t����b����fI��VZ�8�s��������4vK(-=���|��[���J`�"A�y�a���,��6��j(��XU���S�3&�`�!.�v�J�	�.K����Uq����&6XQ���[Z�����'[=�wQ�
�����������������D�������F�����+gR�����.��OJ��o��^�]
��^������I~N.��B��.���v+�D���V�,LOx'��������X+�p"��6��#�M���Z�:y1�����m����
V�Y�����������Sj����bz��V���
��e���=H�-X$��G��c�Rz�=]k��f���z��ZF����8��c|~Xz�6�'��5R��M�6�]V��u����p���\�2�����x� ���]z�JD���>P.S.�x�4qY[���G5�������
�{9�k���S~i�������y	w���������l��:&�S�y�����o��RXQ�U�("^<��e��"y{D���������a������������ ���D���D���/O��8K<�N�8���H�+}���d�X~���h���f�K��HQ@��
P�(��F���/�~��N0�� �$6�#TS�����O	�F���h����fM
��K{&����?�]n����W��L��aj^�T;b�|���8O��":1o|SLy.|a�N�$���$m_�<D�p��(������7�������������>S�C!f�H��$��hd�"{bG�2?�_�Y�oo��)_������G0>c?��A1��S:K��c{6C[2�xn35����T=���Cj��	��S�J��tJ���~����Lwf�V$
��4"�~������H�#31#���z	&���������G�Uqx��!����,������g�� ?�52��L���/K��@'k�i������m���3�zw����O�����d�3��p/�����#;�^�}��q��������>eiU/HK����P��
zB%6j	�&�J��E�e�A����/��S�Y0�������j�h���X3Q�6=K��jK�j�l��ng��.�i�F+e��{�x����nl�>X9y��+��x->��S ���ppDa
�\��*�V��Zfd<:���u��S�0D���ZUM�v�#��
�t.�����}�z{uv�����uYP*I���� r��K�L�����x
��+����)TGt<f�&����'����5�fai�m�l��wG*�W	L���<�)kU��
%DH�[��i�?9I\T���I��t�L�J
�����v��R�x�.��&�~�E�	���-�B��ymJ��[,�7��D����sN�����bjnM��2`���y���R9��!��udq v��i�V�X�Be)�|I'+��HvLD����D!�5� ��(8N�\������}��{�>�B�$���E�$�3rXy"C��'3����\�8$r=��C���X�HA�j������LD8:����
���6�.�OB��l�s$t ���$�-l����I{k�bZ�:�wE5�*����|��|�]�$��� �W��V��rV�R�,lR�N�Ic��Qep�o����/����2��1i���0+G�����'�B(q���/*w����:f����4�c��C��mA�����{[q<���-�������?n��f�<zF�MA��EW�J���;��Y��G�����G
+���5JRozw��H{-W��%���G~���%�w{}&{�����l��s��@�ZTf��������"��,���y���+�����5��t�o�����	�J�[�}e�
���wdY���B'�;,���aE����c�1-�E��[�D6�2^��E�)�pq1.%�6M����0G���BS���V����}o1��Y�����W�TviuT.�U���72����QwWl��������~�n����U���{j4��nxdW�r�(������4Sgs�u�;~�3q��I�����_(
���u@�=���7�$��3�����P���e$t�$7�5��`o�p3
��8�&SFE��d�����YN9u�+Ko���>Nu������-�NAE	��]8-]<!:t������X��5c;�2�R}�=��sf�%�]l��n���%�.��gh>���zY�[��P��Fn�L�$�bu?Zg�N&�f�k�rT���9C��������\	��na..��(N�l�Y&g6,W���$,���H|7d+�;�����o��t��\fD��T������ATe��/P�� N�1Y}0�)����B�9p#[Qi����n�~R-0#��b��D���t��:|����sr������l��(��m�=����
����a��=F+8q����'RO���X�������������3�akT����h0��x��phO����b��\�����Ls��Y������u�fF���4��}(�����?=���������)��_�5����Uj_O��8e;���V-�B0�����#+\��f�I(a��Q<���F3Z0��#:g��9B�P����B���*w��m�|3|�����.���D�z"����?t|f��gqO������qr[���m2��8�q�Lte;)U��
cC9i��YN������e���g����w�8��
����0��C�c�������r������y���n��U����S�@�)�T$l�{�P!����*3�a$�����C�U�Q4��f�lV@�@]Q*=��&O��8���4r6����hXkP�Q��-A}'��v,��9Y��y(��u{��=��[�a��'*�	�U�����S�kg��\�>���:�F�b�����{p:���1x���f��+]f��!=�6d������0�g��d�������2i�=�u�Bg6�X]&a[�Eyw/��I���E8D�N���R�<�E	���h�����Nd8�l�^	v$Hg���jr$i������-d#[M���o�8�1���*���Y���]�C��k+��5�1�����t�� �O�f��D�k\"G�;���ci�����%�]&��/MWwJM�W��U&6D�!������[k%0��H��Y&��Va��y���W���l)�P�	w�0c*��q��O�����;��!���n�c�Yo(�7���h��������\����
�4<m�*3b���E���^w^��/���Z�����{�y�F��8X,�����$�I*��1������D3y��e����U��9���x��gL�\��lye)�4:.������i�o0���-�r��F�}��T�}������Jb��f�oUz�h"��������,���PL��J�8*��r|1���/7���su�d���F�U6�n'�9
�����I�� ��������/��rB�>��g���A�Y>�x��
��+jI�����W���TN+"hqY��lV��r���A�
B)23)��W�/��g���^��;gv]��
��s�����}��8��*?*ki�W[��TA��CJ��������a��!}<]�����w�M��Z�y`��u���?8��DO&�Q0��(�������Z��rc�������~�����������n^��#-�7�9_pf�d��'�T������I����<�S��E�������^����t����!���)����Rl��;��e��]�0�L��������y����#`�9��c�4=�O5YmJ��-��E4|$_|���Oo�]������VM9��h�x|O{JV!�+�X����]�Z��dL=�����6_&
�/zsY�������.��V����_��K"���{�|�`��!���w�j������,���b���*��b����6`��^�����m�;A\��@-�����o�Ey�^�E�� ���^Uc���V�lS�p�^����=�
�uk�����:�Z]�v+��v�,� ��XJ����t1yfP}`Zx�Ki��?��B ����,�w(���m4Z��I�*�~��{!PVRR������mm\Y����)��c[2l'v��y8vO:���T@�%�Z%�N�������.]����3�����]��e������S7<R�
��^��Y$����~�aF��������>��o���Yw:ac����B<ul�Q<^9�����'|\��=T<B��"��4��_���{��-a���+p)pO4f�h;I����y�&Hr4I�^�5'A�D8$GW��]���n���f�F����{Y�8�Fw:�}Aa�;�i�Z���_��I�/M���%^{Qm��R��.kc�����3s���{�����P�S#lK��=��}��>e�H�]�p6�__�^+�%~H�-H������f��1��va6Ptn)=��M/�\��($��]��P"oC�����J�������|>����[��{���&\>�;�����;99:Qi����h�$�Fn�f�����4(/w�dAA�@L�_�{���]J��=����=O�
�G.E@���XhL��X��B*��o��=6|�zK��k��3?��t�
���<dq�6a�7��y�N2(�w[���VB_�����e�@��tfB����nT�3�����_$���	,5k��?�t����[��E\�|�Y^*�k|������Q�t=��}������2�w^e�(g�X�*lf��!���_���xJ�
�������fx1��8��~QZ�����y�5p�����t�QZ���f���H�c��G�� �E�U�s>A���3���YS�f4���a����������Y�a�Dg���H�2�����������t(�5=]XH����.�����<�XN~@�n6��
����=�4��%l�;<�;�'4������!Jw���L{��f1�.c�5c��3�up/�l����K��N��;�}=I���!�VkS�V���hJ!Hy�l�&k��]���t�K�y7��mg�@������w�g�}�1���}D����>1�H4�z��$)����D�}�|YC���*���.q�*�x�~=L��(�1k�B�a{�do�,�59j�}�9�?>���<~�~��}���������x}���@g��������^a�+�eQY�/�l��.��h���M���p���.�*$�`���Fx	��6���-�Bkk�������jP����<��<�7�#��m@��<���2�I&/0?�Q�R%�����2�{���?�ECI'^��lV�$jO����?t}Eb��	��������]���Wj�K0$�k�����0I�c�=�M�|�_��5�v��^A��x3�$|�^�Og'q,j������.�0���|a���D��DXh��L&A��0��w~F����K�{���G���n��kcQm��W
c��S��{;�_b�b�A�����������e%=oI�{���'@2�gY����i�c�����h����&�H:��(Ve������b�����XX�
�(�����zp�#H���������v�x9V���A�������=����d������dz���v�"���.������5Y{�21i��C	���|�lT����n'������K	xZt�`�Wx�A�����2"W���+�����p*�Hd{���M�<���|��+7��S�������{h|�P�L��
/�Rn��]��_�ZCT������hXeh` ���}��� N��X'w��wqXF�C1�}���9���%��b�
�P��eFd�
�{�	�a�"�Q�SF�<���	)������8�H�=�r~7��Q|�-SVc�>���/}4��P1:�EH}0����%�S5���%���$��>����F���N� C%z0�s�I71�Z�}�����L�����L�4�|���ih=P�R�3���+\z��G&��P��P]a����"D����z���1"�����*<'NP�z|h|��i{+��v����h����������z2f+�K���1e��\t��8
�'����K��x�%�	�������"
��U����g���2�*"i::bLE��!�RAT���CQ��G�\4��D	�&�����h�FG��Qt�����37����(���U��5�Q"��.V�T���G?�.�����I��I������t��+����9���9���l�wr,k\8!U�nu���to�����3Z��_s9��Kn�r�%1SN��'kj	xh����92�[��W�����5��������+��W�����r]m_k%c~6��GN�Ql2O%���D����������9Ja�E�;j��E�W!���OJ#b�8��6�)`��h��J�`��X�'�b�!��9���9��s(|����&x$H^�G�3�����#��S�1�m�;uI���2�`�A�)����M�����9�p�(�b���f@�M)F���e?�������f�`�`7-���������[��-	s�='�i,�D/	�W�D'Mz��~0��$5%6�����QM�h``LV���1���?a��.I����H�����R�<n�ZS'�z>�
XA�a0L�O���r���K�U6X�$�~!�A����q���\�)]��t��I�U����1�/RL�	��D���G$x����M��>f<7e��'j��)��$3�C/=:�`��{��q?'"H���0�������f8B,�4�U���o�#����ax@Fk�������x�s���'_W��w��ZUi�n�o*4��>��;����G�m\o.�r��J�t%B���OYv�����4�F���_��J"�e�n���_]��m�q4��VF���������
����IO�e�d����|z���!O602
����bR��Y�'ne��A�R��.��v��������"K��<��l�Y���}v�%�Iw���<���4
����0���N�2~]:�|!������9h@�����t���_bIn��Ix�7�����_�<~bW�u��}`8�b�b��EE�D���R<K�]�d����&�L?�?�����o3��%��1�)�$SH;����XYq#P��[N��:�}�7-Yu���)��j���0(�_wg(�r��8kh�[�DY�@vH��F<7GU����@�'����:z�|k�rV9O�A����M�\z c�����&����Y�%������bx�V.�#����8����%�y���JNQ��HCA����N���tc��}����gsQ{c]����������y���1c��������=�����1�-�����Q�U\F��"�>��C
��	v�6�#b��6iZ�����"��Z�����a���j�������JL@2�������������G8M�VS��a�r�������	��RP�+��~!����}��{ �^���o��f.���RN����!��oz
��*H��~��qb�!��0�-��9�x1���7��h��#B!���/��n�_= p���
r\�B����c�[��d`s�c[������2C�����>V�����9?%��������	#~;����%6!�g��#�i4����FE3����0�H�'[�W��	y�QT��6sT�����D�!�I&fu4Fdh�(���zo��c��9�e�*i�OL[���Q�
���� �m$x�;i�$�b)$W����Q�n����3Z�
D�n��`�P��&�9J�%@�gOI��g�<a�3�7S�����9��������b.H�b_3Sk����Y����.qj�}t
��
	�yPgA	z�
(<D����R,Jb�#	B�|7�
|����
���$O�wq���1������HPvgW��eZf
��3���J�������=�.�������}����w�BmG�;��)1������j��+h/�i�C� ���y����������l��w�w��s���s:��6�����O��N+���V�+@��y&
s����-+����su�\�X�\"&$S4u�����;\��lR]�F�x0����<;s�t�m�4{
���n���?�()�"BF�F���F����bt���U�n�������-A0��������8�#g���)h�V��-���|A�/O�'e@
����sR7�t�����������bbF-��	'�#��_
�G��������~,>���;$`���Nk*�j��l��Fh�i����R��������"���2�\�v��� ��$ZS&����R��
KH��6�<�-���R8)�a����c>=�Tz���ND��u��Fs���v�	oa��=^��0$]Y����af��
6DbH,�(�o��!����O	2.5�d��O"�U^P�����^�|B1Ot�}G���O-?a�&�F'����B3�H��8����=k�Z� 1$IK���d:���d���up��~:gfZ�b����X0�X���#��U7r� (�E_R3	{�-ad�P���'	�rU�O�<�d��SL���W,��:m���f��v�9�y�?�����^�?p7���~�W�`��4� /
�sZ��!X�:o��e/���g7�^�^j���$o����s�j'p�	{���zZO��!��{��N#���'/EL7s'�CQ\Q�)#��H��y������s�.vgn�����-���ol<;�]�����9�I�5G�qI>�+}��)�"�s|��`��i��E���0)�l��i�X��SN���HM��,z?��p�qP�t�_	6y�o_�A�/�:�?�6
��d�@u�������S��
���������r/���'�������!�� V�`�A�R4���j������W?l��tF�8� ���ml|��Q���.��f/��9��cr���v?ja���c2������E[����%�-�a� xJ��T����;<�����P;�����>���V��i�=�s���G�n�����ou��Rm�t�����"���"���(�TMJ��K��_��H�y��~�9LK�-����Z������u:O~���0rN���������& �|p�SV<�\zV:��%#
3�5�u��8�q	R��������F�1�@��~%yLM�$������6t\
A���#��M�������G��P�	�cT��2�I�
�����\0!2��PZ�`�U���7H�#* i�.�po��8�����t]%}����PN�;\[���/��Lsv���8Fa����6��YY������c;+GYA�e���G�*n!�!��[�h���7�_����j�y1��H8����WN�q4�K|��mO���@4]��+��9�J)�l��O�J|�p'J�c��6�	���q������x��n3y�����<z�MZP���8H�[Lvq����������* :r���aN@���e'��0�!c�2�qp�P���lD{���c��o���k��-�Y����6p�.3jbV���L���(��)�9� ��q��Y?S��/�����q/���d�j2|�<�[�t�n���T�w4�������|�4"PK��%������$�������-q�q�V���{4���a��;�nU�ObH�V�;4k|���|������;e
�u�R��d���6.��5�rK��� �|��p>�W�N��|���T��g,p��wg�U��,�g`0:�;!o��6:��;���^A����!<�@�2h�c�[{P"��)�oH(;���_����� �MUS�����������o�L��T�'�����3&2�
� '@��}���^������C�Sc���@���^���l43��$��Q�\�)�������A�a������HJ��J����n����a�:��mxq�<u�>�S��zA:�5��;�0��_�k}��k�w�kz����1�E��o����0h&+�B������1��9r��1���4�JY�$9��(��i��)z�J�x����~y����^5���"����n~��`�l�z����t�������i�\h=*p��M�J��\���{i���Z1�������n���w�"o��m���K�����C����z^����s�v)dp*�`4]8c�V��k��UB�����ne#��A-`���]��W:���S�t����������������W��;���������N���5�__���Uz&l���7����N+_A����c���/��p��}���'w���z�e�l;Z�v�H����d���7c�%\�$�SfU���L5�P���1�^������0P�}��w�c���1�'�|VgO��O���'��~�}�gIQ��M<`	4~�C�T]9{�����@<;G?����	�)]Z���y�������������g�G��-��x���O�1��ID����L�����������`�p�y��&'����<�K�r�lZ�`��N�����	�N�&'H�X9��FK�Fwxtt�	R��{d����g;o�_m����1�b��x�d�����	L���^��d����d�M�<{}�!�����������\=�����J��a%��w(�y}�Cyk.8���������E���V��:;W�G�j�W�8g��8�������'a�#�I"�����-�r8��������0��Db������������������Gg�(���F��s���>����`D6�mV�����P�����f�=�9���6���t�e�jI�w�O7�Q5��
	�����g
����E��3���c_�)���`��������n�9���"Wcf�u�$��V�@%�,
�7�&l�V�SGm>�UI�_�F����(-K���(1��O����������$G�:nA9�%X�c�T�;�4C����664��1zs&%<�T��8��'�?�$+��O�M��1�sib�@�u�o&���g0���Vt��B>j�rQ��������qm�9���F��(}����������l��5ri�Z��+\�e�m6/���f��X������_�cl�t_�([K������ t�$�g����\>l��m��~���6��t�������CS��������r�g>s��c�����8#2�&0�r#�$n�n����_Lg(�7r�=Nr�+��_��$�T����i�;��N"���q�b�b�~��1A�U�rE����)g2T0?~��<�F���)�m'�Y��mYh:4	�JS�^�D�
�S47��-���p���%;+�ta����������+�o_�3��Y����J6G��l�9O�h�n<��Sk������c9G��N�=����}��H�z���.�2|��h��c	�`8��E�,�#�BU��Q��'���l����%]8��!��-Gl����X�-N{G���i��,{9����x�y�6[V�d:%x?
��~���W��@�9�:�V����!���p*�`���,M�EmJz�������]�����+�/����_�8jR��G�r`�����g�[Y�8���^x��e|�tO�so�7v�{b9)���t�%��"S�����p�C{g�"�R���v���+�T��M����av���f�KD�E4D�@�)/N�������a6��"D����4:�H�G���DS��Y�,=���������[qK9y}����{����q�R�"�?����:�w�����xw�l��3Z����6���r��ef3��\l6�3��J`�Z0-UQ���$���}l������YK$�y��ug�a�*�8��:��)�^��pP30BAW�wA��9�m�U�^�h�O���J���
���w���/1g��'�C��C�=\Q�S����Hl5Q=�����r#��d�0��9�0�2����s��kGi7
�����9���f�p'�	0�W%,b�����9;>����W~7>U.��iR���$^I(z���2uks.��q��|���8)���
wUy��9}���
�A��G��>�N�0/���,&�rl}:�,��"S��M9���w3=�Up���O8�b�5}a���<�3I{W���d�C���2PF��	_P�����F��H�:�%�n�:�����;�����M61	�����6����w�tH�9��&���wP� �^2������I�
&]6��q�Z YPH�W�M)X8T8��������E�pinz_��y��K��	0�'E#��|������V��=8�6��TE�p�&�#���Z&������	�6���Q`z?��p��b|���K�[3��*s1�5X �� <��(��d�KT~��-b�&t(s�
n����:����}���j+������Y�!���8.���|��<���x?����QC�E�+R������b��9)J~v�����l���LJ��A=@�{�w� _��q�9y�����c�\�b�25�{�m���W4�9�yeX5�f��C��s\���@<U�4��&$�"�4&|A�l�b�5�a�2�1/�N:"^�T�8��qN�z���!�c�~n�Q��-�
������q�W#��j�?���K�_�-u"�I�BP��.�e$������<�\8���)2������sc��f���	D�k����[����E�U�]0-"r�nE��q���i���������������t�U}$d�P�i���y�i��RL)k6�������e�.m.�{5����&Q��q���1s��c��Os������E���:7�Z&}�AK�/.���Le��
���u	�����d���Y���]������.�0.���/���{G'�{'�W�_�6������k�'#D�Z����[�lq�	�}��&�7d�3���m�g�X}�����n�D��20/A������IX����;���������b��TY3�"���t(���}��c8��z}���5��?��4�����_�����F(��1�UK ��3��F�8<-�I��>��p
6V1�0�QND�2c~C���8���)���Tn�J�S��e*�����6^������P�4�`�C_r���h&���zy����X��Wfe�Ag��}Z������'��
����l�{r<��T~%�����C����*�)���`!BJ�RWZr���E�K���z������m������9G��E���Zzf�;>�}������s	{�^�^�?�&cw��7�+�Vn��n��g�/w�pu�/c����b,S�+r\�&�A�U�dA~2��3U-(����,)��x�H�A�:�����xBu9�����X����E��5����P�.������0�]|!��r<�fWU����P�\AYxV�5y����0�h����a8���"����[n�$�l��8����AAa��bVF��6�&=��V\�$�z��>�I����4��~����������5�C~���u*h3�vZQW����m3�����RD�K4��ym�ay��B�����'���������J�	Y7������'hv���#�d�-t2����8��t�!s��x3����'7\��(����a��%=�m�+�R��K�>��f����M�&Z�����*$�������[���;��*�J��P2�O��1��<�&�#m��6�#�7'�2�����JB��4���G'g��oI������
5
sr�������������$h����������e�P!������������a�x�G'Ku$�*��2Y]HG�[��dV,V�%\���Arg�h�p�&�N>�9�p��q��V����G:i�o#�����
.��d�=�
~���4�f��Q����A
�(`����7��^y�������RrW����TH�x��d�� 4F��##��<���$�����f3J�.5��+���EOZaPM#Z����v��)��Rj�&p���QS���	�����+l8-;�yE�J�������� ��2s�{xBe�=I��c�EF�|�u/��|��K���a_r�f�E���$g���:�e-�9�����rAF�#��*?��	]]��V��bW�C"��<�
W�mg �,	��(�F��5S��R�b�2�:���P���r�
�q�e����37��Q,3r����x��!x?���>�<����������������_p{����S�&kb#��!D�t�i/��{�O=~����+���o�`���r���|��X���\�������Y���C4vA��%@��Q7x_����M������y���$��������=~�M�_���(�Y�u���yN����6Q�������H�>���KM��[�.�X��1'TZ��O���zT]
8�9�.�w7A9GS�^gF��Fowi�����_��e�A�%�8�����!�Ff�;��L�_�E�8M(%�.�y������e���@���[�c��^V���6�i7��\�[���&���E��}�p�LK3�n1<�)������`�7�WwB!��~6H���
��E���W�"�f-�9c��l/�t����}������]�a�������������*}(J�����o�iE���A��DX�(�x��������I,�x���iV:�t���s +Q
����s�'�F�ZJx�]���J������	�x��L���1��=���Hv�����o�����1��{SM��q������k2�)���t�<i2��|���-�������������|��P��,Z �w��%D����9���_s���L�@w��Ox/{0:.q��Q	��S
���N�����e���j ���r�(�]������ZQ��,@���"v���?I?e%���]�����CY�D�8>B�y=Fo���z+"7������C�b2\�2�3�7>��!��3������b��w��]_6T��<���:��[�$-��������"+������/�^������C�Y6�R��k��e� rE=�@�e���K�/!]�/\�����eE��_p91!�����m*
���+�,'����rB8S��H}BnR���C�<
<����l���������s|�t���"t�u�BtV^t�J�E���Q������>O��YCs��S`L��Ksh���?�R��<�Z+�aI���&����:�d�>n7&�/�<u���}6��7����"�I��"��d�5;�}���k�"���1G����-0�n:��^���j�;�/���9���c�N~�uI�����%����x��^7�,.��^
�������x�f=���[��J�QN"��|�"��:])��&�^I#G�|*���B���3��� �z"mYy����O���_$z�����9��HXH����B�"b�)y��`�;?����9���lP�oX�p��RA��������N4�Q�J=G�%1h��Ln
��~�~��%�cR���9���#�H�_���C�0���K���@3��@���<�>���=]�x�������M� �hQ��p[=����|G�Z��.�����g����WcwZ��U��c|�P��Rc��lRq:���|�Uw��7+I�z�[F������It^�[3��tT���'[�Z�{����g�F�0S`��pf��$��%��G$Wp�)���%�_z����I0D��q=#JW���QJ���d0v�[��OCb0|�Z>E�Gt])�Y�2.]4'~�������<^���4���_�+3��^���x���d.B[P��&�����A�2��t,^W��w������@�U�O�#�L�4vd�p	|@5��#�"/�V ��*9��y7�!d�nk�X��!�����8���-
�^�f�z��&��I�O1���i�F�b4
Z.[��l���O����-�F�e�>m�K}B��e�9���x��S��`�8�p[�-���oHz
� ����J1D�s~4�c�l�����:��/VNX����|�
��iR�2��r��Az�v�m��/�E"��}���.I��3���Vr��}��k��C�#~g�-��3����D���*�!�m|���{1sC�"��W��A�D�*.�~�a#w��� JL%�{E��vO4[0�-B������1���MFI!I��Q=����������p�G,�DZ��[��?&�VS3q���CS:��R���8�����"�
p��� ��������s>.�<%��q
,�]8�(����;�3A��0f�D��Vj���8�.g��>��i��������$��E�,�I�x��(��s���>z������������a~����O����l�D|�����q76M�K�_�|��s��f�������}��z���)���@��|e�&oCF��M%�e:�����3 �TD}H�H*�.��9�F�:�����W���S�����o�^�a�D8'�HAr+2�K��|-��E��p\R^�T��t$��
�R�&�%l4�SlA#�����X&2D���5�����1I:�_J����������2���+���������$�ik���w�&'�I	W�
�����BM�b�1�Y�&�Oi3��"yw�?�����.U$b#^�;i��j�S������5;��z��?)�|�<���r>�����c�7jcj��32j����adm`��x�[�,7����o�\����
�"M��T�By_O��Z��U=.�E����h�?��7�NJe�
�r�`�o�/;��v��^,Y��>��~��~GN��I��/��Yz��+N���T��J P^c��he�d��Lb5L��'io�#���	E��^�����7c=����X�).B	N����pV��nU�Ow����HDK���LV�~O���/��,I��T��^��FA����#�D�m�%E��w������_��t�����n�8���0d��q�	�d�O����@;aM����O5���$����������&G	.��$��^�Rvt��qG��A�&x�����&kK�p���h�u�Zp�p���Q���O�������5��-���%�(����h.|
(��)���7�v�������h�4�u�3
&�EB9R����V�h��p�d-}������L�~rU�?=���+n{2�mC���a0n�}�i�h���[�8�J�����_�0e��K��R����J��6�!�#>��d��n�����V#8K.�R�n�����4=�&�Cs�<��0Q��a��i����N��N��g��(����Y2��aR����R��jMT�� _��Y���T��/
$�?��Pl��
/�X���7�W����{d82����Q��i�������osrT�8����/��/�W�,�����eOUxV����Kk��w;1
(�_S	>���S��=(u����|��~'��'}}����e���OKYs5��M��!U+�l����
��b��������TK}I*l��xK"�����v�[A_=������\���,��[o����l[W���p##�T�-������\�{�O�J��5�j�@�@�a1!�wF��(-c���]Q�
�����1v�����pYY�tF�0�rf���n��S��1T0���,2����g����G�E�J<�F��,;�U���t���y��#(ME*S��`�B��F�������	���I��mo=8|
������PC}�eX�@����`a�,x�p�|������:�s�w�O���(��cX��y������5��1�N��{�_��t��t��Xd]"�������k;�����b���:2K��<��z���~��Jm�4��8a����o��6&��y�=��4(�
�������T�`��5z��������r��q��#9	�S�{:4L�O����ee�1v��qH?�����6���H��A,8�;!h�<~����'g�V���xjjgp�aZ&;'{���j������&��p������
���������h�h��
Ad�N�[����Y�=�"
��-��vN����{�������������6H�s����m��v�N��)U`=+�\�{h7Jq���gFMW����,�w����nep/Z&�7M:p������&Y�����P���$+_�8+C�|RoX����x������������Cg�����;�z��X�}���U�r��
1�N��i�p���^Sx:f��������ir!�;�"I����Y���0���T��y�@����t�����}G���M��v�~M��k��d��J�g4J���?)>['��H����8����W�T���^���'(<��O��>q���������K���y�d�"��!	��\�gOQ��'��5��e�	_��+��bk����������m�O	���`:q��/�)�)���k`#�M���sy{�.�R�)���:R����9�iF��4��Z����eDWL6X$����PTi�
Q��J����P�����0�(&�T��/���W\�$w_0�P���"
�2�VB;~��7

X������s��k����(T�4=7R�'K6�`�XrB��-������n+��X����+��fH�y�K5�]���pZ�����H��j@���+=�Nw:\?��?��?�D��$H�k5F�8��?����l�"<����`Qd]���.�yF$�TX�^����'{�TT����[���`S�i�����r*	��*K��MKK��n��X�r�W%N�,G7�cmik}�&*��dtwj��������"p�4�!���3 T��b|�b���]#�J����!H@��:��J����%�����00��5���M�-a�r�%��J$�J��}�����D�����"\[mT�w	Y��h���5S����w|c�1��F\�2��6�������\@m���+~V1t8Q�����@���8��t�����S�h����v�-�|�
�/����������w�T�K�����-u&�,��Q@p:�a��������}D�-�����.����f����/��@x)}O�h�E2�'V'"Qp�P����hd�N�k�H�#�9 ��@�Gh�
����F�#D��p5��.������5=�8	���L)O��l>E nS6�[������5�r��)ByX $��:�!�[c���O��a�]���
H=$^��x2���[f����0�^�w�w�-�L3l��pA��1w��3�[���4����T���kB)[[F�����j2�H����b�C)&�F�Nv��1��&T�R��1T��?��a
"uXF��������4��I+�����
�r�=0����Z�W#O������M��V���]�?�@���{��V"���S�:����XZ�����L<������X�w~�ZE���\+,^L�a��Q���G��B�x~X�O[F�qh����I{�����?^�3�c�'Dz�&;}.>_�r�����Y{,?zK�3��md���(�j��}��T����Q(������������6�k#4��7�S��������U�b��$���Oj�R��u����{/���,	j���������b]����������"��/�\n]^Xs=���z��_����s���>���������t������������}��B�����R&��49���h��B���>� v�@:��g�������?��X���Du��G6����:��{��e}2*V8�����`��������M4�����!R��G�Rej�IV��XY�P6d^T��l2wZ
�sK�fe��`���o�����M'��]��2^%{�q������y��O��"s�w�Kt/]d�;��^��C�S�w�e�n����Dw�������F���7�kft��}��QR�4F�����`���=��%�R�?��8��n^���c��7�x-�x��/�F�t��??{D?�N����c��S��-��!�4�����~6��\���`��_rU�w�5{�QW\O~�>y�{r���HD�%�#Ywr������y�5�]#�����6Z�q[��[����s�����@�/���jJ����w�R�u��s��
���8���_v�����qh�-a����S�� ��0z��c4j��cf�6[ W0�
Er��0�%m��`h���fa�a�4hb��4���hS(z��Re�����d)����Gw�%�Uf�g*���I����!%������I�al���[�Uq�_[	��~K��[	o�=��������'�)����/��w=�{���eP�&�4,1Hm�j�	�� ������Av����L�y�FZ.�B��m����?
��&�|;n��e,K�c�"�������3��4�8Z�_S�-�����Rzd Lh�Xj�i�B$!�)L��a���<0�z�WD+��v��Qf:'�	u-g��-���������^2]��G�\w���+�hM�n�.���s�N.~��������[E� NI�M:�CB�D��t�������}��E��'�I�<+����|����A����-Jx��y�h�
����Q�d����/��	�����O���jr������%R���@�p��d}�\4����j�h�j���Q�i�4iqmb4���+��/.j�n��c�*�G#����d*#����s&�����~��=����:UJ�A	R���a�rM��;r� 8t��g�u�mp�A���i�����s�t��Y���t���,��UN"k���^U���*�%����'<4�<u����o�+��of\��/�B��=1,���!�|����&���V����������n5�V��5���oh&��^G�z�y�����9��n��n������"��������Z��bx���l��K����
�����Y����!����^��z������x�Y������<�����HSx:����`��q�w��H[��F�4i�?<}�����>������O�{o"���[��]:����`4Wf�f���*X���{Q����uy<���5<(��JX���?Dq�O��e�AUU"�[�I�H����c���J���
.��`�C��qYe�m�Z��$L�������x�!0��l����/\{��mx�
#�������%���<�/g�U'����`�V�����wL:r����������	X]e�����~\(g0�
���(�I����a����~&0�kN���!����}��'���5�8T�����G�����s����bq�a�Y�ql�D����Bw�]s�p��L8�O��D���~k�%,W%��&:�-��t���:��} Er����$�0�2���-;�*D����g�#�+t�����F�*6�t.�}��t�w��������������g���tM�~���=zt��g��r��%Y%��Ca��������#�kv�|����b��n��iFxK6I�6��,�O��7���Z�?�U^H5"�u��tl�&���gL6l!���-+s�h3;?����@Q�-pbi��jX�Rq+`=��
�\���#�LpbSm�{
����PFJ�����2���-��18�j6o���ic�\+�[h�M���;��t=*J��^����C����y�Z�WL
e�R���mu�50�=�������������q��)��kQAg�|u�������w��a6J���x��U�Wy�����I���!�`.0��G��J��	�X]s����]�	���:[��9�9!����]ZSV���,���a�'�7��g<I)�����!G�c�o�o�sv�fbt-����s��je�1j��J=��k�����x�"]8e���$�T�"����$�BZ��G��%����
,(|v��u�c��jD�!����Ij�.�P��xt�����6`�jo[�i�*N����������GP=���Tb�9�S�����[����h�:����]�}�c�����������
�c{����W���gd�����X'�q���W�@}]3Ft��_�6a��m�1X��&��viyyN�����w����x�P�yz�V�]��<&L
�H���T�5�U�BN
���|Tr��:(���4^K�����Do�@	9/z��R�-s�M������C^$��AS>DvSt�����2��6��M�)��dc/��q��U`E�Cg��D�b:�fG�Q��fu�#�r���?GI!gx�"��k�����}�����]�I�w [	Q����CJ����Y���+%�^�eD���r[~n%�-a>x�TLSbO�����V����������B���'��l)��b���v&#^��lWY��b$����'���`������0�}s�������:Id`6�E2c��]�aS$L��D�AG&?U�S#���Fa\��	��q>��'6��Z��H�3���i�j��$���d-�>9����}�xB�����ON��������ZT��2�*��%��b�N-���5�zw2�i</k1���36��f5,���h*����}���z�4C��]�_j+rH�.NZ��7�d�d���L�g�%�3:f���*�ek���m���!��_�U���-/���wHZ4y��l����������!.�i��aK[������A��	`�oG`���5��/���	�A��?��	Y�K�)J��I�9U������������I�x�E	�Hz s������s��8p�{���%k��_�����}�
�B��nv��m��ZI��:�&6��;�I;ah"��	���h�U.�t�@�Rg���I������r�h�I��t����^8Q�����
DE?��'��$��PV@���ld���p��%�%{�M���J������j3-*�PG�\���vMM�j=1e~�B�[�G�������z��:��Y��y;�j�j}P�+lP���gn���Z!��c��ZD�_S�*&GS���o��{�Fh<Q���������u�&�2����qB#+�����M9�;��h��s4�k�]��d��USkI�j��5���'�E�"�������6y7a��1���h�����O�q��@�����l�>�����i~��-��h�^���-��]���M�f^���_V���/Y2�V%\��������8���s�����d�������C��r��+N�_x��%�<7~R]���nI���Z.�%���!�I�-^,�r���8W�<�T/3A{b���rc��]15���`Z3��������u�9U�@K�������0�Uo'�Z7{_E�j���h�Z��5	�"����~<�|�m�����D������L���'U6�$ok��t4-2/R{0��," ��f�kv$��'f��~����b�o�g����l�3��l��6��=\*�MR;t�,����P�����N��[e���sR�������-�-�.g�9)g*��I!H��S�����-���u������"�wS��DFb��
��?�=����S+`SJ�
�OHg���R����fQ��� \�
���e�
�_���D%��qEL���c�i)���%�E�
����0%=���0��K���1X8J����l=�'�9MY�n��R��N�����[�?	�9���D���TW�e�i�IG'���	G�1�pK^R
�1!j���.~�����f	�9;i�5�Q�0�B��s�����Ol��R���0t����5�2��&�*4���5p"��I�e���8�� �W�6����@5���7��!#��j�t(�W$��_%����������p����������g�����}@����$�!���*K����@�c	Ew������l��{����/3.K*���P�j]��3�Ci�d�������H���x���?���JoJ��LxH*��#4$��.q�y2\go$Y4}�&�����*�|���a�P;�E*u��F�p����N����x��������D�����`�P8Z���m�-�~z]c�;u������z���6��s�[���'�E8A��L*5�%3pE��r %B�)���M����XK&%� Z���$� ���hb�����$WRtAq�8G���Kw��=\<B����
����w��OC�5f���1���Q�)�����;�����=]�a!���� ���x���#y������j*rUQ'��>\1�Y���2����&)�e���UE��e3����
\0�tRI���{�x�M^�A�.���?gd$FQ�Q/��>'(?���!�������=��r���V���g<6����d�a�_��D7���n�=��m��X�<���Y��W�(`I�X�N����
�@/�L/n�@���4uQ{A�����L����oS3YE���V�{����8K��%L��
S������`�f'���p�����eB��s��O�N�6��n��m�����1n���4�P����O�Di� $kH
vR��>SJ��%7H��<"6�.�r�hnll���t��<o����
td�������7�7+�M��k�E.G��q1$-�V&R�ca�$�=��?�%���]��h�������)�4JE��#\Q�"�!P�?�;:��;i�z��5�g�����=9?�>h�F��7��\�!o�
:����"�9z�n�p����@����{;���rQ���B`[��F�ArQ����3
���i��tW/4����������j��7���E�gmU&c��I�������DNh��`y�k&/^��8�*��Az��������G����Q�!����w�a?}��j'�@R�w)g���vF�_��f��zVF�(���tc��%�~��E2s_����������1�$���/P����~�,rvh���J�>�!uV2�������i��I�:�{H���i9,���d�vI�S[���(�C�_'p��-
4��u�a=�]��;�
���`�����=wj��{�j����iX���#a��C��!���GNG���JF�m����>_
g��	?)��m%�w����}#��V��l��>���IZ�,�t���<�wc6�U����;g�����kkE@����1~����s��L���{��I��9oJ�{+�B�����i��d�z�?_`����(�LG�C+���t��0��'��~H�n���c��-���f�!,�9�|���gJX��\\�*�p����U!�9��~��X���_����C��U���U���������^������H�>~b�l	5
A�ho�t�	��Z��~��sW�����<�T�;��p2��n8�7�^]���ED�����Z��"HwN1���y��4ZZ�p��W�i��#v���fi�tP�p8��Zz��(:K�F�����[�d�������j�4��9S��5]��L�� C��"���+_�
��^<I�#��b�����"�@���$��<0��u>���z����_�����;E�����e������.�*K�@�%9C�����,)��T#o������=2�-���"���������B
X5K���-F@h�8���D�97������hy���?����t�$���������DN=w�����8���S1�/�����jj��,���[�=�
����[QG�K���G6/$W-Y9Z>T�s��^rv�}z&"��-��E =i��������"�M�k��gE�t2i��������C�~h����'X�������j��p�������\��<��������vou��,n>w(������m8�-����Ae_�E9$���L=�'x�u���n���9;XYA\�;A�\���h�l��d�ha7�����2�9�E����C�.U���-��6�y�K�W�6�e�}[��u��xO�V�
�2�z:)�d��dd4i��<i'�������W�����/��F-&`*'���Gsl��M����f]HV�}=nf����F������6��������v���DS�-Y���5fg�=��#2�E���uip�p�9tn�����S����9�ma���]!��,����_�o�v��b�Y3��6����_[t.����h������h+��vj���G������v����%	hi��(RT�&k��}%���=i<B�E���"�1���
5+gt�k�G���%R$v�1�\�pF�02�8��v:����;U(�$�.��];����;��gA�����_���8��jp�Z��0�|:DJc���y��+fXU)cc�.X�Z;\��c}���kYs�\(��f����������[a�9��A�VBN4�m��������i�#D������(r�8d�F�u�-{��n�h��)�W�M�rD�!�8P�j�!�zG�dV���Jb��R J�����&�C;����<�Z���Y��m�It�3��RQ��4�=_j5_a�o|���Is��`Mt"7���V����B^�F�4��#��is7�.i7���LW*��7��M=Fa?���][���9`�����=����cR��X�W��� �pOa=�t�l���������}���i��������C ��v��<����e�!���t���u��_��YU��)~����:#Y��W����V��Ky*,���lD?������~ct[�m�?����MZw��)��n�\^-T�;�����%������Fl�n PSf���v[C��a���l�m�����Y7����)#��6@�cl.z����������^��-~5��a��"F��}�0���a��p+N���VQ������-��7vsw���`��X�����=���
�[w�������nNi	��.�b����y�k���~���
c�j����
J�?v������f1E�����q��(�5��>W-JNa9S]�o���h�3�&3\���1���^{�Yk�@���`����+p�]�P>��kD,w�
{�yL%�����"����?��d��E�����Y
}9��5�������r�D�m��0c���_3�r�E+�;��%�������5S�e�c���=��?gj�j9�T���c���X�������K)��u`zEVb(�Ff���-�";O&���{pz(}a����;WHt3*�%����}��UR�t�.QA��a.kb�Y5/�jU��^d�"U��W�b8Of�(H�T#y������_���0D#JQ0i��_�D��������p��21�w��s��g�8���d����$b�������k�`�D�h�e����D��"�P=�|���- 0��d��'6�����,�y�(����@��'-	!��B:�(�cD+�Yb~'���0ez��Q�E����^�BR��tGb�C,���z�)�#��1e���a�!������z���q��1�_���>f#��r�:��gv��%�@���f�"���*�tRQz�6qp�	���i$7(����T��Q9�-eH���sq�_�f��D���j��,���@���7��vG�!� 9��5�Y"�B�f���1Q8-[���XN'��R��~�����q�����&��������RF�V<6��j�:tm�p�8�0dvz<�*\@U��J5�T���Qzv�
|<qRL~���O��UK�S.b�G�v%nQ����O=��R,C�Se�O�sG�n�����fS�Ci��t��rY���q��=����^o:�����g���,3<8�7w5�>-P��I���#P�#qY�*������t���i�tP&XI*a���	#���p���M��@���"q���3���L��
������s��
3���0 rF;����g��[��S��-�B$��j���1/���n\�6C�av���rW����b��E��~#X��_���T?���-��|WCd������D���v**���D���i�����g�Pe����M�jh���l�D��`x�M3jg\�������Y��%�F`��G�)��}K��1���1.�����Dj0����	�f�2�/���&x�T�'�U�����
-�^�?@������Sp���g��ss:���#�u&4.O�5�@�f��0���Z����>���C�tx����(�\$�5�
��D6��U�������`00��B��5�z�.)7��F�g8�	�)��u��t��~���+P^�'��HT��l0�gH��������oe�����\���)-�Z�����+���{4�
J{����c!_E%����D��+:K���DGX���N���{�S���/Q��k��X{��tE�C%k����tHKj��-���Z��E7�����xE'm��8�?d�T6��&���O�u�.XD���	%���L������H��u$��������18�^���$V���{��0H����O��/�����������x�%9��<��wg����;�1��cL��Z�~���|F	�*bdF�A�z���a�W!�a�i����i;���|+8����e[��T����A���\?(g�}>�
HQ�A�z��zB�X�9�
����(}�	�+e&v�������r(���5�P�����}w��x�v(�wH)/W�cc(53k�{���C�rL��>��� s1j��w���a�x��fx?��f�^9��������������0�t���:I[\�+f���t|�������o�����]�����O2<�K�9����6������j��*��?�cBo���c��)�zQm��Q[�$�wKk~�}���ft�������L���Q��p�A;_�p�td����f*��G4�~iX��]D�n�dmfX�]�\�;i�;�S]+<d����AH����������B�����e�$����*C��2m,���.	 _y�^e\�V�B&����0�){��g� l]L����%�Vj������d>������2o���j�l�w����3��pH�$��D�x�8���JL��F�l*&���j��2�-&���2pS+�,�[5h�?�q�.����O�����-���z�X��WFe(�x�V��8�\�YL y�����q�%������~][����c��/��	������
������0������"��Gmm���f�E��>�[�O ��A��cP���Z����(�� ���P�OH�$MO��\�
��[��'LV`F��l��[a��d��.G0�Tx��R�������qG��]C>�� ��>J�Q�q�f%��@	(3���l���c�N��QG��2�8Pj���[�x��A���z��6��p�VU���T�����U��zevc4I�X�o�T���������,c��)N�i/@�_��W���(|I_��g�O _J�N��M�l��1,.6;���9����yU*�z����=�$lN���&\�X���DS	����*dPA��ly?���?���s�,�{���9f�������IvV�w���8��o%}���f��$z���Q]\��c��v�����$��J`t-�z i1���B5�VP�������7��go!�r�I�M5g��G��e69+�j �K� ���!R'��J��.��(�=o�+7������:bx���o��5�~^e���q�b���<�A���2�vl��C��Q��GX�*�A6����1�Y�/�6nK����z�]�Fg	���������w�'�w[	���o;a�CJ��2F�0EYw^r��+�9���P?K��I��R��E��f y>�Z4�G��:��O�7�����_v.����%a+~f�S���t=NK���/���(evKR6��(.��ow�:��Um��RM8��b������l��t��b[I�yl��mU�'/5���x1L�
�f"��*���Dv�
���!Vta�8����-S1{'H�f��3����+��a�#F����%��m�+"�����L �6����������*�A@~������&�D� ��Kl�����96~��`'oJ���z����j��FU�3<S��Fd/��0���ax�}�H{fkm�������x�w��������X��I���&�!��C�.��c�G`Vn���Y�;�0����k���mB���!�������W�N��*������^��4�v�|,�V�����.��i�"!��J��.zHVn��$I;�F�!�����o���x���t���:d���pTGs54����q����=����e�����x��r�}��D�Y]pO�h��4T�������c��i����u��U��&��$i2���TG�
��w�����N�(3��@k!�
�y�7-.F(���Ps1��Y����gKV�13��+V��XJ��L�i�,X�n*��$N����Z�yc�!��������>�R�
��	�^�0/0��y'��gX ������h��6H7����&v��6N���7����������LO=KH��f7����*)=q����b:�2c<���#\9���D�f:.3v#L`%I��o���`W>	�ZjC����'	��X���Xo�p���0�w�8ZX���~N���'�MS�6
�'R����.��Bz7.���y�Bz�����O�q�j3�h!Ho�1,��`�NZfm�0�8��Z���Y�}��KX`����1����:�f�mu�����I���:�DU?J����F�T q��������5F]�lh��������	�6�1��R6��������Ig�3?�pd(�����JKA�:�j�i����i��6-}'�&����/
@1����rU�5������U����}P&oA����S&�s����vvv��u�
��/p�����rx�,wD��b�*��~�IX�Ab���$���W��]D�%�
��U�������@��E��<K*�k���(0������l]�{��y��H���s�x�+�v�����:�����E`j������-r�E��������I*_�R��������}���^O������4����k��~Cj��X�d/6��t��a�k]3�'N"p���04�c�a��L�pM�������N&���Lz��ae����F����c+���L��:����i3��m�u���c��y8���������p�g�������r$I�5�N�X�X
C��,R8�����?�����b!���\�Pj��h�M��I�tEj�g}�2'.��!�7��$��yv�m�h\|�1����b�:��5��	�x�k�J�T|�����J�G�?W��.w�#���
�^�9��&�Q����=%�����H��t��=XC�'pM�\�
�R|1����!���`�(�;,�9�]`37|
z-y��C
m\ ���H��lx�����98���FedS\�g�����,?g����9��&rB�3;g��R�[�����`va��L2���m1Dt�,J"�N�/�|}��,�1��#�J�U�|>�)�M<�x�R���.o���i�"����Z$>E���A�J3�A�H��9��
������Xc
(j���HO�,���s)�!4��a��� �'�L���vi�����9_��[c��I���Z�g��S���H;r�7L(U�o���~��x}�P.��q�1�!�Zgi�B����r6g��\������.������x=��M2WU[�����s��4b���WF��5�hK�.D�v$���[����pd�2H��l(�>q(�U���G2�oL��H	C�����.�un��R����H���p��`0:������K���>/<��������%���U����D����g�m�oxw<��y�k�����M:']p�,hD�*�n�6����^��A���|�1T3�c��A���|��dX~���}�e����X�_g:�K�)��8
t[��%�.�yF�s5��04~U,bUkX��s�[ �K*4������R���:�,��v����fN$~�){��X�_�`7Bv��{d�sD=#v���r�\%o,�<s�j�"(����Z���S�3���y+�H�
S)]o�i����A����;a����"�*��AI�7�TtF��FK�"�.�������7W��A\������{����4D���
	��YW:F�[����O� 1��d,J��Pzb>���V�T;�A6��:��,@���=$�8�8�n���$�JP��8�P�$*%c�/I�j�E�5_�� �����TC���xMa��q����f���MjL}�2�"I�G>��_x���$�I���F<L��s�����}k�1G���|��������q����bh9��4�?������<��4�N�/�1���@@D�!������]3Sg7���TMK�`�c�)��yC.��L��4_����������7:`R+�dQ����N`p�7�^Z~�����.�i1�-��a��=
z�*��|���KWAX����;�1��j�jM��9��%�p�Xt7�Q�����i�=t���Od���V?A�H�D��(8��~}w�!G�8?m�_�-�1�6]�w����
L#�V���#�QPu������XL���[�5��k��^�Tl��1�b���=i%������N�|��]��[=z0�{oe��!Cu����[��#c/F�-�����;�G��u&�1�2�D�o����1m���_�����uT���s����t��������r�*F8����x�w��g��|�7�0
��#�������knU]�WkK��qm���x�/�]���'����aoj�E�@*%��X�(�Q!i��;(8�z�,s��
Ybd��Xq�|�xu�$(p8$�L��1c��7��"�p$9��>�[��������5���$����;�Jn�o��F(EQ��%+}�V<�M��f�C2���S>2��a�b�Ev��"�����M��'�6y=.U��U��`�w�g�r�#n��X������.�=�����	6.�m������w�	c7��-W�q������)����o3�[���
1��Ln�J�����R��8o����aQ�)EmO��8�=�j]��
�C��q�(*����R3���"��	��`L�"_�i{�v�c:�8v�;U_mp���?&�*�����m��6�{,�@{�N�3�E'��j{�����'o'B��TGN�^	fa��i/��V��v������cP�\���}����RsP�W�����[En
^';Av�u�hd���W<#��}�i����=�c�}�"s�5_�\�%�IU#�_e�����kp7v���h�32M|=�F�P��h����xm�	L�#X;�����$�v$��D�����4s[�A�d@&��G�b?h�Z0x�QKfQ�Q��O���hG�\b����
c����#�7�i�E`���W�E?��Y�eLLMS���%]�X6��Zb���m�K�7���������IOl�I	3��!H��$���?0���E6�JOd/��I��zX���-{�	N�
&��a�����N����'��a7���f���z�]���W!�#=��7�����������h��y�7�B��H�de�H�>N;�}$�Y���'T��Y��g�����?h���e��v����S��b���o�^���"��E���p�0��g���1�
?�k��=9��p)i$2u�x(��S�
T�-������k#9$?
�TM��|��P�d�V��Uc_I02v���U���T���nW'U���������.�4"���\ig~�$��tHI`*�v�n*B.��ec����4o����.�D�	�������E�l*���N��e���9z���5�p����M�~�
�����8L��EsF��w�x/�Fr��*W�D��zJ�z��f��=m��LB�F-�3�&	��iBo�T�p(?���tu����B�K��S7����a�(�F��0V�����T�H'�fx�{t<���P�$�TI�
r6���A�4�\���	��{!���[�=�^h��]]f�f�s���E9K����8_Uf��0Y��0\�c��8�S`Es�B���T"T�L�	�A0�7�c������e>��y0�C�z*w,Y# �$�I��)gr���f	��rU�*5�Fn����V��5���C��$E��2L�0�\�&�N���a%^�Cz��6�D�O��NHe�������F_0��3��:�%|�<_�oG&��7����:��Q
�h�S�p�9�1r��0}4��-�3���
�e�:<��0{F�e�'���]z���cBGPx�U���/��3�ave>��;��:'��Nr�����5�~����/�^?{sV��L	��D#��/���x��!L����	8boq���� ��Jb��o�RH�KVC��Y�>��M|b�2��%�+�4D�9w�6����&��
��oM�j:u������Y��	����\���	k �yQ
�0P���������d&wg����)K���-�1��AyQ��N/A����X{���M����6���i�������.	� A�i\g,6�����}���Yt�s��!��6�V���+U��������>�>�F���j%f3�����1<�KzxS�����Xu����h��@,�+^,@�k�TD�=s���"u�����%3�%-o�beq�^�'?&����rP�y�A�V�����/�J�K�����R��\Y�z���7W(��D�C�G����u�8l����te.w���N���W�3����X�0%R�a30��;��G�y����t�z��0o5��N[�6e��	��R}��l�R5�O�Vriu��l��iQ����{f��y��h+V�:���Qs�����$�w���eUL'��9e���������.	&^_�D�]=6�o�#'��q6J����E�D�4�eXz.�iw�S�n^~������4���o(5���r���ou�o9'�X]�����rws�>���c,z�9r*��������N��C��b0��]��� ������B��<��4��T3�q4���|t�_U�6�r�� ;Qz�*��D���#H&{�s���e��o���/�N]�O��C�o	:�
/��~6��|��0��?�7��	N��*�QA
�p-����L,�Z�R���I�o"�W�m�C
���y$�v'�X�p�q�_6��p���2\8xk/^�-�'�i���\e~J�(��h�%(�1��3��c�������	������c@{�`��
vcy�d[���gp&G��Z��&����������yI[�a�����F:��8���Wk	Tnh�n��D��Rp0p�O��|�w
r��6e��
lT�zM�������k��(]��Z��Bcm�,���E��F>�Xb�}_�!���Z���!�%���%x!���~����������������R�|��tjPF��/��U���#��9��h\��@��Ul�(&��A�"���G'���)�����B�h�����\?I��DK��r��B�F�N���7��,���@�<2�J]���` �4$*���Mg��@
��L��\������'��S�n��!�49�+C��~��]�EC�U�ay����KV�N�u���0�S�h�)���;eC�G��&p��c���'��L]N5�n_��B|
l��j-/�H,���1)$�At�>F+b���Q`��=�5�Fc������C����X���h\h!2cvAE����.�o%dp���Q�����IO�i�cz�������vN����(���#)�]����mu��g��G��!=������2_��Lh�FJ:�����#�y�x=;�/% �FxI�G�`�A�B![�
f-1X8�1����b�u��R��G������WL\�d��"��.��R�dt#����5��Fe6�q��
����M�Q{�do�,���prtx��s��x�p�<~�~��}��������S���>�_���~���
��p�	#��
�vdN)�hFThB5YM(~�y��R��^g���[��T���b��[�]0\9����j���Y���4������"z�|�6W��5��
��=S�[/�������C�W�lME�z���8���K����0��"7�en��B���a�m[��������QhBk���/����m�U���3���d�EZ�:��A�6$�Z�D�&���,|�V��n�5�/�������o���^p[�P
t����U�fY�q�E�2�C*��
+�u����L��5����7�Z�f1�>�C�B�ADv@����u5<X/�pW�+�|��p�L"���HVdP4BC�?���_����^::Sh�o�����L�������1W�����m�������2F�^8�u|Q�XI��=���t���A��e�.6�RS�Q�A~�1���b�4�(
�J^���T���+r������������@3GKrzV���n�I,����<�2y<��9C]_�09�2���y:,�����T����\��s>��eZd���&���v���s���d��������b���'{%�7�d���n�~\�N�|w�eb��y}����A�K���0�/!����k:�R3V���E��Jp������&�x��p�����H�������b�J�8)���Y�u�`	s�G���"T�7v�S�u:[<�����C��SBL��_�r$&�>(#;R1��n�K+�	������x��\c�BL�:�NSB�,#B���8 5��m5?�*�+��|hI��9�MQV�@k�X��1[+s"�D�fS��Lk�x#%�f$�i�H���#4�_��������;10s�X���"a�p��M �j�3���������nl��m�GA�FRm�o�����h����_�I&�0S��s�8�������j�8��Z!g�(�t��}P������;Y��T��n�
����q�{���T6�O��N�S4��.6� ;��R��k]�s���J5��!a8V��"�8�"c�i	�R��"��O:v�J�.�M5� ��3BC�$���8-/�������#R�s���
p��(��a	���:���i��i?y�*'���B�a��������$	`B��S���k4�������|�d[��v�q���1�����N{�������T)-CBn�G�g�x	�j2�F��_��hE�On�m��E)�l����yEL:�1�$�E�S� ��R�	��*�[�T�O�k��4:��h��Q����L��A�Dx�R������PC���]9�ji �m:��L+��VR��cc��\�Wt�����jZ?Z\.�`Q�.�[�AFp_HC������i{���!O6��� ����MQ�7�h==��[	P]"��!I�aA��h��c8r���R1J�!��RKXJ��q��<�[���]S��o�U��l3

M2����K�O��6s��}o��8�������?3��y�
B��
b�yo<r��aqa�c���R�����2�tDo�#q3�.�C�W6���S�n\j������.���O����{�>}�w�>>������s�437W����+�$����X���N�q�
=���>h&
z{�^	N>�j�N�P������^�)OD$o�(:�+owON���#=jU�F_�u;�F+���7)��@*�_P��5�'{��{��PqP�����iQI�<�Wb8�y6B��BT�`��B��0i��c��&�40����>�{���5U�]�?O�k�{B����g��?���K��h����Jej�����W���HvR�������c$��z� �8^��R�����	����}[��y
E#�2��-�0���Xdv�K@��0�<�����=!A���-�CM��*����J�}P���(��5�V����>���`�H+��l�Y�]��-N��7��5&�r�����/e�7Uw�VC#��}H[9���T���������:���~�q/^d��5�XbOy���5����t����o[�k0Y�s������������
-�rVk��e7�S�^�J������-g/[i�������7+�"��������A�)�d��������L����s��`*yI�
��o�col5��X�����"�%���f�u��%��������&����=7�h�K�%�3�(���b����i�_c��z2��([��w��C��>'�o's���2�6�����K�F
�V�):���[������wA�����e8$�L<y��5[����N������;�]��1��7����,��?h�}�+(����-\d$�����:�
yL��5�n�t3�(p���]�J�x��i��"~(]��g�5V�\�)��������\�.h�-%@C�������r�>���kC�� ���jC�Vv
�����������l���"�����������%n�D�3���c��B��2���J*,ea��v�7L��-(}hA�[xGo%x�R�H���<��Y���F��_��a~��Y���JVx��+����Q�b	������h��B����{{������%.L��;����c��3�[&f���AA��b�U�w"�����\���x�P����U��Z��^c�G�H���}�|��]&NpE���\�M��tf%���e��G
Q����)����	��D����DkO����F�
9v/�<{��F���������������F��~�c�3��^��Gm6_P�����%�����/[q!���F�9��a�<�?���Q�G���mp�b�5�)�����|PJ��@���;02�p��g;��6����_�?j���a��<G�yb�+������gYo�DT��(���t0,�_UGk���������qFO�a^���:�=^3��
�����7���$���b��S����I������1v`����M5������z�����6�j@8��F����3���&�I1���V�%���O���z���k8�^1-#&�0��E�_@�[D�s�8o�h���V� i�w�/j��e�!�u]�Us=�l��V������Y�6�����������J��U&&,J��������<�&w�(jR\�N��7�����3�����Z��Ih\	9��#�h��2�:R	��}�+�Gz���M0���d�^�3�(b��?F���Bu�<�I�!�p�|7��C�a��a'j%�����
���r��9�{Q4I�^/�
M���ai��i��?!����s[@*R���U.d��3z
�K�D���~���r��x����o�{j�l�6>kj�������������XJ3,�|&�H9����{M�c��#���c�*�1�1Ca{v�a#@��������Z�4�QJ�n�k�s<���(^�\���9�3J���Y1����d�����!����[e�Y�mR������E�3���WV���h����������?���7{4��T��z�l�{��k�6�j���D�Z]���7W$h~
�j~�����{�����
i0�<����Z�a�O�t{���,S��{iM��v��

�,x��v/�����2��<dV���q�jdfk��,���S�)=rF�����S������C�:�)��������Z-l��������O�����&���������vP:���)��*�"x
:��*��I:�LD1"��M��4>�Yk��`��������g$kF)3�rCi���z���S�c���"����%@����_8�%��h������	��F%z�d"�����2���|b0w�1�P0���&Y�Z�G�<(�Op�p�=���I�4H*�#<-)�K�8�h{_rU��UzS��k�$�G^�Q/J��\I�Eh��sc2~�l�E���=l��.+I�Z=v����P�����S��pt&	�@*�S�^SZ#���_��Ku)���	`�E�zCGD�h��������z�!���5��rb��G���g5�4����+�V@�b�H��P��m�G�� ��)��p%#����Z|Q�S�&��bk%��C�-��E�A�D�U����BJ7:EI
�#�h�%��h\���.�uw��R��������?e7���MP!�K%�d�#��s�~��AL�R%,��g4���q�d�])��7�	j(���^��	������q�p��I��v/64�����p�!�)x�h�Y�������x61)����$�����n��G�)!a���Z�f�^�&d�l��VH&]<T�A/C�WcJ�*�dF�ol^���H��E�y������S�������h�&n����hA�I0���T�2;?��9����T��i���L�fy�A��5��++���5��d�'s�����zHE�y�e�������Wd!���N��r�T��E�����\���y	����}�J��=�;�yro�I�kE�����|v��\V��K�f��o�:��0W�i9��z�u��b����	CH���p#�;�O�z�.���(����l!0�wzM�T���eC��A���%�5�dw���PAS�1���/��aO#��Rt/�N�����u�6�����Ah#HQ��~�a���Qu+9�;��k��DM�[�s%4_�?`0��`��?�T�m@��I56���M-3�����<�l&"IRV���H�A�a�j7�Q`F9��n�"�8���bV4�h+4�&k'F?��8���}��Fi�g�;�ZCq
duCv98��P����	�4� ��n����m��Z���	j#����4E�'�8{G���3�;f��w�b+
V�f��B��c��:�>A,\J�lk�����N����b�8����8�/�����|��u_���_�=U��]Ha;���r}��z�.�L���Vu}���^lQ�>�(�#V����C4WL|�c���[��o��G����(�2���(?����e��H"�z9��M�Z�h����F�K�������j��|��l��k�N�:�R�������yy��TZ�@��J����x
d���[e$�9q�#P���H}+��J���2xo�;���1�5��mIP���y���D|�,����Y/yp����#z�h�������x��`���@�rc^���p�7����cP_�fN"	lIG�lz�B����rS�1�9���fMtQ�H��$�R������A
���;hwn�����=R����m���[���a#��a���y�3��N{dM�)W��1��n�4��2W��|iI
��G[�r���k4�s��*+�|����oLB�Hn�q�H���������x9W���S|��,c��G6O�9�s�#Mp�@��@��Gu����	��
�~qN���i��t��K.D�F����O��p���w7(#`��}�\��D2�=��O��u�L��"ZE,w���r���ly?��'�d��1���k�1�<vl�P���>w�P�o�����o;/;������`��Nk��{�g�O�@�������� g~�f�FB������]����>h��}8�?�k�>:y�}f��}���%��>-���n=�[B#{I��r30b`:�~&��V��E[n�������������u��N�c��h������P0"w���{������Hy�E�|��pV���1���u�w��Y�*7I�v���AX��s����F�H�����w5��D������=�x�@�'�L�q��w���)T`�w+9��A;<��.w(J�%I;��2G�A�]���t�%����K����{�s�o�03|���0J����|m
�N���Km�0!O��fx��v��.<���VR�Ck�$�!yl�sC�� I gT?@O���(cF"�+��h�j[}��f��2��u�|���zav����~a������p=��������������%����; �����+���\b���*��MHLr	�	&`�D��Ud���4�X�i��6�����
I���;������dK�a[���F�\�Z�m��5�i("y���
^��9�� "g����X��'�>���!B���!�i�"
"^�YE�������^�EC{���"���5�?d�,_�<��<e�L4��/z�#������.����wn��|��]k���T���zU$n#�=�H�!����5�Dm$#�cC2�Ti.hI���;�1)��O�*-�$1��7�1wU��h�9�i����f&��~#('d���^�i��kq|��2�F��ok�\�&Mp�,i��1,�d��Q��tCi�G�p�,�d�+Y0�2{���A�Y��"58���n�.�I�pUzS4S������N���*��X��V�$8���^����t�w71D���H��v����n�Y��*���(y����o�]����G�O��?{�����z���>obh���������O��%k�[��{�M�����rHYw�)��-�?<��7���!)��_	�LP���9��9���A:�_�_�]F���������X�������
����hG!�pp���i*�d�����tnX-�1P�7��#�/�+um�3��}U�jF ��)�w!(mI�C@�(/Q�K��w?���W�+II�l1��3��b'�&w�
	z�����x��vM�~��M��������N`	:7<Q���u�_!\(<u�T�}{�@#��7�����m�XAm����o�2���79���p��8�7A'��J��FyS�
7�����!��&N�
�����5f���� #K^j���C��*`�}�C��eWH��q�
��2/�������}��b�D��C	�N��c2�Mn3���������]��n���q�h��q�����)��-e�����������O�iU!�I���oHD� w�Iz�!z�h8t�p�m^7�K,��Xh���U.9};+���0!T��T ���@�e#�6������"������|X�@(�k��)��qb��V���9G)O��������8��80$OI�@���^cf}"Ak� <�{zC��6��G}]c�"����Y��4���t���iX����;42�����el�Q�,-���\&�K9�qq�i8n@���d�8~~q��\'�u�e	;���)_�,������d| "����)0�Jy(���1����k�@�X�� ��cK�G��C��k��{�`R����_�ur���5�!�l��;���w�zN
'�N�,�+m��r��>c����V&�Nt���&�+-"~*��<P`�9�+@R��`���Zn�`C�S$���W�*a�0j]gM��N=iD\^J����r�'M����F%�r�|���v��)�z
���8G�+�ji0���0��'�J,�9�{��)��$�*�^"���T
,K=��m6	�@�\��5�R
�I�6�6����a��p)7R������M���R�������D��P���1-�G&�8I����G���ay���w�TY��T[������"^;s�(��f�	C���&q�(A�*�#d�)^�lM<eF�hP��p�3,V
W�!���b���.�Lt�f�3����:�Q�P��3J�;a�6�����:F�i:F.�5�k�e4P}F����#�9��4y
ws���t���-���6�'�?Y���������$o�EF�=��Q�����dw��l����6����_��Dt����l�q�#�G)Q���� (n�r��e�3������!\�=���~�����/��.S�&F$���5�/5�4`^;�?�������>�og�%���~�I�7A�X&�}h������p`�l���L-iM1x����3��`fA)�YZ�]}���A�}�����5�K��x
����H���h:�����F	���yU�W��5����tvJ����+�h�vrVG�a����t�
���"����� ?�1���M��� ���>5}�|�t��4Z1.�Y�+�n���0�]FT�������;��RJ^��89w��h��2z%Fw�T�����)��I�gh/�4�+��Q�]��-�&������	>6.�m�T��C85t�����E�h#)��H'�Q2�"�|)�jr�������^��U6���_���d����K���^)��G�B[)yP@���pZ��FK��d-������9�3�+����!7_������ �����k���u
T7�q��������� L(�����������GtHz�_���tW���a&�Ld��h��!��N���R�U��h�!���g�H6�����/G+"��\8�j �\`D��X�(����
~T\�X���p��Q�1�H�#*0�stx�z�	�E�I����nc�KB�C)��	�] Q~��E�f~��������&T�d��\�A�7�2Gu�e~���Q�X�YY�	8��n�����&V��<�B��?9��I��J��J��bJ���Qa ��d3��"�4���
� ���)��bn��9c5�[�V�h��&�+�Q�=�����[�;�n�kf#)��H�Hw������E����h��s�t���d	���
K���Y6����xF4Z?�-6�+3������eJ�(o��p�2=�8�Pr.
M��Gp�!��3�p	1���r71���NN>l��
�'���3�A}�2K��0��l�"����Q���kf3�X\20s
.�a�������sa�bF�.�7�7NrQ=�����W9�C��	���F��qH�%#�!��:3��9p����V�������!'�X]����DN7;/F�����/=�jbX�������!WY�@a��0l~'�+z5�i��j��G�D�X��?p�	n=�
$�i��L���m��<�wpgJ�db�����g���)<g��bZjul�6�b����7E�aO��&������v�=>p&<�"2�������^H���K��1�ch����\���
{g����w���gd�����W���:���zQx����G����	����OY�Q�1��H�;�R|��{Cz�7��l�CS��F�5aN~^f���`�����G����?��d�p�oW��fW;�g��'��h1>�����(����jw�n t��j)�5(8K���@g���i�^d����)���RD'"�V^M���}��+������5}GW������?M�ZUfU��4q�J:I���1��08�Z>����l��mS��fO�RL�D��X����0��$��D����8vXI�F����.�~��
�}pp���i�{�������"���6���gs��������"���:�
�Y���r�%�-/,!�����."0��ic���y*4E����f��$�3�P�K��I���$��;TR2{I���A�<�v�[��th��������NW*���
D,��������O<�'G5kW+I;1Z��b�E`�����-,��aka�/fO���q��{W*����3�>�o��x�Jos�;Z��
&J�����#�L�,���-U���w3{�W^�p�j���D�kB��Sc\���I��cr{U��\�e1�}&��8#�!Q#U�67G�&�.��9�U��8d��-i ���+���T�����]bs��q�xaC�O�W�����6\�u�v���������]�.��=���U�0Urm�B�9E��Q�B�2�j�]��D]�|��N#T�)Cm��-�,����.����mi�\&DU���T4��������J������@gw6LR)����*��$������hK��yZ�S(b�����H�s=��������N91�B�����AF��
O#�kO��	f��C�;��������?\��*3eY1y�D�30�j���"��'�_���c�������z|��!��h�;H�7�m�!���ef�O�.U�����Q`�M3��AA�.���YQ4G���TV�5�s��d��sz !fV��qL$�*(5\w%�/������a�u���`��!��k������cL��Db��n�F����b/^7Q���:{�����\�#U���.����d
c�"E�KK'B{��B�5bdi��.
���#��hL|Jw����f�mJ��B	�<K��9��1=����U�PG)�,uj�KWO|
�g�y���LI�/����e������f�<t�qW����c�~M
���>��n&�hEF��Z�
�'p�F(���rp��}�=-��|����,5���b�*]|���H w��G��D@FY��b"Fdx���,�Js���q���M�� s���d������b"x��|���c^I�-
���	-7-9tf:�����Gg�I����\S��'.1���z��X�a�t�H�_��TJ�X�y�}�7F7�o�.�3t�{d�c��N��������c��Q��pu���%cl��S	��9~>$BC';���yv�I��8$u�$������8).|�h~�c�V@��]qB��4����E��U��2��9|w����X�a�Q	E�����+�����)n��������C��1����.8"�7�%�WF� =�mC����-l>j�����4%Wd�vD.���-��*���e �Cq�
�T�������!�ZV��++9�}z��p�k��z�
ZP������U��B��P��/����}-�Q�r�
�l�����[3�[)k�5l+u�Qhu��
p�S������.�l��U��'�g�Z*������^j��`4��
�3do��?M����rb�6��xQ�.���J����AV���B�phQ�K�7N����E4���	G�p�C'��:w�&�!�PXj��(2��7r���<�jb��-��]�}�B�J�{�B���������Yrv�}x���A��
�VjM���2e���#$�Ok�H���;p
�@�(���5��s�,�����*bg�)��05��cbIMj��B�M&s'�
��9�\�S�0j����k�9B��NA������lq�4�0�M	��"xg�1����s]@����qTD�W	������Kx�����;��a��j��j��d����MFN
}�5E�Y�q��(8��rm�0(�Ec�{������<��[\�������?a�n������_|�H��_7�������_:8;� ���2�v�����~pv�M�k����0!�Z�����s�z��5A�D���|��,�0�F��BL]O�i����H����d���>������,8�>�_�u�H>n���mSUf�s{wK�!��.�;f\#��m����+��#�F��A�9��LHDW����
k�������PCl�}2s���:2x�#@0H^��^���[���xJ����d����_8��F-���|�js��uuvX�w��.�G���(�*���c��0.M�ws�z��]��77�Vu"����HN�JDg��	8��,2b���Y�|Cu����Y�k��jln
y~�&#3���U��&������ou�A����76�(-[�M��q��&Yi#�W9Br���v_�����q��D���M�WQ��0Ze�*��p����b���+��8�/4sz�7���d����#�I�F����Y�Yzf��k���n�\���9ic'���T�2k#?�#������"i����:��V+��_��:��l)�FBV|���Z���b���]3(��'�#	�fx���e�{S�3�%�K�����"��r=�L���N�:Y���u�hY�b�F��yce\Kb����EQ�x��*�De���R��*+�2��k�fOV����P9a�7iIZ�M��K�
���R��Zy���c���+�'W�"4��2j���i��d��$`F����I���1������"�����wv)�-&�xzzWR$�\	���J�6���,�_��s�����>&9�<�
j�� ��_
��iV����+��w�r�Zp9f*��L�M��m�p]����LH�|pG�+��T>�Qo�	�1{��(����z(d?�z�����c��T:��
���W������
b�|)E-���yi��I��Oyf��pv��$�~�$��UK
J����+F/!�7pO*s.�#k]X��+	k����3�~	�������k�
Gg�e;������
t�6-_?���;#4a$�P��wW�-	�Sb��Z@�H�[EH�����QT����� vC��*LC�
�F����f���J��~�
(��W�]q�vos����3����9�/����T�fM$�����a�>�.��
�\]�P�6�~��-��C
	g�����	��&Pxo�	(�b	.k$a�����d�V���x�yx
��+<�,�
��p8��#h,~����/�G�q��"^�����,��Q������
�8F��|w�54c����{=XPE������MG����T�`��Z����0���1�H�cm���
��/Pz��YS��)�{��p�Gd�V	_��c��O��T�F�������tZ�{��=������?l��]��/����y��FO���KL����Q}����:%B@�3�8v��%��P"_����KiB�@2�l$'1(7�7T@P���t�}6���X�#�,�����;*��M������-b"IY('��1#�W^epR�%���~�R���8�@,�E^s�x P\z��f#��S'�?��5�V��/��h���� �/��c����M�P`�c��}�N���D��I���5���T�(Y3������nE�@�
��T�;uD����
��,&X�K���O�.n���8"��CtXR��t�|�Rf�������`j�iF�C����x�vDt��Fu��b����~� &�"M��u�4��2'�Cv�j���<4_k��z���Of
\#��c��v�������Cx�L�f8&
�HB���`c���j$6�a����V`�4�0pT�%���L91�����	�V�v����eJkJRH]����z�W��A������E2MO�7({�����*���Z���w�����TJ�T��d�_������l�������U��s�*����v�
�A��j���f�L��������2��f�#�b0��9+���]R��?���~����+<i����v��]l��'X`C�<]����Q�>n�������V��J��U{�����VZ�C�O`��JE�U?����.��,W����E��~&w����+.E��s=�%Lm�����p�y����D��m��N�h��;I?��R��s,Z�u0�vz!U�|J�R1Bf�����C��dm�v����e/���3��V����$����n"��l�����1@����v�� MB��r�&jA�H��'r�ZZ���lqU�l)�
���!��o�[SH��S�&��\|�Y>�����{�
�!K���x��e��S!�\��)�fWt���/qM���W\+�)���<���d,�!���y�AhW �x�;��,R���C��a�:\�O
;%
���s��p/0<��PI�2��hjo�>YMx��l�������p]_c ��V3#c���mQ��P��%���mC� �F��GF��������fV]�nP8Wp�BXsN���kd]�,��=�T�"cN�2�v��7�����������TG+�����O�\�Bm7�P������7X��H��� �	d �)Z�\�J����c���HE�X�uoWZ~�y����m9Y�f�*�*��E5�09��6AJ���o�����������x���hjo�	����n���O���b���P���;3���N	�z�^�
]�:���hPq�����k:���m-~�>
�
W���������^���4���;��	��������+�&N�I4��*������
�GNST�@��8M��f���AYp�
��B��a_������TH!Qq�U�q�S���-2H\%)�C��Ku5F�W��E��'��:����!f �U���>����	�n����n4������)�b�����/B��q6s���/:�����6������g�"/_Df��&�G������{���O�~���m�atk28�	t��I�l�.��*��dO]�.G��P����`}C+�R��m�a)FQ.4��-�P$V���,0�G��ziYN�	4%Sm��f��1$��eN��l���B���t�+g#��_C	�bXco� �iI�vn�,So:%
'N9����a�rI*%
6��J�DX?�8.��L�-?���6Y��G��DK*��^��0]�
Z��`��j�"mZ[,��5��ap�6�������e|�EBb�-��x��@�n�	��N0�t���k�G~���?�_������|���n���n�K)%��<<o|��\�-����8�z�����������S��;o�;%+�/OJ78������t$�Z���s)��j����R�J���i�#?lGFM���x�����[�b����)�9Tx�G����vw5�?bq��!�,^�-c3;��e:�����9�6C��Ji���ig����������	�w�x�����?|���Q����}y������0+JV���TX!e��Q��j��E
��$���n#�;j&v�_#�k`��1�����,g�)����d�v�A�Q
FeFg��n���Up�_��������)�24��b1U��������E���Q���+��+������HKw����@m�L
�������Ea�2��L\j��������(D+����vX7��N���Z�t�h�����[�s����)L+�,�[����Z2�����p��+9�G*H8��^���u���&��U+�,PZ������+�f#���Td��];���S}^zs��q��^�Q0u��Bq��g��J
��Z`�?���$1����R0o?K�����s3?;��It6���==F��\%���j>p�/���B&�@.U��aWb{�z���}/�����������`�)��2�QCY�/i��S6"�(t���C���r���k���Z\h����H R���#�	����)�N��e�Ge����(z=-)�b�@���A2����:x[�6��jEb�/�c|�(�\��R\��CcS���_�w�zu��}5�s������j%�9�W��h���[��o�r��#Q�S�������v������e��hW��
eK����������N�&T\Y*T��N���]�O�p��C>w�X=�d8��}����	�������9�Xl9��%z2,�1���+u��*�+�a�EZ��T�[�4��������>�~�������V�_�jM���[t[�^77��;p�^������A&2�iR�a��
��AAH	���������Dr�
B~���m�d�^y�I�Mr���d������Dr���-���N0��C��B���[9O������64��B��Woe2�dz�����7���6���p���l1�(D�a���j�V8=	��{��Z9�8,�}���L%�+#7t����������q�%m=u*�doX���Fy�	����?��6X�������bL,�L�!�}��pE���i�j�D3m�����"P�^�j_u5�l=�vo�\��M�q�9�xD6q���^�����_]'^\�{�R�9����{���b�M'n>?&gF�Q���4�?���o��� U��"Z�<#a�+�2)��4��MQ�����:��O8H4����!X=��W,��?�iH�9�F�.Mi|��e]��w	��YY�����������u���� �a}�f��j�%��d��"��+#�������v�$Nv1�@n�f�!��6�_X[L�L��~��I�7U=���t��w�.&�D��)�8N��1��RKQ>ez�G�4=��^�t���t�m���$9|�����q&���rN����=�|�Z�]1j���G|N��6f�t����TwRG�oU=Dw��h�wL���x3����-�,�8s��bP�id���z��X��u�*%�5W��6��� �R�HpFM�x�)�l�a��sA({���U�g|�*��q``��H3��;l9F��E? �$�����jm�ZL�0�3Vh��Z��5����uH��x���T~�G#�IkH��r��48��78Qqe��H�P_��$����to�|.=���	w`c�3K��@� 9����}rX�6��n�7�E��G��#.k����_�X�`�������M#38����F4j���	����H<�3cb�8;�r(�2f������c}wsa���_����V�V��|8g3�/\�$Pk��^d�@�F����vy��{�V����9q�.���_)Xr�XI���F6�+��m�mRp���-	Z���rB��:f�j�U��z]s5k�a�<C1r��4�x|<F0dSI6$�r)�t���i
�z���h�Q\����3���q�+�1��{h�t�:� sA��Rn��6H�Q�K��KG	'�r�����w����`��:�m>����K^���q�1�%Tbb4��{���pO�1K�B��v
-�3�n������H?N�R\��w�l$�������B�Ww��	5���l�e���q*�y�yi]}�����5Y�2��E�+8�R�=5#��UWI9���H5e������U	�����|H���w�^2&~|D�o���f��c����/3o��;����<����(�w��P�W�x�IF��5p1,c�=�)�_tU��^ja��ya#'�Z�9��n+���]��F�=Y^�]1����������cS�$S?��&���tG�|T@�����;�Up�t��x������ ��]3�c����n� ��6�] 'O�R��yPt?���������0vD3�LN�	�y:�dV=����L
h�����,����m��q�U��
��#6��QFh�f�jV3�8����YD��n���Z/�#<�KFt��-U��zR�N�*m��*���sNak�4q�����7���������<���o��6��\b�B�o�<�nr3�@0���U��<�W��7�$����Iu0z�(��NW<���P��c�s���������E�E"]���.�������:�&26����!����.�����@����.��h4Cydfq-�����*n��)�\Gk��������`��]2������[X��L&����R�����"���o$�g���V�K�
����[����Y��a1�����@��Mo|��}��f'yt������G�����wr�t�<v��)����"��\�$������E�.D����P�"	��p$��l�Q���R�Tt�f"hk���<�s��@���B=���&V�w��Mu��1���)-����o����E"���������-��e��t���|b
���(������`�*�v����5_x1��%����6�%���a1����%m��6�C��;��+����~~���������_�����W��0p�$�O�3%��S�����>X���Z����:�gX?]����_$��7HQ_"'����hG���z9ZH��`���a��{���$�������K��7��@D��Y�`S.�$A�2��BS"bz"��N�au"z�Mvpz��=p��@
��P�*�94�NX�v4I��`z����e��#G	�=��J�/��]�KAE)�Ne3�����R+�/\������!��������}ha�)X|���qI�����|l�&6�{��)��x�MW�c�P�#��x����B�R��{P���M3!�7��30�n*U���	�b���)&C4�
�1IO�@i���q�1Y�`"$T�R���
'�[�Q����U�^�1���X���4 ���e���U�b����e��.����$�uM�$�M�&�����8/��LRRe{��������&������4�R�X�sV�v���1��-��fe���4�������aRt�k��-����A�R���4�L�m@]p��B����r&����$�s�Q?���tRr��%c�]�t���R��	23�.���7W����M���F-��&��!����E9i#A�;W�*�?UR�r>#}Tg����i�&�f����yW�Y6�V?�SAvq�Al��i>J�-E�LF
���O.�9�o��tZ.�[X%
���J���!\7�hd�m���$2�� ���e�;6M ]I��VS���&1u�-�WC�Bn��&Wh��
����TR�{�4�����!YI.>z���]���L���SZ]���n��m��cis���k���f��X�.	OH�k�;�b3!�2�|y����������(�Lso:�:�,=V����v����d
�,���MT�~Q��ffQ+�����Y{�d��'
m����������ok�r�����y{��>�gia��j��wR\�u.F{1���O���c�[N.X�xd�t��7���-��p���&�;����m"3�J���oe��At�V-��o�e��w{��9�[v�t�����������!�=
��?
�*]z"���#�����4���G^����
�x��N�.�f�#(�4�ybr�khnn�UDu#��>K~���>��N���i��?�>����i{����	<��>�_4J�����h]��3G��4K���`���^�R�e�_����w���K#GU���v���x��j���vm*�c��P�qo��	�HA�AA�i���G�7@����s���!�`@B�O�W�G�M�%��q5Q��K6"�=[���%*k,h���������q1��v=*|���P�'Oa���Q&���.-����Y�`��&(ILf�5��=)���������r������k�w+HVbH�t�DsV���n�I������W�2���6C�]F���Z�bL��Bm!�*�a����b���B�8�wG'%�;W�^]e���Z@2k�,f�Da��������'L��0k��qjP��1�H���I��)m����Wwn���Q��)�DM��d����2�����������n��U;u��6q���]:����d�l��k��Z��O��Ue�+�VX�.���h��/�KG�����`A��`u��FS�����j�� R�bAw)���pu)�!��=[���2C{2�������/��� -��V-��E7�����I�L��)$�����7�����w*:�|)��2�\h����PP��o��j��<w0��P\IUZ��'�����C�
@�v���S0��a�4C�ea�E��?���U�^�w7��*����_�V'`N^t�\)]~�'|;��:_�?��,�5"c�"���G���w�^�0��/G	�����������E_���7�]�=n���q��+1W���	��&�
+�J������T����Q�K�+�~���^��r��@�]X��$,v���z��k������nJ�0,u�{�(���
�&6��g�0�)��M��`���"I�r���.��jnAVF	jW���qPE�AW�B<���M9^�wW�����>�,e���}\�f����F���Y����v����%/z�	
�&W5e�p��{�e&G��>�y�\3r�M�o0�9�6�w��Q��H����hc����U���[6&�\�/$B���t�|���m��Z��[�������B
���JzRdm��f��Qi�������J�����To�M�OF��p7����Q��e�0����_?��)����i���b����I�ty\>%��������4wA�����6���s�[GW]��������#��>����bKc��X���������%���A��$�a���l9b3r�{�d-Q�r��g�N�C��2��^(��8���C;U�s�M"��������`Z��$^Y����&�ER��T������y��ui��r�����g��=V����H�f�!��-|��$r)X��
NlA����0�.��Wd��x�Z�f/N�����8l�6�����
sKx�#���O��SNJ�"�g��I��#�����a���n��+��j��3�qU0x�KB�$!�x	r�y���'+3sf�D�������N����#�y�?������!nP�����n�����l���k
(��� ���n
��C<��XDb��3Fq�����nX�|,>X�N��1
3<;t6Q^��snm����
��^�K��:*�y�
(8���fE�id�D/�
C��;�(������C�,Ip���O���9dD���c��Cj�'��[&�?n����c�6:��.�h��a��7���[�.���K��/�-��}�.��42��X���t|B��qw0�q����9�����&;+�I}Cm�N\=��!�������i�0(c�y���'wN���'{o�D��aA+��QV���$����i?K��F�?����8o?��'T�2i��Q�4��d$1��Q
�E"w��<�f/����=��M��3�����u@�j1��y2��<
����I�:0�������i��J�1��%t!�����������IdG�U����5g��)RCx�_������fr�7��"�5�f�d
�&�\��r;T&����!?��N��%�~iP�XZTt��le�
o������<�y��f�WV��VS�d�5).�b�9j�����o�����n:��&���n���`�O��G����z�66��=���g��G��}�������o���������{������g����~8���s������+�I]�I��M����ns5A�8���Chq
�~f�%�&(�������������CX�d%��g�
A+1?����|���@�>1�O/r���G���d��3��(�
���'���T!��s�����Bk��?����k�fe!�|��.��gOZ�E��{�D�M��n���s����@vJ��4E���Uzq��p��D��[�e7��>(jQH���x���9��s�Z��m�T�$�H��d����Jv�����.���V�r�����nI�h�P3)�H�
0c�
"���1��D�#������o�ta�OC��]j_!@d����+���-M�jD��R��@F)D��w���`1~x�z���	��x��\P�l��M��i�'�=u��Rz)eln$�e/�����3s��zBs'���������P����+����	|J,b}�v��&�i69�..ds�Um���������c]���Q]��i{��#���$z|�c.x�u�D>�Q��?)������&Y������GxN��.�������>j��-
�MT��Iw�A�z�
x�_�E~����L���r���	W��E��HM1 ��2"BTr��!�ns�p��<����yZ^�E�w_	���;���=�EUY�:��"9�X-�H��7"#]�M�;��f�5u����6H�8l�$�Z?����c�h?�����o�r!�a���*�t�����F����r4���N~�	�dGK94A�O�
2�1e���xY~����bd�t������~�d��H����Rp�<�>z8�jl��V9���d�?t���������z��[��[s�eS��b��?v
D=��	��F��p���l�<����������g����������y��]q�j��ueL�-�*��J���?��������:����������W��%�"����?�Co\�*
L��M�������������S`H��d:XE���lRUyb��cu]�������Y���Y�������A{wo�hw�����w�N�g_h�W��M��|�����E�p\bt	��������N���tW,�������t�i��H� �������+����;������Ha����/^p��y�[A3���M{����K��dj���>a�UU<�
7�;:�M���Avk39>[�XO�o=~���J�K/��h���n!�pee�|I����#�wk��3�b63�������(v9�1�w���w���,d�y��X��@��v�����������|m
M];06���lr�]O�K4��yN�_�YQ�����7l�(�z~owG�7%z��r�J7��*^Iy���}��+�x��;a���;L����F:���iq��My�B��^�Crk��b�Vj
~�K=�fc���zO�,v��������d�yJV��t��&������K�s��t�qy���T3� �&u�v��P��f@���d~�i���g�������Vz�m���&�s�h���jM+���Y7�}���x�M��}��~W����j]K�F�������fZ���x��l'
����1w}k	�"���
��}XU�Iob>p�>�/p������=F4������&:��W����	���,�H(?���l������n�w��?Q��fe^,�lY#=n"��3A����vf���_^�v�IQ��
�C������CB����Dj����b���@��y�?<,�^���O����'��~����5��	�5�t/9����g�8L��%��h���4}���r�����9#m��O��}���4^��e$7��S�<~���K/��ZB�TZB�l���q�d'���hL-I����.)qDm�66�7a%����zQ�n�u�������KU%�iT�E<����#�H���k�b�U��i�/J@���y����o�}d�D��6,��F6�RN;\�]�DV��]�����	�����#^��O/���n�%�������9���Z�����/�~�_�k^�o���}���y���l8��o���h�:�U�r}�G�s%
-����WC�M�Y'\*w|�#�����W�=������f���|��*�O���������~����������c�kR�j8������i2�E�:�BY%B1����o>n��I��t�������F������w���@uX��Y]�T#vZ%sP�H�V���K���������x�0��uE�����P�!�n~��-
T_F�`A0���!0

k�`���"{��)g�7�\w��2�P���\��-0;���rp1;���N���:����U��O��|���]$���(L�,G0}$����e&xV��L(�AW0�1[:1���B���x��
�Oj�a�(�N�e�pFTQK? �[��[�Y��o��~��S�p�:�C��z9���g-S$Hb'�	������%���S��������[G�Q�T�4��4D���"s��^�@$SYBN�������5y�lR��j��J*!Wn������H����t`���z�2�V]{h �,�4��U��W��#��������{-?Yl��������Z���jU,��������&uiX�s�9�s6k�s���dx���u+�E���d�DP5����]-�Y����.)������l�\j��=2W���)�a��m��'���M�IofJh	���?M�3-������TS>3.r�r\�g�����/3�Sz�-�k3T�J���u:����V"�������k_���	^�]C�����J�d0�b"��8Xa90�1iD���Fz���&e#G���F����Sr-����2y�������JJ���JNRe'��M�x�N����~B>,UU�{�����Z3�$X��nj�F]9�a���&q���e;�wx�u��91��I����2E������r��E2p���|RJ�~��2ha3�����>\
��m���3G��	���5�[�2��D�0������s�fF��!ID��"W5I�)g����D�V�Y;�M})L]�Zx�$C��oa_^��Yt�����*a�4.M1;��`
��4E�aP��
��Kn�x8`�t0�^����(pt�]�J����!���!��H��P����3BU�LexV���+���m��*7G����
�Zk������o�O�v[��qLY�d�����7���A����B��||QKTz��MEh>������
g������p��V��d����
�����tB/�)	����*yX���Y��6����v��=�]�V��G�5�pO�Y^�ma�<N�6�����b���XMJ)?�UW�3����(�O��fs\^sSJ�+&���/�����+�y�����}��M�9����J�2���|����84�qJ?����t������	��X������de��R��E�Q&����x�_sb�@W=�p�����a��9�����sW�-����aq5�������M�<"M���f8c�1\4rK�^����v�\I�@����;�[�Z#��+�Qn0,�����H��!����G����3M���<��8����3x__��4z�K�Z�/%y8�@�&x�>�
�?���N`�RIAr��J�4K9zn�:�J��;���:4��k>��eZ�0fX��Z�F%�r�
�����*�������e�U���uz��BQBs��~���1�������1�\~MP���D�?�q%b���D��'�:Y�n����w�$
[��I%Y6��j�����[��O��<��I��g����b~��t��+�+��#�G7"��r2k�����@�E��H<bo����S�1(=�$Y�
��**[����C��"kKtP��7V��O�B"�����H`qA������'��q��1�E���q�D������j��y�f�J>�+x��,�/�<
�I�t#������By,���r�p���k�A��H�dd�F�L�
;�+��+\�F�]����9FE�X�������4��P�
Bg�:��TL�Q9�<=�}���=�������bTl/�#Tl;�O���?�P\�r#�6<[mE<�Oj(��JP��z��TD+#�5bl$J�*����@S����U�@��N�#���Ik�	���L�h�0E�>l��=K����h�����yA}�+67�
�hQ��9C��|�
�����:�Xa�D.[Z�0B8a,�9��9(�p���H�y��}�� ��$�{?�h�.�9��x���'�`"���l�5 Jg�� ��OX�
��1�|q�An.H5����d���x�42#�~��Ev�����	"-�|���o��G�?�@�z>���b�(��1���(�����$��h�e�J#�,��G�iM�~B��@��@�D�|�:��1�b)��/X��Jvn�T������X�-��]g]���q����d��<I�G������$$Z������3~����XAK-/	(`��
��j�����	�F�u�"]��.���1�B��~���:q�����4;�����Y*���"o��c&��FB�O�o�u���g�G���-F�N7���i�{��������;�l@!�����8T��e��d]��qp���)y������COX������|#���.r���?��<<��!!B���_��aXj���$��dI�2-��RZ��1L'X�?�>��=�h����3�D����d��,Q>Jr
�������x��ON��h�������Q��rZb�n*����>���?`&M�������<�������Qc�G#���_]��3�	�o]O��c�y�IL����%��i�e���IDZ�(A��b&�u��%���z����Rj�MCW�1�����vvu�K�������nU���EC��}��Q����b��y�A0S|���D\�	
Ip����A��V���-)��f�����m���;��y���"�?��F�m��8���H��L�����E?���Z��
�����h(�D
�f���������w�G��%�7O��;�b^r�����������f+�gt���-����� u���8��uS���*b�k����T���s]7Y�@�)�P?J��1���MI9('�i����1<L�E�w�
�.TV/�o<Z�i��l(7� '�X��e�H���!�����0tw���o}���x����%-j��Gx#|J3������^{X���^�� ��w7����%�����p}b���V�7��Bp(��j�:�h=dk����x���O�����)~y5q�m.����/\J���`����
��#���
��\`�h�4@m�x��E��K���2��L�I�P�1����������R�:�z^���J/�
�����d�)�]IUhr���X� M�0�`��"O�N�b
�T��1�tzP2���,��2�R�;��O�"Cu����&E��z�QW�0��`S8�QC�%�}��Pp%�mC�M��`�����y�=��doW��A����4vp�VV�����r�8o�"3	�5�SwA
X�F�9Y	�Ny��~����K�����5�7{g�g'�w���F9�`TK�������y�����M_FF�8��_����6M>�c�:@������wY!�K��3I6x����<�������<A�=�Q`GxI��H�F�|��0��{E�WE�����������4�;�����G�X���N8�4��H*S6m$�
�(A'��f�?G����&��cs:;�x�V�F���8�����}��wr����}�[�r���E�������A+h����aER#�&3�|�0c��\�`qu����#p�1�#L+������cI���9�3�����o�&����Q�����I�I��o�YK�N�l%A3��g������������ �_���?���+�y���~���m+��)�p�^:�Y����X�*^���/z�M�c��&����-�yd���2U�:������=�;Bkz�"��yf��
bRt�R'�j�0e�I�gTp7�%KQ(�AMl��oC6�����k|�(�
��J���s~�S���gB�����g�=}������ngFBw����A�i �����n���xk�;���nX5��C�.3b:�4��Cs;E7����u��#L���I�1Q���� �S=>E����=����xV����F�������h2N?g}�i�>��S.�3�{���������� �n������dOL'n���g��)�������"m���y�-�J}�������A�"�q8��x�"?1���J�g��z��k�9J�j
ki��YDzh%\�C,����;��@w���z�2~�����l�V�U��I���i3J�>}�z�����c����%��(��<s��-��7�V���M��V{��~�AV`Q[\/��'G0B���hEd?hjH���n�QXt�jk1��5d�2K����}z���'������ao�j���d�P��43�(%s���Ug�#��ka���7TM������'g�����C� ��W��Cw�+&�D�RV5y��}�~w���n�������M��f���(��#�~\�Y?8"7g
t��`�,���M�ll"h���B��
h�S}E��JK	y�d���q����d��<�bXZJ?�%$�N��1����1�Np��&a��'���Id�y�{�@SLZ�V�K�<��?��pa;2�8��R)�V���|oQ�����C�&-=|���K�5�e8J�R��DY���������	=
^A����.�E��o��W��}�j���l "��"�ul%��l��������w<�(��:a*��B�&�5�i��H�}?�s����
��'�BX�73V*�XR
:���`���q,�z�~��W7e��<�Cm�7g��_��������E�s�a�88@���n���6�Vx��*���2��������n��,��a����	�jR�an��R��%8G2Q�/9u��5�:�a.�����5���{��R��0��|z��VO jE�(S>�|J�g�Y�O��SY��bfei�,
���Optw�S���D�;�~���|��Sw:�J|��_��65rl	~�E-;W�B������f
����������*�*�<��<�|VVI��7��
RU��d��96���K��\9���'������"8��Up�����_�<�$�d�9ZUGC�W;g�YFU����&���1����[A�-�s���$Lg�s4m������0�rC"��^1��wI�� JR���pQB�t��q�g���y
��|��������d����GNF&a��"h�'5��Z���jt�E�R��0���
���HpE&��+�B�0@�����Uv���ZFmd����%�E	I��)��(:<!3 �T�i@�k����:*������DH�
�7���s�/DP~�:�4�������l�'���"��3l�!j�0��l�f���A�'A��/��8��o�^)1�!
��c$�L�x�C/-�(��0"�����/���U�n��{wwsv:��Z}Q}{��
Vn8���](�w�#�O�0����D�j���PA,���@,~Z1M�Q9�!���$���X#0��YL���O�R��9�����:�����!�T�}������*��R�=�g�"R���y]��^�7�]��Y����^opuu1��6A���
(�F�V��c/��z@�/��U�@���l�3�sl��{���������#��=���^,�����
�NR���g %���O��7
��I���/-�����-�+�m_��)Zu�!���W^�K {��
�e����d& �� �8�N�����h.��F�V�q�3��D��{��/i�c�T�������*��-�Y!6�
K��c�Q�e(�`�[�c����K�	��^�,����%uv�U����x@�#��'���%�'Fq�
lXZ)���$s/4���s�S
f4���AH��2$
�����H�P��MK������QW�� �Z�P1���<�h�P<y���q��cpA���Y�T<�o�Y�J�C�d��UW�YxW�����Y�!� ��<S� ��#*�]
�!%�-��c�I���l�*l�{�`��Dv�(0 �Q��,X�^�p�3pI��(�G��_��,p����x.�d��p�h�z��%�5C�.�/�����h��"��6pt��}nqA-�0�"
+C���#"�,���($�x�@3c#HY.%N�d�����Z&Z��!�i��I���2Sb#R�o��u��?��3GG��"�[�l4Ta�l��,�4w��noO���e�FWLUx�����GY����a/H���C0��Qn�!��xI��'0F���QB�BA�Mc����*Zi-,�����L�Jc
����A��z��
=�{A{H��K(?Q�=��Qac�,�F�.��*���!#��B���285�V�-_���h�wuE���f�Cu�k��/M�`��'��m�R|#��:�f�h�'qv}nr���}��-������P�!�M+��j"�R��F=�2	�/�<XNf�b����/{��x����c}��H�n}1��[��n#�~��UqY�����
����d���PU�:��u�I��:��v<��*�+^Y�~W������3,n�t����������F|�|�������O�)�VQ�Tt	j���l�u��u�+�f����~������H
��m����Qk�0b-�����5�o��S����}Q�]�������@��$���
u����H�y6F��y�u<E~�TN6`	��C�"�J�{b$`����#��aUJ:�ZcQ���L�[h'�!���Z#KBZAe��B�,�J� ��:���k�M$���a$�8����rou����X����F�sc���~���A�0'(��(�tf$<���xHc��`�;m�9_=���O��z�4���|�)~J�i���5�pACHA����T����c5@n�Ty�`�������v6�{�����=�5�bz_s@��`��5j�JM�T��t��� .1�*E ��X~�%����t��o��S���^�@�K=�����b�6V���Li�0>��K�����|u� <����������ma�p�|<��V�L��!��h��94��?Of1�Ed�� ]�x:3g?}&�����E��YE$j�M���f'�����H)��Q�?J��O�P�1�����GX���+�A�Y�
2#X6%o
G�2/{��6�|���R��{��d@Ol���E}K� �GS�]�	z�3��������j!�8�u���"��
����<{��<X�W����W�1�q�Z}�a�\v0,��k8s,x�:6&���w^�������{Y��"��b3�|���z����G�M�;aM��I$.�W���8������3�!��$�����\�����`c�=���#���p0�Xz\Y/	��4���+�}������8!�P�\{k�|0�#P����|7���2�!3{�(��-����D�|��+~o���uA��N!�Vk���i�_wv8|.*������#�Zn�������c�E���O��c)��O���b>���(��w�l��X�� �eTy��n�NG���f��<��w���>�����$�	z*�����$Y!�F�]�pW�77f�"��S�R�;u����C�����x=v�
�b&]]-0D����Z��P#��U8���p�I�k���m{g����jH��5������@�@��������~H�\����-I�N��(���YJ���Y�,���(���0�zc�{�'N�m�TI\��uO���`�_���,�
.�v�_c1%1;}~)�e)L���������T�����(�oA����39�����B��e��><8�Pw������NG�5��������Q3�l>�9Xf������NTDT+h��=�{��m�-�B�/�������[��7���O�������;�v�x;Cj�����oQ��S�jx������Xl�OY�����Z���A�O����`{;����A���[�z�H|���u�����u��!�^�f�R��U����������
�|���sW�\�zx��r�.������*#-��V�|�F��2l������q��H��0��r��;�5l������I=���]^��l�"��}�+�v�F+~"h��)�w���x���`�8Fa}��T����LK��K�1�����\+�P�
��\�/\���y=�Zu����O�z��G�v�Da��C�F�t�:��$�0{����:�N��~���:�����U���� �Y�^�rP�o\���e��B�o�/�� H$��Zf��(�AB�Y��n�4�s�1P< =O�8��
�W�BK���nw�i{5>A3��?�/���&�I��06?"|.�X_�H�#Y�X(�rr�;PJ����q����+�FE��4GL�7���F���������w0���h�f��m�� ��n���!�������4_>d����ht��X����U4�/�������K����tG���v����MR����O�*�?d�j���}�4>��/>��	��._�IOpvbd�$���S	���~��~op��|�~bJ�eH��M]�#I6w;��L���{��x#�KWP����b�Lo�)2P�9��z�|	Y+w��g3���z��d�F2��N�[T�2����n���������j~���;���c��8,�����	�R���(	t@���Y����@�kN���+�r�+)�����������?[���|�VK����v��r���D���	j���6��$����,����������
EP� ��r�r�7o�0��TO���
%h�/V���T���-�����q6��y�)F-��55v�|W��P��]$�T:�Xh�H��K�u�K�j����k�7�Q��_�`2��DU6�c�],���	vl�'GsM�$'E>ow�
�/�)��E�����2��W��Qs�bS�
�K�e�?�X�z'F��5a[���6������TU��_��qRQ{V����[bpv�����kA�#I��|I���{V���4/�%�����N���@��C��Q� q1.�%���2I�^p�� ��d]������Y��|���Pl5_���#���& p�N(��_H�c�h�G)��JEr��k�B-I�X��`�Lu�����@�|�f0���E1|����i�B�@.gi�<t�@��Y�76�<���C���*a�<�-�I��2�bF�<gf���ts���c1P���\�I�P��<��N���(������a��l��{��Rs��.��{�3�h8��f�����QT�]QJ5\gi�;�9��QE�
�":e`�/����!��Ok����M�|.�!���?��B��nL���{���WR�*�
��W����{C3��o��2�&��I����!��P�t�@��-��JaG�,�;��\���+�O��tu���.����8�x2���#���p,�������w��N�u����qf�:����=
�Q,����U�}8���dp7���o.�>\\����bs�z&���81�gF�S�2�-��I����i"p�����������[pi��)*����A�f�1�in��������;�J�iw:�1�%��8����+:�A`�=��Hr��|{?2eN���=�2�",�!��`���6�:��@��G�m��~��\�_�C�������XB����.k���H@�B�9��V�m���v���QB2d���/H&�&,�`���wx����������b����>����,<��G@����&�7��{�P-Lok���������u��|����'g�V2��@�g������?a:��������[�
���(�d�)�����^+���O\+����5�f/\��eVv�������������#�ZV'���������;�lRW��tr��s������x������K�����^�q���&oX��b�*�y��?��$2��� *�a+�
��)���7'���U����A|v�r����%��QQz��P�����)�R�	S��dc���l���?�=����;?���Ta��G'�)�(^����*#��w�,���������krOy�������f}������`>-�C�d������MW���
X9�����u�6F���V$�*�������T�P�cf*�����6*���/�rx��-���*|��������{�;)���+�6��0�Ta�7z�7-�G��|����@���A��������C|q=������)�^����e��2qN!*��!�Z��R��n���^��Ve/����N3;���9�9�,�����HQ�)2��(���H�P ��*��KK������a��p������a������A�1K��L��s�
S��m
�P��~Acb�����x��9.�S�3�Hi��Z�j��VXHt%�������$��8	O.�!��� 	����V+?�5s�� �W"���~�!�e0����7J�!m��d�H���1�9j:NG�����)���Y%Z�i�:p_��p0JU�s��]1#����a���r��~��V���"�l���d�)3x(�����G��9.�=s�FXi�4N"������i�
zW�9sC�n8�c���Q������3�IK*^�pN���cB�+��J�����L��d��{nnc�����W��S��-��m��ET�b��.�^�ep$��a�t�2��B�F����L�9h5�=��Y������~�>q�>s����"���8�6���^��T��.K	U�����T\o�]���Q.b7�o�7H�0(�^�Kd�=�&�����1��+�BI)w���b%j��4��`8
L�!��2 |I 
UQ1� U��H�FT��B�yl"^:�C�KQ�
��C�Br��1�{�+���%��;A�� �!��*^�I"�Z�*pRuX�m(5a7��r;�U����y�A����K�b����\[����3r�BD.I����-���#��enF��jgQ����,��1�(�(5$��JJi����pb]8��7J�Uxz������*p�o�S�rLD��5F�.��X������;F�n�����zN�j}�6C4&��D"Hp�-�?�& n�dJ�\����p}�~����`�l~�������u���&]�TED�f!������@�(����5E�+�]���4��GQ�
����|�H�V�����0M9�
L��O�H�	�E`��@+�Hp����D���0"�^[^\!;W�����-�������2�.GN���9���|u�M)fP�)���b ��������%���71J* '��o�f\M�N�MeZ5��b$�0�C����s�P����B�X4jR�-��i�"gR�k�t��h�
��1W+�yO���7����������<���������q����8y���{)��:�
�A(j�9K�v�.���}<��fAT��~���
�I9Y9�T��x�$,qF�����Q���4�R0@���p�r0�!��.��Wq�����eEA]����!�c,�U T[�:
�.��]&<�zs��]���8��P
�=��F��;n}��v��\��
�(��t-e9
������KM&���^��d	y��J�o�1��m���G�`�p�X�^�Q.G�f����&����L�T�wR&{A�&Y�6t����QJ*��T��*������X>��YE�:"�g�+��	"�����X���F�{�r2�|&�����$z)pl��EJz�`���{!���bX�T�Y{�{�����$������HX��R�E�jH�K`Xo$e����2���UA�@{��Y��������6RH���f�i�
��;t�
�����(]E�cf����a�������2]��W��9=F��1�����=�MT�P(X���,�\���/��ax)�Bf$�n|����R}�&���P(����vVs�X5���yN�VO�[�Cb�H������"TL^8F�ql0��<��PXBK�-��P>7]��E��M�CC�/A{dc���Nz������
]8L�
,b��$�y@�$�I/mvXZ�W��R�	�
0Z����[����B-�LV�z,�.���� ����2��2�Ceb0+�9��(O[�?�K�����?J^V���1�R�I/������jD�*u/w��i���x�5e!�f}J{���yi�t�/a`��%R��!z	�K�xN�e�=&�h�����&ZJ��-����G�j�Mx�WnoUS��������D`*9�k���xS�����l�Q���
�� �JX�����k	�������D����j�����Z�H���Pje�p����t�&S���������T����2Vw��$�	��
�f���.�	�
Z�<�E�����W���S�t�	p��V��h�#��B]q,�Q\d��q�7�k�#�W��`�
����Vt�h4[�i4-���i��0�a\�n�8x��Z����0DfA#���lN�=2i�tz����TH��3h�.;�������8���|��'T�-�S�e���%����b/�is\12]�?���h�.m��/V���+��a��<��7Z�-j����;R����~"�u��'L�n7�I��D�P)6�fo������% ~��k��
n��@����r�i+L�[��T�T���@az?��l��r�c�p�a��3(f�����K%��"K�����Y{����a��������w�.��h��'Lo0��i��E����_}��R��O���I�*�W����qE��F��q���b�)��gr����:����Y�����w�g����$*�(����>=HO-yw���-5�����MW����2~ZM!o���V#�N�8�h��X����0#��-]=<Z�����j��2�+�lC�GNKw���Li7)�I��WE��K�4�ip�g�R�P�96u��Ua�j��I��=�������� �V���G<���l��./��u�q�,�9j9�/�cBy.Q[:#e
���wV��8^)%��:D�xe`:r���@�3�TI��Q�I�u/�>!�M�7�^G����TX�
@z	��@c���%�yRb���cI�M�e���DY��e�>9)h�tX�������u^0:�j�^���R�h��W�x�;;Fe��7���j��F�)w���{
S���vQ��BO���
���.�
p{6��CJh����m|?�h :��d�U=3��N�H�An�����7�������|��w\W'9,>-����JA

H��?'oe?��������l��U1�>nn�9+������L�������z����^��,T�S���b�O�Ip��|J�%�r�q�T�qKW
\���������������q&���W$#H*������ASUz���8�s�=�����$�L����t����Dz�fju�1�?�&c�J�v�'��@�:�!P���@|B�/4�/e K��A�@������5!>DO����*�0B��]M���Z�*2-���y4��D@.��s2BG�8��P�s��9�TF%gj5�%�;(3�#$�j�������Z�t����i�{t�h�������F9��0W���/''g��\�[�
�y�'�����e�������\QZkA�Mr�#M�i�NW����P��K�K�k�{j�[_'/�9������EK��������{������y����(H��z����H�M���C��C�0��?%Qh ��&�c�{�@ Q�@���_����l�x����V8�������@�N�u>�d�yk��,�L��X����>w�N}���3���xnn��������H����@����i���Ft0�4��:���+G�4v���t]��T����h[�P��������X}�x���@V�)l�n��P@��'p#�dv�:������j{��f��,P����!�l�v�0����;��ik�y<=j4���n�l�o�]����{�g������u���K0'���q	j��s�����n�N(5|��9^�����{��Uwq��.�CLN�TQ�m�|�H��R����n�ux(�T�����u;�����.���q����;P����#����~�|,v�8�B��@��f�uz�%i&����f��I���V�q�!�������g��U�)�w�7qg�>
����w�����]�3�=j���j�9a4�����������vd+���a<���W9������8���:�6�R��ec�[[�q'�S,*�e�	�P~�CH��9����Q	�&�4o����h�F���e�2Y��rA��f�W��4���VM?��1����o���l�_[��!Q\��zg��'��V,W,�3�Hf��w��7��Q��q/z]7^~���Dv����{$�T{��nuQ����v-S�4����%�b��e��`(R��O�S��B0�6D�`���h6YV��L\�����,JAX�Fd��2-43��D00t��T�~�3�<�l�a��C�Y���X�a����|��V(XU�9E382��������Vr��-�:���(9:5)G�Q����<9����D����aN�6�����'H��S��@�wg���fy�~_^�{��w�hj����E�@�������]��]��@���l����MJ����p:��qtx�:���w];�+�\G�+8���;���p�������`����F��a(���%~.�����.��Z���`p�j�F�ug�5��;;�:*�n$k�!�D\E����TNj��	$��YC���N(�p�@��W�C8����('�M[���\h?��z����oWA�,�`m'���|=����x��P�h0�Y��z�e���f���a�v��(nx*�TC���xN[�m=�W8��*n������|����y�|(������VGp���s����*1�eU18���- ��O����������
R�(����`����p���C�7o}������},��b������yR�!
�d�g�^��}��y��
�|X������F���"�7���������}�4�$,2�I�>�diz��s���g?������"�I�;8)���G��R���oN{����"��1o���6t����E��/�
`{[�-�G����Gn��ca�|����w
����JbW]p�'���-�1$��6x�DcXZ�+������
�!8`I\���^�To`���'�_.�4g���a��9�H��`��gV���*\N�	��T�6��������&��������U|7�������s��Ig[��2���h+��\T�~:=;��O���{����1t[t>���,[���W��;���2/�<�}SsQE�z�Q���lI��C�:�4q���S'|������S}�`1�3�|+��:���*�rk_3��^��oZ���A#��Q�	>���H.��
0004-wal_decoding-Only-peg-the-xmin-horizon-for-catalog-t.patch.gzapplication/x-patch-gzipDownload
0005-wal_decoding-Allow-walsenders-to-connect-to-a-specif.patch.gzapplication/x-patch-gzipDownload
0006-wal_decoding-logical-changeset-extraction-walsender-.patch.gzapplication/x-patch-gzipDownload
0007-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gzapplication/x-patch-gzipDownload
0008-wal_decoding-test_decoding-Add-a-simple-decoding-mod.patch.gzapplication/x-patch-gzipDownload
0009-wal_decoding-design-document-v2.4-and-snapshot-build.patch.gzapplication/x-patch-gzipDownload
����R0009-wal_decoding-design-document-v2.4-and-snapshot-build.patch�[iw����_���'K�DQ�-��Zb�h�$�$���v�dG�0�n��h���Uz�I�K�)�Muc)�rkA��4��X�������O�zG���H=��O���O�??���=q���V�E�������`�����0�S�����c_����2���K�_}�8���:-q�L�S���;���^px,������m>�Cy�@�����$�����wb)����?���+Lc�'^�8������B�r�gI��<ipe�X�w�6�v�!t�u���W��M�<<�I�
�)>��������N�!��A<=>�M?��w!��$����8���t6��
O/F������7g��j����������L�S���s�b�RZR?i�6��*�@D��X}tx�l����N�h��d"��i�	��A��`p#VKfI��F����:�������#�]_-�q�
��������oA�i�?4��n{��[�$�����K�S0��s�P�85z9IRqn�7�>���Nt6%�z�h�d�J1�a���r.^��X�ZX1��-�N�|N�u�Y2�fI�f�����%�~*1�<�;�"�a
�2��%Q�	�_��8K?����/���,��� �"K��TgB}���X�Vb�D6�{1w����5�K��J�
��N��?�I/g2�\�U<6S�O2���X���H�A��q7Sq�	���*�f�+�32O��|D�P��a�Nr/�%(���'%�0���j�6����,g�7�����^j{��	� �L�o�N�DJ�#n1��^2�b�b��8~u��y���2wh(��������5x���IO�c���~��3��J@l1��U���@<�U�R�: Q��0�9L������	��\�1�4^�e�L�8:A�A����&�e	�k4A�T�v^��$�O
�R�35�=})�S���h/�t2X��X�*!�'[&���O�2�����rx�aY),���z�H}��l5W|�B�d���^,O�-fY6t��f�t�������n���S��.Y��Q���<���:�Q�Y1��`����F�����kH9����������VRN�|@��t�u���$�V��Sb�UEE�33(2� ����;#��&�� E�I�vI6���]�j
	u�0�U� �D�B;N�$�{�3��'�mU�,��w1k���<H���t@������^aXDK]&��*����|��E����]r���=����Y�����!vl�@�0<( �)�Oa�L(Y�Jh����ng�81`�����j�O�X.���)))/t�0��k8e1~�b�#�9���@��5�M�M�j+��i
b� 9��]a}�l�1K �6���A�U���m����t����E0�
�����4I h_IZ�\Vr7�F��
ET�
���b_x�s���pFAI(�u�AX���3�0��� �u`�^�b�'���J�qN�$�j��js#@N�A	�D���O8�-���Z�(�H�n���+�aq� ����L���-M�����f��dlP�`�>N�1i�����cM/�^" �{"B����c��a\V��i0�a�R���q���y	����\fgr�a����#������V�� ����,��k��EX/+�B�C�)�<����V'�	&�D.�������FwR=����@�1���(�������i�+���M���`���&��R�M�����/�_{�%'��LN�2
C\��=F�*�o�)�d�����4�����94��������m��3�g;�R�V��(���{����Bu���h���EM�-��D�*b���2��b7�yH���C��`�-a���I���=U��K��*�fi���
[%|w�*�f���E'�o
���trj�c��G`Ng��n�J�r��\�Rc;[@Qm��>�s�6��gH&�d�YQ���R���M�Dl5�����lzV��	y�<�9�w�1J_O�`�3P��g�rPGvWn�7L�C#��Y`b���������5���#�Ad+h��u8NHy�
#KTc��89�"������pf&���~t��mU�X&���p��O���X���"2��s
�ks�QI`@�A�W�����(xAV��B�t,��6���?(��R�DG�q�N[!Q�m���$����.|j4�e����x��0�W�3v�IL��8e����%�_������	m��3b'v����'������}q$����0sB�[�3�^�-o���+�j�DU�������� .��}��sdP��Qe�[���'#]/~G<0!	��G�9��������yeF��R�[;9��qp�����S|h4��\�XOB��u���#��������6�Z�3�N�=�{�["BD
��'��y�``Y14����U��� �*�����P<f�J�/hN>��k�
�����U�b��<�5B&1\Y���/����x=���	`�R��
�������j������J�a�����nQ��F���T�5�|�B�����_��u�.�����9�QF��1�G[�7��T��QS9�}eK����#�,(�-&���^m2&F@#�'|9�f��b���J*1T������4F��g�u��<�5�����(��=�
��7�*R4�I���}$n3��������n}�������v�g��A�^l�@V�����aV�1��(�q��R-����FC@���E��.��2�0�%$&��	�^@�)�����GK�H���h.W��h��H�dg���GJ�N�3�T]"�b�C��(A	L�.d�`�����)b!�
l��~�������jP�91m�PEI��2����H%���2�K#V�;S�Z�|i��O��VK��Hf?�ki�[lfe��}-��~6#���W<�	'����P��r:�T�\2������Y�A"xk�"��\�0%
�I�f��	���C
X����jZ�\�����i� �K����j�8������D����lM�{�$L	�v1�k�x�A@ �#j��qI���/R������LsQ������VH��u!]QF��MT�����
R������"B�e6"Q�V(K�PQ��7���S+A�������h�R����t{"#h�LM	|Ez@�N�\�S#�,�a8l@�8�|�����HNq�t���h�}�gl5zG5��`�wp�R~G������t7qw�,B��,�L�>Qn��h��xe.��|�Y��>���_�v���_M�CqoX�P�h?=���N�� ��et�]l�P�6����a����>za�����
�o��p��a*^|,�����4�����5�7�#V����$<��*���?�EbB�<���?�����<l�����-�����B��t+�D����������g1���V#+�Q[������?���
�j?uiQ�b�����I��N�����d�Z�g�l�������(H�W��WZpt�=8�j��9�d�4��9,��eP��r������V���fo�8����\TC��>h�?���g�����B��'���}>��aN�������oq��7�����j�o��_����}��}3�N8W�E���o��Zi�l��%�f�B���`����,�>��9�}�~6���v�a�M�����?L1q"Y���������9?����F[LicR��0	3��a���Z�v�XW�\b�Ap*��:�)���*u����g�[�4YrL�h�a�K�TL���F�����;r��c�����f�Q�������Pe��=��G4QFI����hrA�Xs��������.Xf�q{Ir�L��!��ls�OL{B�BicKW���W�M�-�*���H��1�M�����T��������h�`���l#>���nT�H�qR[�&��}��/���r���<��T�$��#���V���e%��~���v����;��g�����^����|�.��A��B�)_��4W�+��(O��2���0�6+��5HMv@%e�L&��TRvD�(�
tdoF����3����c�r����%n_�Y&�7a Q�M�#�f���*U�UZr�������]��Ef�,���������@���Yue��ed��0`'��%S-g|�~����w��W��Xy�U�l��J���U���.!D��,�����r�\_�Ss!EvGj��A�4��LV�	��NN��<+�r��W&��$|3����E�C��� ��/��A�5�#������-���P��b�X�`���V~y���]$����3�Y	������>;::~��i�w��kQkf���6w���9�g���c
9�����[J��d�����u�N���~��A+�*�;Vrm�M�V�#�gIj����R�*jF?���c���� j�-����Us�Pj��j���x���-\��K`�9�Kw��A�����7��������@���0v�wm��&Ks���
"[���,L���=v�c���"��F3Nf�(����pMU{U��%AZ���
��D~Px��.�@�����K6O��%�;(q���du�����}���^���<i�S�����������Vn8�yW�tG1W!i�U��e��}H%M�o������:���p�&�?��5�Kxm��:P�(����Z��6���!�S���*��Mc�:��!5'a�H���4!���B����y3c�V[V�L�7R�2y ���/:\{]-�}b�I0$_�x�������\YP���]�q��VR��5~�V�\ ��z(����E��]f��_,k���fm��X�m��)9s�t��w��n^�A���k@[�(p ��lq����xA_��/L���+���"�5�f�"w0�2��6��$���[�e������q��9�C��-|� #ed`������g��kug��F�E���V���W*���{Uf�D��d{�Kh��K��6�r��h���]8S��[OO��fn��v2i;��t~��0���n���y����h�E�oc@����s�$
��{�F��������gq}3���N��d���W��g����f4�������_�'�xeg������������Nn4Oo�������������u�{{(|;:������U�� ����.�]��{��4:������n��
�?	����3��������w���w�d�p�����L���ww+�?��
w^m���e�������'����~��>������	fz~7��~^1<='W�o..�X��>O�2Z4�$�i��]^������v�o]��7�s��o���S�!e�1�EHi�I
 C�2�k��R�7l^�I����7(L�*���n���7���q�16��.�#�n����A�G_��vVI�a����6��>P�@]�&�hY������sDl���Y�����#��C�����u����������iq�/Wf��l���r��:6l�D�����{taD�(�4��vOv�������g�wZ�y5�?�1��:��B��V%���,'6z �-q���W`|�����Ey����-p��D~�9��d���P��;�����`�~{��b�/X����+����{���=[���)]��=�?���#?�@�?����:����__I�G�� �����#�7����By���o�\�V��K<�MA���r-�E�K�5q�VJ�6��C)Co4M�n������=\��>�5Y�C%��2��-���������b�e+4���`��}�C�pa�{���EW���@��L�,����h��eu+w�������2��������Z?�%��:|�D�Q���:��4V\���K��JnP4�1�|���<����v��%�������j�B������i�^���p�k���i)�<JZ)��v���{#�-)��Z��PeP��[��r�_u��;�^T%}�2v��^R�T��������z���F�����r��D�|�����>2�8[F&�����]=���ft>�Z�7�!��4�kH!���"��(�S d7��_o��Z�&�~��K�s�d[�b"��9��	�F@ e����V!��V��.	`��t����}���2X�C�	�LMI
�{�?>�}z`8���k���=�2<�� i�:�C�y��<��7����rD?IO;C���ih��LF���J ��m�~*��O3�Dv����`����d.9��>��K����H���8>�xX; ��o�f8RI���ws�d
����4���� d��I�4��Z���������������rS=�w�G��I�G�1\�=L~��X�<���e���Kd����p�_�Yf�������|,�!�m����������c��#���,��V��~��"A`�V6g��d���9�{Y��������8C�>^�d&��T�#�DS�������=��W���V�����f�V���t�s�\��������y.����c
29< L�H�v��<O� B�>������g������>��?R<�GTA�2���Vp0E��#
0�4K����~)�T����-7�C�K
���}��MB�W�t&
��-�w$r�Ty��o	��_x����P�?`�\��a2��R����������n�Iw`3�"�u����������A�;��w\�B���y[�G����K�z������5��{*� �����
WI�
u���6�X��#��V�����~�i�������]��
�i��T��y$����e���L�?�p����
�qW��nO��4c�y���QMQ�LA�"f����^���}����:�^L@@c	��T���/���$���g�F����cB)q&@��;$��xM�����4)��yw�f(l�F��k���o|�/N���8�n����$*N���c[]�)
+����F��<�5I��\��*I���!`KY�!��I���gY���$�_���M*WX��X�N���������G���2��D�47��r����+�OC���1���y���,�@X�<�K��I��g
u�Bn��2���f�y�� ������P���09��#���2�D�E��AF/�b�ja����@+I��U~��iP�U�US�D��o[l<�SI��q]�&x�Lhf����h����^�7Z��n��c5�{�0W����M�x6ij���2�
[��,��G�Gi,F���������zw	����k���%n���
x-"�I��c���Oiz��G
Y��n��!�s���[A!y
9���R[���
�����]��*�R��i�~������%x*���T�8�^�R��{l�"<��mz%�.W���Kq���RN�y��"�<�WA���Ip���j���+���r�I��������[%�q�����������U
*��
��������FCN��Q�H���d]����W4�F�]��"�.�����r	��k� p������J��Pmd������l(�h��%fmT�,���<������j�������V&����s�����{
$�?��i�D?�(]9y����%�F��.^\���S�I��zX��3�,��x4#Z��S(��~|o�����d2��H���?D���A\#���������is9%[[nA���:���)��s�Z�N���Tq����5MP�� R����c�TC5sM����|q���x
 ��v):�g�������*b������rVU	 V��1o%�W��X��W
�����B�)�4��f��C������@^%���lcP�/A���K5@���[gz�D
�V�ED�'M�M��MG�mv_�<8<��?^puY6�EC+���U�����P�uR��Hc'j�
��p�p�?r�
�*L�@P&�ceF��H�,gW�
�+R��m�)W��lF/ucdN������S���q���7!|�i��1�EF��W���(A��Bn#����$U^,��Hm�G�S�Y��(�p�F$���
EFA�{���r:Ev)-������S=�g�`������� �'����y�;<�������m/KK�
�jd�e���;UFzv
Mw����{���������&��uV�4��f�"IK%)����^�T��`�K�e��r�A��SDhFw#uT~��c�f�i����J�j�}��)`��2J�K�2�p�������79��t!�_������<gw��wZ�����{���x�f�Fb��z�Uq���I���������(\<��������6������Wz���g\�[Q���*����<;�N����$�dv�|>���b�� ��;�h�p3�������������?}�O@�QL�G���G?�o??<����-|�S����2o����w��8��z#����|��c�OO5���M�N���� sCC���������q����7��D �1P^���u���>C���v.9@��L�`�nd������u��rf�p��cl����S����_�+c1
���i�w�tI��$�����Z�j���Y�yvw���>�������'/�G��i�A���,4�I��k��|&uX�7��=�?�Y
|�*�
,_�������g��2�_��{�lw��U�s�?q��{y���W�;'G�[������/_o~�����W!�`[$�������=X\yJ$7�>)���U��e�lH�����
,����9H�����[��[X�
we�/����>�0�����m'�����������'[/Nv����o�y����H�B~��������������F=��
�>8|Bi��<���>X�
���mT��t�_��cgyH�2�������L�s-1���3��6��`�)B*]8.�9d�$�6���{j
�3�b0���(e����A��~�J�f��gR�8�d�30a~Z��P2���x�Q+��������f8��iY=��;/�Q�����B@�q������EO���B~�7f
�����O����?,��_�I��z�^|���������xh6���N�l�v-��o����c��Y)V�
�����<�We���-6��[�F�������")j�������-�u�\��B�(�;�l{����|$��X(������f?i�,�����[���)��7�������U8j�K�R(��R	������U�)��d��?�� D`f����������L�q�fM�doP|��Y�Q�f}#E���;��1�@z����t)?���p�|��8�@[b	�G�X�@��Q��X�Xl�����E�c�������9��m��jX�}S�~�]M�\n�����6B������&��^��+�%��.-���Ta1cT@xE!���\U9u�����0����=�``k6=��N$�1��$#��}�a��%K���h�������F�:��Ok�i�CB��%fi�7_��H�jZu��e�'�Xi��7t�v���K�s�
�z��CY���\��f�xC�:�$�h���`�w��iP�(��i�_�5q�N�[��@��	81��n%��z����pvr�n=���7���������"�$�R�5t����h�
#56����4�C]E/�K���zK8�7�;��u!���?�n�44b��#�I��%�i!�~C�y����Nq!��U8�QN���D;P<s���/���o
X�x�q3�J=��KI��8;M�����V��G�$�k��M��&��������I���SrG(�%"������Fq,E�a�d#�&q�w�������P���~����/M�-b��vO���ke��d��N��-F��W��
����]�R:��W2/��q�x��|.%��d��������q�( r����s���c����x�~q��@	)H7�/�$Bw�/�x�I���} <h%� ��d�r���	X���/Li���t���+�:N�\Ow?nPl^b�`�y}������+���I�Gk�U�V,�*6�2�������G4�C?PF�������
����1N��2
th^���l�����I��{�n�je�nhd+�x�S��1����*���):�^�r���p��vdD��93�#�~�E������0Ma����+F�H�� ��3~�����C����	D�e)�31�L�W���
v��;������ �1�]G'���F�3p�E"_��j�����y� P][�������ve������?���������/!&�;R	�bc]��8H����m�����]}������1��pcMc���Tw4������x�O74���fb7[5�I�yW���dhA�SA8�N���R��Bl��-�j��P.�iM�'���d�$d��1��E��h��4�)�,���r4�h��D�����i
����A����r���
\M���L����4�_�������B������|��Z���!p_bL��d���y��I��c�vRoCM��\�)�������������b-�����UNnp�j#�X����������[���I�)J�����
G�.�`�3�Zo��4�\�*v"��d�yRNj	����a��^�<;9|��L���[��G��UU
�(r&������CB�ycIW���f�9�-Mn:���q��z	\K�PI)��L
w5�H�����w��\�\�%t��1p!�'�m�j�4$�d���F�?���-����-������s4�=E�Y6L��N�Or|n(���hN?1,b����*g3%�T�1�+�uQ&��K��6�*��zgbn�����N��D����Glsq�������jvVmxV��\XC$���zu���3�De��i��&n<������R�`�6�%�Z��L]��5���A��y	l-��{����4���5c�bV��u-�7����	�?�� ���?� ~`�WL�]�Z<���jd�g>����R'
SM>��SS��=�
�v*{�#� (������+zf�9�'y��[{'@o�v���c��-��!!�^:�,.L9���
��ke�H:�����I2�f����������r0�����2U*3�uZ��������|��E�^�rQ����Mq>�u�$��|
"���d�:3����m#MfQ�W��*�s2O5�4;����������}��\� ��g-*>W������z��uQx~N:�6�#���?�]�5PY���LR8$��&�E��N1����
�/�*��@[�"�n	�l��&�Y������DH��K�rk�{(���|l��g~����bU�����YKn+���c'�:~��-�����>�-��E�����"�G��-t-�VM���������j[�����y&x\y[��_����������xK������pT�_&9����������#��xA��3�[��N���gz�����:�U�6_ZP�!�n��xO��
e�M=�p�K*��/��Z=!�@����3T������I[MA��(J�n�
�W��yp-�B��u$�F9�� ��F�T��6%Ri��q������>�}�����x�������n{*
L�������E�p������8�+��l>�F#f�y(����r�H�����)���V�k��FW��)�2YK��!w��;����=vWK���RkS~���0��j�-3-��;�Gn6�\)o��W�	�M�2jkE
I$s��%�����N�����7Z70�0f�/k��0���`�@/K�q�hV[v���V�����c��{@����g��k����;v�T���	��8��+�u3��C	R��7��� z�<�L5������������yZ�R]���>�C��ej������4�LS���KU^U����vh��n1QPWg��@�{��E��I�Y��r����)F����T��2�Q6rp	���`467%1���=
�Jm�\�3���9b�!��I�����I��I��?�������N�ww�>�E���{[�Olq�L�?�P�B�^�*��.�w���������b��1E���~�k���4�R���/-�L�$�b����"q�Vb�"������f��f��iz�\z8E�-�y&g9���:�m�T0e���w�!�C40��?�b\l�{^:z�.�!\�1�4F��l���8�p���tB�OV�<��9�.��O�����h�Yv���������10��C��-�3I���.kY���{|A0�M��_q���H�Q����w��TBH@��6��-�X��0�b Y�"o�A��'dZ�H�s��&��A\�*���R+�]��
��
�D��?�������1����r����m��[�������,W&����y�NFbp���G��4}IE�zJOv�Y% Y��00���B��z��_��T:,���>&N�i��X�s�!��[��/&������3t���O�����f����6CC��f��Jyrz�QJ�1�3�zr����*Y,��W���:(
�=r5p��J]�@d�����U]��|�L��
�������1��hB����g����y�(��P�s���9'��
�|��/p�AB1���������/�������Aq������@e�2<M\�h`YY�	��d�`E���p&z'�f���TDdEEf�7�_��G��"*�!�q2A6��5�%>P�cT�_O�+`ic�y��C�?�����n[�2�e��2!2��:2B����Y3KJ2m3���!Dl\��
�M�z8�
5Y�������� ��MEmy������5��H�"j x
WzV�	e�G1��g`�c�j�j����=��C��(�]��k�����fZ���G�����2e��tl�:<���+����
&36f*��:���sM&O}I�"��t����1	!��6����/V��|3�F�TZ]�������
0010-wal_decoding-Documentation-for-replication-slots-and.patch.gzapplication/x-patch-gzipDownload
0011-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gzapplication/x-patch-gzipDownload
0012-slot-hack-up-pg_receivexlog-support.patch.gzapplication/x-patch-gzipDownload
#32Thom Brown
thom@linux.com
In reply to: Andres Freund (#31)
Re: Changeset Extraction v7.3

On 27 January 2014 16:20, Andres Freund <andres@2ndquadrant.com> wrote:

Hi,

Here's the next version of the patchset. The following changes have been
made:
* move xmin pegging and more logic responsibility to procarray.c
* split all support for changeset extraction from the initial slot patch
* always register an before_shmem_exit handler when
max_replication_slots is registered, not just while a slot is acquired
* move some patch hunks to earlier patches, especially the
ReplicationSlotAcquire() call for physical rep that accidentally
slipped and the SQL accessible slot manipulation functions
* minor stuff

0001 doesn't apply cleanly due to commit
ea9df812d8502fff74e7bc37d61bdc7d66d77a7f.

The rest are fine.

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#33Robert Haas
robertmhaas@gmail.com
In reply to: Thom Brown (#32)
Re: Changeset Extraction v7.3

On Tue, Jan 28, 2014 at 11:49 AM, Thom Brown <thom@linux.com> wrote:

On 27 January 2014 16:20, Andres Freund <andres@2ndquadrant.com> wrote:

Hi,

Here's the next version of the patchset. The following changes have been
made:
* move xmin pegging and more logic responsibility to procarray.c
* split all support for changeset extraction from the initial slot patch
* always register an before_shmem_exit handler when
max_replication_slots is registered, not just while a slot is acquired
* move some patch hunks to earlier patches, especially the
ReplicationSlotAcquire() call for physical rep that accidentally
slipped and the SQL accessible slot manipulation functions
* minor stuff

0001 doesn't apply cleanly due to commit
ea9df812d8502fff74e7bc37d61bdc7d66d77a7f.

The rest are fine.

I've rebased it here and am hacking on it still.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#34Robert Haas
robertmhaas@gmail.com
In reply to: Robert Haas (#33)
Re: Changeset Extraction v7.3

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com> wrote:

I've rebased it here and am hacking on it still.

Andres and I are going back and forth between our respective git repos
hacking on this, and I think we're getting there, but I have a
terminological question which I'd like to submit to a wider audience:

The point of Andres's patch set is to introduce a new technology
called logical decoding; that is, the ability to get a replication
stream that is based on changes to tuples rather than changes to
blocks. It could also be called logical replication. In these
patches, our existing replication is referred to as "physical"
replication, which sounds kind of funny to me. Anyone have another
suggestion?

There are a lot of ways to slice the space of possible replication
solutions. We currently talk about "streaming replication" (as
opposed to "archiving") and "synchronous replication" (as opposed to
asynchronous), but this is a new distinction. At least in theory,
whether replication is "physical" or logical is independent of whether
it's based on streaming or archiving and also of whether it's
synchronous or asynchronous. So we can't for example talk about
"logical replication" in opposition to "streaming replication"; that's
comparing apples and oranges. We need a pair of new terms, and I
can't immediately think of anything better than physical/logical, but
it still sounds somewhat awkward to me so ... anyone else have an
idea?

Thanks,

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#35Thom Brown
thom@linux.com
In reply to: Robert Haas (#34)
Re: Changeset Extraction v7.3

On 28 January 2014 21:37, Robert Haas <robertmhaas@gmail.com> wrote:

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com> wrote:

I've rebased it here and am hacking on it still.

Andres and I are going back and forth between our respective git repos
hacking on this, and I think we're getting there, but I have a
terminological question which I'd like to submit to a wider audience:

The point of Andres's patch set is to introduce a new technology
called logical decoding; that is, the ability to get a replication
stream that is based on changes to tuples rather than changes to
blocks. It could also be called logical replication. In these
patches, our existing replication is referred to as "physical"
replication, which sounds kind of funny to me. Anyone have another
suggestion?

Logical and Binary replication?

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#36Andres Freund
andres@2ndquadrant.com
In reply to: Thom Brown (#35)
Re: Changeset Extraction v7.3

On 2014-01-28 21:48:09 +0000, Thom Brown wrote:

On 28 January 2014 21:37, Robert Haas <robertmhaas@gmail.com> wrote:

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com> wrote:

I've rebased it here and am hacking on it still.

Andres and I are going back and forth between our respective git repos
hacking on this, and I think we're getting there, but I have a
terminological question which I'd like to submit to a wider audience:

The point of Andres's patch set is to introduce a new technology
called logical decoding; that is, the ability to get a replication
stream that is based on changes to tuples rather than changes to
blocks. It could also be called logical replication. In these
patches, our existing replication is referred to as "physical"
replication, which sounds kind of funny to me. Anyone have another
suggestion?

Logical and Binary replication?

Unfortunately changeset extraction output's can be binary data...

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#37Thom Brown
thom@linux.com
In reply to: Andres Freund (#36)
Re: Changeset Extraction v7.3

On 28 January 2014 21:56, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-01-28 21:48:09 +0000, Thom Brown wrote:

On 28 January 2014 21:37, Robert Haas <robertmhaas@gmail.com> wrote:

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com> wrote:

I've rebased it here and am hacking on it still.

Andres and I are going back and forth between our respective git repos
hacking on this, and I think we're getting there, but I have a
terminological question which I'd like to submit to a wider audience:

The point of Andres's patch set is to introduce a new technology
called logical decoding; that is, the ability to get a replication
stream that is based on changes to tuples rather than changes to
blocks. It could also be called logical replication. In these
patches, our existing replication is referred to as "physical"
replication, which sounds kind of funny to me. Anyone have another
suggestion?

Logical and Binary replication?

Unfortunately changeset extraction output's can be binary data...

"system"?
"cluster"?
"full"?
"complete"?

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#38Rod Taylor
rod.taylor@gmail.com
In reply to: Andres Freund (#36)
Re: Changeset Extraction v7.3

On Tue, Jan 28, 2014 at 4:56 PM, Andres Freund <andres@2ndquadrant.com>wrote:

On 2014-01-28 21:48:09 +0000, Thom Brown wrote:

On 28 January 2014 21:37, Robert Haas <robertmhaas@gmail.com> wrote:

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com>

wrote:

I've rebased it here and am hacking on it still.

Andres and I are going back and forth between our respective git repos
hacking on this, and I think we're getting there, but I have a
terminological question which I'd like to submit to a wider audience:

The point of Andres's patch set is to introduce a new technology
called logical decoding; that is, the ability to get a replication
stream that is based on changes to tuples rather than changes to
blocks. It could also be called logical replication. In these
patches, our existing replication is referred to as "physical"
replication, which sounds kind of funny to me. Anyone have another
suggestion?

Logical and Binary replication?

Unfortunately changeset extraction output's can be binary data...

Perhaps Logical and Block?

The existing replication mechanism is similar to block-based disk backups.
It's the whole thing (not parts) and doesn't have any concept of
database/directory.

#39David Fetter
david@fetter.org
In reply to: Rod Taylor (#38)
Re: Changeset Extraction v7.3

On Tue, Jan 28, 2014 at 05:31:25PM -0500, Rod Taylor wrote:

On Tue, Jan 28, 2014 at 4:56 PM, Andres Freund <andres@2ndquadrant.com>wrote:

On 2014-01-28 21:48:09 +0000, Thom Brown wrote:

On 28 January 2014 21:37, Robert Haas <robertmhaas@gmail.com> wrote:

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com>

wrote:

I've rebased it here and am hacking on it still.

Andres and I are going back and forth between our respective git repos
hacking on this, and I think we're getting there, but I have a
terminological question which I'd like to submit to a wider audience:

The point of Andres's patch set is to introduce a new technology
called logical decoding; that is, the ability to get a replication
stream that is based on changes to tuples rather than changes to
blocks. It could also be called logical replication. In these
patches, our existing replication is referred to as "physical"
replication, which sounds kind of funny to me. Anyone have another
suggestion?

Logical and Binary replication?

Unfortunately changeset extraction output's can be binary data...

Perhaps Logical and Block?

The existing replication mechanism is similar to block-based disk backups.
It's the whole thing (not parts) and doesn't have any concept of
database/directory.

+1 for this terminology. It's descriptive.

Cheers,
David.
--
David Fetter <david@fetter.org> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: david.fetter@gmail.com
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#40Andreas Karlsson
andreas@proxel.se
In reply to: Andres Freund (#36)
Re: Changeset Extraction v7.3

On 01/28/2014 10:56 PM, Andres Freund wrote:

On 2014-01-28 21:48:09 +0000, Thom Brown wrote:

On 28 January 2014 21:37, Robert Haas <robertmhaas@gmail.com> wrote:

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com> wrote:
The point of Andres's patch set is to introduce a new technology
called logical decoding; that is, the ability to get a replication
stream that is based on changes to tuples rather than changes to
blocks. It could also be called logical replication. In these
patches, our existing replication is referred to as "physical"
replication, which sounds kind of funny to me. Anyone have another
suggestion?

Logical and Binary replication?

Unfortunately changeset extraction output's can be binary data...

I think "physical" and "logical" are fine and they seem to be well known
terminology. Oracle uses those words and I have also seen many places
use "physical backup" and "logical backup", for example on Barman's
homepage.

--
Andreas Karlsson

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#41Robert Haas
robertmhaas@gmail.com
In reply to: Andreas Karlsson (#40)
Re: Changeset Extraction v7.3

On Tue, Jan 28, 2014 at 7:43 PM, Andreas Karlsson <andreas@proxel.se> wrote:

I think "physical" and "logical" are fine and they seem to be well known
terminology. Oracle uses those words and I have also seen many places use
"physical backup" and "logical backup", for example on Barman's homepage.

There's certainly something to be said for this.

Another idea I had this evening was "logical replication" and
"WAL-based replication", but that's a bit confusing too since logical
rep. is going to use WAL as an underlying technology.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#42Albe Laurenz
laurenz.albe@wien.gv.at
In reply to: Andreas Karlsson (#40)
Re: Changeset Extraction v7.3

Andreas Karlsson wrote:

On 01/28/2014 10:56 PM, Andres Freund wrote:

On 2014-01-28 21:48:09 +0000, Thom Brown wrote:

On 28 January 2014 21:37, Robert Haas <robertmhaas@gmail.com> wrote:

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com> wrote:
The point of Andres's patch set is to introduce a new technology
called logical decoding; that is, the ability to get a replication
stream that is based on changes to tuples rather than changes to
blocks. It could also be called logical replication. In these
patches, our existing replication is referred to as "physical"
replication, which sounds kind of funny to me. Anyone have another
suggestion?

Logical and Binary replication?

Unfortunately changeset extraction output's can be binary data...

I think "physical" and "logical" are fine and they seem to be well known
terminology. Oracle uses those words and I have also seen many places
use "physical backup" and "logical backup", for example on Barman's
homepage.

+1

I think it also fits well with the well-known terms "physical [database]
design" and "logical design". Not that it is the same thing, but I
believe that every database person, when faced with the distiction
"physical" versus "logical", will conclude that the former refers to
data placement or block structure, while the latter refers to the
semantics of the data being stored.

Yours,
Laurenz Albe

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#43Christian Convey
christian.convey@gmail.com
In reply to: Albe Laurenz (#42)
Re: Changeset Extraction v7.3

It seems to me that the terms "physical", "logical", and "binary" are
always relative to the perspective of the component being worked on.

"Physical" often means "one level of abstraction below mine, and upon which
my work builds". "Logical" means "my work's level of abstraction". And
"Binary" means "data which I'm not going to pretend I know or care how to
interpret."

So I'd suggest "block" and "tuple", perhaps.

On Wed, Jan 29, 2014 at 4:25 AM, Albe Laurenz <laurenz.albe@wien.gv.at>wrote:

Show quoted text

Andreas Karlsson wrote:

On 01/28/2014 10:56 PM, Andres Freund wrote:

On 2014-01-28 21:48:09 +0000, Thom Brown wrote:

On 28 January 2014 21:37, Robert Haas <robertmhaas@gmail.com> wrote:

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com>

wrote:

The point of Andres's patch set is to introduce a new technology
called logical decoding; that is, the ability to get a replication
stream that is based on changes to tuples rather than changes to
blocks. It could also be called logical replication. In these
patches, our existing replication is referred to as "physical"
replication, which sounds kind of funny to me. Anyone have another
suggestion?

Logical and Binary replication?

Unfortunately changeset extraction output's can be binary data...

I think "physical" and "logical" are fine and they seem to be well known
terminology. Oracle uses those words and I have also seen many places
use "physical backup" and "logical backup", for example on Barman's
homepage.

+1

I think it also fits well with the well-known terms "physical [database]
design" and "logical design". Not that it is the same thing, but I
believe that every database person, when faced with the distiction
"physical" versus "logical", will conclude that the former refers to
data placement or block structure, while the latter refers to the
semantics of the data being stored.

Yours,
Laurenz Albe

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#44Robert Haas
robertmhaas@gmail.com
In reply to: Robert Haas (#33)
1 attachment(s)
Re: Changeset Extraction v7.3

On Tue, Jan 28, 2014 at 11:53 AM, Robert Haas <robertmhaas@gmail.com> wrote:

I've rebased it here and am hacking on it still.

OK. The attached patch is a combination of Andres' first two patches
with lots more changes from both Andres and myself. At this point,
I'm pretty happy with this, and propose to commit the attached
version, absent objection. All by itself, it provides a useful new
option for users, and it sets the stage for the subsequent logical
decoding patches as well. For those not following along closely,
here's the short version: if you choose to create a replication slot,
you can make the master retain the exact amount of WAL that the
standby still needs, rather than guessing what value to set for
wal_keep_segments; also, you can avoid hot standby conflicts even when
the connection between master and slave is interrupted (but the master
will bloat if the interruption is long, so watch out). For logical
decoding, this functionality is essential rather than nice-to-have.

Here's a summary of what we've changed since the last version Andres posted:

- Fairly extensive revisions to slot error handling, eliminating the
PG_TRY/PG_CATCH blocks that were present before (which I didn't
believe would work as designed) and cleaning up some corner cases to
eliminate unnecessary failures.
- Rigid enforcement of existing PG practices around spinlocks,
volatile pointers, and memory barriers.
- Modification of the on-disk format for slots so that we don't
serialize junk that properly only lives in memory.
- Removal of various references to decoding and logical replication
that properly belong in subsequent patches.
- Support for using slots via a new recovery.conf parameter,
primary_slotname, and a new pg_receivexlog option, --slot. I felt
this was important because, without this, you couldn't test that it
actually works without applying the remainder of Andres's patch set,
and even then you could mostly only test logical replication. With
it, this is an independently useful and testable feature.
- Exclude pg_replslot from base backups. This might need more thought
and documentation; people who use the filesystem method to perform
backups might need to be advised to remove this directory in some
cases also, or people who use pg_basebackup might want to keep it in
some cases (not sure).
- Lots of renaming to make the names more clear and consistent.
- Lots of bug fixes, minor tinkering, comment changes, and cleanups.
- Documentation.

For those wishing to see the blow-by-blow:

http://git.postgresql.org/gitweb/?p=users/rhaas/postgres.git;a=shortlog;h=refs/heads/slot2

In the future (i.e. post-9.4), I think we'll likely want to extend
this in a bunch of interesting ways. I strongly suspect people are
going to want to have an option for slots that pin the LSN but not
xmin, and I also think they're going to want slots that hold LSN or
xmin for a certain amount of time after a disconnect but then give up,
or maybe a certain number of segments/transaction IDs and then give
up. Nonwithstanding those important improvements, I think this is a
very credible v1 of this functionality.

Thanks,

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Attachments:

slot.patchtext/x-patch; charset=US-ASCII; name=slot.patchDownload
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 2230c93..19fe69e 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -234,6 +234,11 @@
      </row>
 
      <row>
+      <entry><link linkend="catalog-pg-replication-slots"><structname>pg_replication_slots</structname></link></entry>
+      <entry>replication slot information</entry>
+     </row>
+
+     <row>
       <entry><link linkend="catalog-pg-seclabel"><structname>pg_seclabel</structname></link></entry>
       <entry>security labels on database objects</entry>
      </row>
@@ -5157,6 +5162,100 @@
 
  </sect1>
 
+ <sect1 id="catalog-pg-replication-slots">
+  <title><structname>pg_replication_slots</structname></title>
+
+  <indexterm zone="catalog-pg-replication-slots">
+   <primary>pg_replication_slots</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_replication_slots</structname> view provides a listing
+   of all replication slots that currently exist on the database cluster,
+   along with their current state.
+  </para>
+
+  <para>
+   For more on replication slots,
+   see <xref linkend="streaming-replication-slots">.
+  </para>
+
+  <table>
+
+   <title><structname>pg_replication_slots</structname> Columns</title>
+
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry><structfield>slot_name</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>A unique, cluster-wide identifier for the replication slot</entry>
+     </row>
+
+     <row>
+      <entry><structfield>slot_type</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>The slot type - <literal>physical</> or <literal>logical</></entry>
+     </row>
+
+     <row>
+      <entry><structfield>datoid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry>
+      <entry>The oid of the database this slot is associated with, or
+      null. Only logical slots have an associated database.</entry>
+     </row>
+
+     <row>
+      <entry><structfield>database</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.datname</literal></entry>
+      <entry>The name of the database this slot is associated with, or
+      null. Only logical slots have an associated database.</entry>
+     </row>
+
+     <row>
+      <entry><structfield>active</structfield></entry>
+      <entry><type>boolean</type></entry>
+      <entry></entry>
+      <entry>True if this slot is currently actively being used</entry>
+     </row>
+
+     <row>
+      <entry><structfield>xmin</structfield></entry>
+      <entry><type>xid</type></entry>
+      <entry></entry>
+      <entry>The oldest transaction that this slot needs the database to
+      retain.  <literal>VACUUM</literal> cannot remove tuples deleted
+      by any later transaction.
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>restart_lsn</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>The address (<literal>LSN</literal>) of oldest WAL which still
+      might be required by the consumer of this slot and thus won't be
+      automatically removed during checkpoints.
+      </entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+ </sect1>
+
 
  <sect1 id="catalog-pg-seclabel">
   <title><structname>pg_seclabel</structname></title>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1b5f831..000a46f 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2348,6 +2348,25 @@ include 'filename'
        </listitem>
       </varlistentry>
 
+      <varlistentry id="guc-max-replication-slots" xreflabel="max_replication_slots">
+       <term><varname>max_replication_slots</varname> (<type>integer</type>)</term>
+       <indexterm>
+        <primary><varname>max_replication_slots</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         Specifies the maximum number of replication slots
+         (see <xref linkend="streaming-replication-slots"> that the server
+         can support. The default is zero.  This parameter can only be set at
+         server start.
+         <varname>wal_level</varname> must be set
+         to <literal>archive</literal> or higher to allow replication slots to
+         be used. Setting it to a lower value than the number of currently
+         existing replication slots will prevent the server from starting.
+        </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry id="guc-wal-keep-segments" xreflabel="wal_keep_segments">
        <term><varname>wal_keep_segments</varname> (<type>integer</type>)</term>
        <indexterm>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 9816163..8dbfd80 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -16278,6 +16278,76 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
    </para>
   </sect2>
 
+  <sect2 id="functions-replication">
+   <title>Replication Functions</title>
+
+   <para>
+    PostgreSQL exposes a number of functions for controlling and interacting
+    with replication features. See <xref linkend="streaming-replication">
+    and <xref linkend="streaming-replication-slots">.
+   </para>
+
+   <para>
+    Many of these functions have equivalent commands in the replication
+    protocol; see <xref linkend="protocol-replication">.
+   </para>
+
+   <para>
+    The sections <xref linkend="functions-snapshot-synchronization">, <xref
+    linkend="functions-recovery-control"> and <xref
+    linkend="functions-admin-backup"> are also relevant for replication.
+   </para>
+
+   <table id="functions-replication-table">
+    <title>Replication <acronym>SQL</acronym> Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row>
+       <entry>Function</entry>
+       <entry>Return Type</entry>
+       <entry>Description</entry>
+      </row>
+     </thead>
+     <tbody>
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_create_physical_replication_slot</primary>
+        </indexterm>
+        <literal><function>pg_create_physical_replication_slot(<parameter>slotname</parameter> <type>text</type>, <parameter>plugin</parameter> <type>text</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>slotname</parameter> <type>text</type>, <parameter>xlog_position</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Creates a new physical replication slot named
+        <parameter>slotname</parameter>. Streaming changes from a physical slot
+        is only possible with the walsender protocol - see <xref
+        linkend="protocol-replication">. Corresponds to the walsender protocol
+        command <literal>CREATE_REPLICATION_SLOT ... PHYSICAL</literal>.
+       </entry>
+      </row>
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_drop_replication_slot</primary>
+        </indexterm>
+        <literal><function>pg_drop_replication_slot(<parameter>slotname</parameter> <type>text</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>slotname</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Drops the physical or logical replication slot
+        named <parameter>slotname</parameter>. Same as walsender protocol
+        command <literal>DROP_REPLICATION_SLOT</>.
+       </entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
+  </sect2>
+
   <sect2 id="functions-admin-dbobject">
    <title>Database Object Management Functions</title>
 
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index e2e5ac9..9d43586 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -643,7 +643,9 @@ protocol to make nodes agree on a serializable transactional order.
     entries in <filename>pg_hba.conf</> with the database field set to
     <literal>replication</>.  Also ensure <varname>max_wal_senders</> is set
     to a sufficiently large value in the configuration file of the primary
-    server.
+    server. If replication slots will be used,
+    ensure that <varname>max_replication_slots</varname> is set sufficiently
+    high as well.
    </para>
 
    <para>
@@ -750,13 +752,14 @@ archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r'
 
    <para>
     If you use streaming replication without file-based continuous
-    archiving, you have to set <varname>wal_keep_segments</> in the master
-    to a value high enough to ensure that old WAL segments are not recycled
-    too early, while the standby might still need them to catch up. If the
-    standby falls behind too much, it needs to be reinitialized from a new
-    base backup. If you set up a WAL archive that's accessible from the
-    standby, <varname>wal_keep_segments</> is not required as the standby can always
-    use the archive to catch up.
+    archiving, the server might recycle old WAL segments before the standby
+    has received them.  If this occurs, the standby will need to be
+    reinitialized from a new base backup.  You can avoid this by setting
+    <varname>wal_keep_segments</> to a value large enough to ensure that
+    WAL segments are not recycled too early, or by configuration a replication
+    slot for the standby.  If you set up a WAL archive that's accessible from
+    the standby, these solutions are not required, since the standby can
+    always use the archive to catch up provided it retains enough segments.
    </para>
 
    <para>
@@ -871,6 +874,81 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
    </sect3>
   </sect2>
 
+  <sect2 id="streaming-replication-slots">
+   <title>Replication Slots</title>
+   <indexterm zone="high-availability">
+    <primary>Replication Slots</primary>
+   </indexterm>
+   <para>
+    Replication slots provide an automated way to ensure that the master does
+    not remove WAL segments until they have been received by all standbys,
+    and that the master does not remove rows which could cause a
+    <link linkend="hot-standby-conflict">recovery conflict</> even when the
+    standby is disconnected.
+   </para>
+   <para>
+    In lieu of using replication slots, it is possible to prevent the removal
+    of old WAL segments using <xref linkend="guc-wal-keep-segments">, or by
+    storing the segments in an archive using <xref linkend="restore-command">.
+    However, these methods often result in retaining more WAL segments than
+    required, whereas replication slots retain only the number of segments
+    known to be needed.  An advantage of these methods is that they bound
+    the space requirement for <literal>pg_xlog</>; there is currently no way
+    to do this using replication slots.
+   </para>
+   <para>
+    Similarly, <varname>hot_standby_feedback</varname>
+    and <varname>vacuum_defer_cleanup_age</varname> provide protection against
+    relevant rows being removed by vacuum, but the former provides no
+    protection during any time period when the standby is not connected,
+    and the latter often needs to be set to a high value to provide adequate
+    protection.  Replication slots overcome these disadvantages.
+   </para>
+   <sect3 id="streaming-replication-slots-manipulation">
+    <title>Querying and manipulating replication slots</title>
+    <para>
+     Each replication slot has a name, which can contain lower-case letters,
+     numbers, and the underscore character.
+    </para>
+    <para>
+     Existing replication slots and their state can be seen in the
+     <link linkend="catalog-pg-replication-slots"><structname>pg_replication_slots</structname></link>
+     view.
+    </para>
+    <para>
+     Slots can be created and dropped either via the streaming replication
+     protocol (see <xref linkend="protocol-replication">) or via SQL
+     functions (see <xref linkend="functions-replication">).
+    </para>
+   </sect3>
+   <sect3 id="streaming-replication-slots-config">
+    <title>Configuration Example</title>
+    <para>
+     You can create a replication slot like this:
+<programlisting>
+postgres=# SELECT * FROM pg_create_physical_replication_slot('node_a_slot');
+  slotname   | xlog_position
+-------------+---------------
+ node_a_slot |
+
+postgres=# SELECT * FROM pg_replication_slots;
+  slot_name  | slot_type | datoid | database | active | xmin | restart_lsn
+-------------+-----------+--------+----------+--------+------+-------------
+ node_a_slot | physical  |      0 |          | f      |      |
+(1 row)
+</programlisting>
+     To configure the standby to use this slot, <varname>primary_slotname</>
+     should be configured in the standby's <filename>recovery.conf</>.
+     Here is a simple example:
+<programlisting>
+standby_mode = 'on'
+primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
+primary_slotname = 'node_a_slot'
+</programlisting>
+    </para>
+   </sect3>
+  </sect2>
+
   <sect2 id="cascading-replication">
    <title>Cascading Replication</title>
 
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 7d99976..832524e 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1401,15 +1401,39 @@ The commands accepted in walsender mode are:
   </varlistentry>
 
   <varlistentry>
-    <term>START_REPLICATION <replaceable class="parameter">XXX/XXX</> TIMELINE <replaceable class="parameter">tli</></term>
+    <term><literal>CREATE_REPLICATION_SLOT</literal> <replaceable class="parameter">slotname</> <literal>PHYSICAL</literal></term>
+    <indexterm><primary>CREATE_REPLICATION_SLOT</primary></indexterm>
+    <listitem>
+     <para>
+      Create a physical replication
+      slot. See <xref linkend="streaming-replication-slots"> for more about
+      replication slots.
+     </para>
+     <variablelist>
+      <varlistentry>
+       <term><replaceable class="parameter">slotname</></term>
+       <listitem>
+         <para>
+          The name of the slot to create. Must be a valid replication slot
+          name (see <xref linkend="streaming-replication-slots-manipulation">).
+         </para>
+       </listitem>
+      </varlistentry>
+     </variablelist>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term><literal>START_REPLICATION</literal> [<literal>SLOT</literal> <replaceable class="parameter">slotname</>] [<literal>PHYSICAL</literal>] <replaceable class="parameter">XXX/XXX</> <literal>TIMELINE</literal> <replaceable class="parameter">tli</></term>
     <listitem>
      <para>
       Instructs server to start streaming WAL, starting at
-      WAL position <replaceable class="parameter">XXX/XXX</> on timeline
-      <replaceable class="parameter">tli</>.
-      The server can reply with an error, e.g. if the requested section of WAL
-      has already been recycled. On success, server responds with a
-      CopyBothResponse message, and then starts to stream WAL to the frontend.
+      WAL position <replaceable class="parameter">XXX/XXX</>. If specified,
+      streaming starts on timeline <replaceable class="parameter">tli</>;
+      otherwise, the server's current timeline is selected. The server can
+      reply with an error, e.g. if the requested section of WAL has already
+      been recycled. On success, server responds with a CopyBothResponse
+      message, and then starts to stream WAL to the frontend.
      </para>
 
      <para>
@@ -1444,6 +1468,14 @@ The commands accepted in walsender mode are:
      </para>
 
      <para>
+      If a slot's name is provided
+      via <replaceable class="parameter">slotname</>, it will be updated
+      as replication progresses so that the server knows which WAL segments -
+      and if <varname>hot_standby_feedback</> is on which transactions -
+      are still needed by the standby.
+     </para>
+
+     <para>
       <variablelist>
       <varlistentry>
       <term>
@@ -1720,6 +1752,26 @@ The commands accepted in walsender mode are:
   </varlistentry>
 
   <varlistentry>
+    <term><literal>DROP_REPLICATION_SLOT</literal> <replaceable class="parameter">slotname</></term>
+    <listitem>
+     <para>
+      Drops a replication slot, freeing any reserved server-side resources. If
+      the slot is currently in use by an active connection, this command fails.
+     </para>
+     <variablelist>
+      <varlistentry>
+       <term><replaceable class="parameter">slotname</></term>
+       <listitem>
+         <para>
+          The name of the slot to drop.
+         </para>
+       </listitem>
+      </varlistentry>
+     </variablelist>
+    </listitem>
+  </varlistentry>
+
+  <varlistentry>
     <term>BASE_BACKUP [<literal>LABEL</literal> <replaceable>'label'</replaceable>] [<literal>PROGRESS</literal>] [<literal>FAST</literal>] [<literal>WAL</literal>] [<literal>NOWAIT</literal>]</term>
     <listitem>
      <para>
diff --git a/doc/src/sgml/recovery-config.sgml b/doc/src/sgml/recovery-config.sgml
index 4a97bb7..b69ce28 100644
--- a/doc/src/sgml/recovery-config.sgml
+++ b/doc/src/sgml/recovery-config.sgml
@@ -418,6 +418,22 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
          </para>
         </listitem>
        </varlistentry>
+       <varlistentry id="primary-slotname" xreflabel="primary_slotname">
+        <term><varname>primary_slotname</varname> (<type>string</type>)</term>
+        <indexterm>
+          <primary><varname>primary_slotname</> recovery parameter</primary>
+        </indexterm>
+        <listitem>
+         <para>
+          Optionally specifies an existing replication slot to be used when
+          connecting to the primary via streaming replication to control
+          resource removal on the upstream node
+          (see <xref linkend="streaming-replication-slots">).
+          This setting has no effect if <varname>primary_conninfo</> is not
+          set.
+         </para>
+        </listitem>
+       </varlistentry>
        <varlistentry id="trigger-file" xreflabel="trigger_file">
         <term><varname>trigger_file</varname> (<type>string</type>)</term>
         <indexterm>
diff --git a/doc/src/sgml/ref/pg_receivexlog.sgml b/doc/src/sgml/ref/pg_receivexlog.sgml
index 19bebb6..2a44af4 100644
--- a/doc/src/sgml/ref/pg_receivexlog.sgml
+++ b/doc/src/sgml/ref/pg_receivexlog.sgml
@@ -225,6 +225,24 @@ PostgreSQL documentation
        </para>
       </listitem>
      </varlistentry>
+
+     <varlistentry>
+      <term><option>--slot</option></term>
+      <listitem>
+        <para>
+         Require <application>pg_receivexlog</application> to use an existing
+         replication slot (see <xref linkend="streaming-replication-slots">).
+         When this option is used, <application>pg_receivexlog</> will report
+         a flush position to the server, indicating when each segment has been
+         synchronized to disk so that the server can remove that segment if it
+         is not otherwise needed.  When using this paramter, it is important
+         to make sure that <application>pg_receivexlog</> cannot become the
+         synchronous standby through an incautious setting of
+         <xref linkend="guc-synchronous-standby-names">; it does not flush
+         data frequently enough for this to work correctly.
+        </para>
+      </listitem>
+     </varlistentry>
     </variablelist>
    </para>
 
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b333d82..7f63185 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -39,6 +39,7 @@
 #include "pgstat.h"
 #include "postmaster/bgwriter.h"
 #include "postmaster/startup.h"
+#include "replication/slot.h"
 #include "replication/walreceiver.h"
 #include "replication/walsender.h"
 #include "storage/barrier.h"
@@ -225,6 +226,7 @@ static TimestampTz recoveryDelayUntilTime;
 /* options taken from recovery.conf for XLOG streaming */
 static bool StandbyModeRequested = false;
 static char *PrimaryConnInfo = NULL;
+static char *PrimarySlotName = NULL;
 static char *TriggerFile = NULL;
 
 /* are we currently in standby mode? */
@@ -485,6 +487,8 @@ typedef struct XLogCtlData
 	uint32		ckptXidEpoch;	/* nextXID & epoch of latest checkpoint */
 	TransactionId ckptXid;
 	XLogRecPtr	asyncXactLSN;	/* LSN of newest async commit/abort */
+	XLogRecPtr	replicationSlotMinLSN;	/* oldest LSN needed by any slot */
+
 	XLogSegNo	lastRemovedSegNo;		/* latest removed/recycled XLOG
 										 * segment */
 
@@ -748,6 +752,7 @@ static void LocalSetXLogInsertAllowed(void);
 static void CreateEndOfRecoveryRecord(void);
 static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);
 static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo);
+static XLogRecPtr XLogGetReplicationSlotMinimumLSN(void);
 
 static bool XLogCheckBuffer(XLogRecData *rdata, bool holdsExclusiveLock,
 				XLogRecPtr *lsn, BkpBlock *bkpb);
@@ -2909,6 +2914,39 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
 }
 
 /*
+ * Record the LSN up to which we can remove WAL because it's not required by
+ * any replication slot.
+ */
+void
+XLogSetReplicationSlotMinimumLSN(XLogRecPtr lsn)
+{
+	/* use volatile pointer to prevent code rearrangement */
+	volatile XLogCtlData *xlogctl = XLogCtl;
+
+	SpinLockAcquire(&xlogctl->info_lck);
+	xlogctl->replicationSlotMinLSN = lsn;
+	SpinLockRelease(&xlogctl->info_lck);
+}
+
+
+/*
+ * Return the oldest LSN we must retain to satisfy the needs of some
+ * replication slot.
+ */
+static XLogRecPtr
+XLogGetReplicationSlotMinimumLSN(void)
+{
+	/* use volatile pointer to prevent code rearrangement */
+	volatile XLogCtlData *xlogctl = XLogCtl;
+	XLogRecPtr		retval;
+	SpinLockAcquire(&xlogctl->info_lck);
+	retval = xlogctl->replicationSlotMinLSN;
+	SpinLockRelease(&xlogctl->info_lck);
+
+	return retval;
+}
+
+/*
  * Advance minRecoveryPoint in control file.
  *
  * If we crash during recovery, we must reach this point again before the
@@ -5478,6 +5516,14 @@ readRecoveryCommandFile(void)
 					(errmsg_internal("primary_conninfo = '%s'",
 									 PrimaryConnInfo)));
 		}
+		else if (strcmp(item->name, "primary_slotname") == 0)
+		{
+			ReplicationSlotValidateName(item->value, ERROR);
+			PrimarySlotName = pstrdup(item->value);
+			ereport(DEBUG2,
+					(errmsg_internal("primary_slotname = '%s'",
+									 PrimarySlotName)));
+		}
 		else if (strcmp(item->name, "trigger_file") == 0)
 		{
 			TriggerFile = pstrdup(item->value);
@@ -6506,6 +6552,12 @@ StartupXLOG(void)
 	XLogCtl->ckptXid = checkPoint.nextXid;
 
 	/*
+	 * Initialize replication slots, before there's a chance to remove
+	 * required resources.
+	 */
+	StartupReplicationSlots(checkPoint.redo);
+
+	/*
 	 * Startup MultiXact.  We need to do this early for two reasons: one
 	 * is that we might try to access multixacts when we do tuple freezing,
 	 * and the other is we need its state initialized because we attempt
@@ -8620,6 +8672,7 @@ CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
 	CheckPointMultiXact();
 	CheckPointPredicate();
 	CheckPointRelationMap();
+	CheckPointReplicationSlots();
 	CheckPointBuffers(flags);	/* performs all required fsyncs */
 	/* We deliberately delay 2PC checkpointing as long as possible */
 	CheckPointTwoPhase(checkPointRedo);
@@ -8938,24 +8991,43 @@ CreateRestartPoint(int flags)
 
 /*
  * Retreat *logSegNo to the last segment that we need to retain because of
- * wal_keep_segments. This is calculated by subtracting wal_keep_segments
- * from the given xlog location, recptr.
+ * either wal_keep_segments or replication slots.
+ *
+ * This is calculated by subtracting wal_keep_segments from the given xlog
+ * location, recptr and by making sure that that result is below the
+ * requirement of replication slots.
  */
 static void
 KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
 {
 	XLogSegNo	segno;
-
-	if (wal_keep_segments == 0)
-		return;
+	XLogRecPtr	keep;
 
 	XLByteToSeg(recptr, segno);
+	keep = XLogGetReplicationSlotMinimumLSN();
 
-	/* avoid underflow, don't go below 1 */
-	if (segno <= wal_keep_segments)
-		segno = 1;
-	else
-		segno = segno - wal_keep_segments;
+	/* compute limit for wal_keep_segments first */
+	if (wal_keep_segments > 0)
+	{
+		/* avoid underflow, don't go below 1 */
+		if (segno <= wal_keep_segments)
+			segno = 1;
+		else
+			segno = segno - wal_keep_segments;
+	}
+
+	/* then check whether slots limit removal further */
+	if (max_replication_slots > 0 && keep != InvalidXLogRecPtr)
+	{
+		XLogRecPtr slotSegNo;
+
+		XLByteToSeg(keep, slotSegNo);
+
+		if (slotSegNo <= 0)
+			segno = 1;
+		else if (slotSegNo < segno)
+			segno = slotSegNo;
+	}
 
 	/* don't delete WAL segments newer than the calculated segment */
 	if (segno < *logSegNo)
@@ -11026,7 +11098,8 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 									 tli, curFileTLI);
 						}
 						curFileTLI = tli;
-						RequestXLogStreaming(tli, ptr, PrimaryConnInfo);
+						RequestXLogStreaming(tli, ptr, PrimaryConnInfo,
+											 PrimarySlotName);
 						receivedUpto = 0;
 					}
 
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 277af61..f02efec 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -613,6 +613,18 @@ CREATE VIEW pg_stat_replication AS
     WHERE S.usesysid = U.oid AND
             S.pid = W.pid;
 
+CREATE VIEW pg_replication_slots AS
+    SELECT
+            L.slot_name,
+            L.slot_type,
+            L.datoid,
+            D.datname AS database,
+            L.active,
+            L.xmin,
+            L.restart_lsn
+    FROM pg_get_replication_slots() AS L
+            LEFT JOIN pg_database D ON (L.datoid = D.oid);
+
 CREATE VIEW pg_stat_database AS
     SELECT
             D.oid AS datid,
diff --git a/src/backend/replication/Makefile b/src/backend/replication/Makefile
index 2dde011..7941cb8 100644
--- a/src/backend/replication/Makefile
+++ b/src/backend/replication/Makefile
@@ -15,7 +15,7 @@ include $(top_builddir)/src/Makefile.global
 override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
 
 OBJS = walsender.o walreceiverfuncs.o walreceiver.o basebackup.o \
-	repl_gram.o syncrep.o
+	repl_gram.o slot.o slotfuncs.o syncrep.o
 
 include $(top_srcdir)/src/backend/common.mk
 
diff --git a/src/backend/replication/README b/src/backend/replication/README
index 60120ed..2f5df49 100644
--- a/src/backend/replication/README
+++ b/src/backend/replication/README
@@ -47,8 +47,9 @@ to fetch more WAL (if streaming replication is configured).
 
 Walreceiver is a postmaster subprocess, so the startup process can't fork it
 directly. Instead, it sends a signal to postmaster, asking postmaster to launch
-it. Before that, however, startup process fills in WalRcvData->conninfo,
-and initializes the starting point in WalRcvData->receiveStart.
+it. Before that, however, startup process fills in WalRcvData->conninfo
+and WalRcvData->slotname, and initializes the starting point in
+WalRcvData->receiveStart.
 
 As walreceiver receives WAL from the master server, and writes and flushes
 it to disk (in pg_xlog), it updates WalRcvData->receivedUpto and signals
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 7d0ed9c..781f678 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -847,6 +847,10 @@ sendDir(char *path, int basepathlen, bool sizeonly, List *tablespaces)
 		if (strcmp(de->d_name, BACKUP_LABEL_FILE) == 0)
 			continue;
 
+		/* Skip pg_replslot, not useful to copy */
+		if (strcmp(de->d_name, "pg_replslot") == 0)
+			continue;
+
 		/*
 		 * Check if the postmaster has signaled us to exit, and abort with an
 		 * error in that case. The error handler further up will call
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 2e057b8..ecec8b3 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -49,7 +49,8 @@ static char *recvBuf = NULL;
 static void libpqrcv_connect(char *conninfo);
 static void libpqrcv_identify_system(TimeLineID *primary_tli);
 static void libpqrcv_readtimelinehistoryfile(TimeLineID tli, char **filename, char **content, int *len);
-static bool libpqrcv_startstreaming(TimeLineID tli, XLogRecPtr startpoint);
+static bool libpqrcv_startstreaming(TimeLineID tli, XLogRecPtr startpoint,
+									char *slotname);
 static void libpqrcv_endstreaming(TimeLineID *next_tli);
 static int	libpqrcv_receive(int timeout, char **buffer);
 static void libpqrcv_send(const char *buffer, int nbytes);
@@ -171,15 +172,20 @@ libpqrcv_identify_system(TimeLineID *primary_tli)
  * throws an ERROR.
  */
 static bool
-libpqrcv_startstreaming(TimeLineID tli, XLogRecPtr startpoint)
+libpqrcv_startstreaming(TimeLineID tli, XLogRecPtr startpoint, char *slotname)
 {
 	char		cmd[64];
 	PGresult   *res;
 
 	/* Start streaming from the point requested by startup process */
-	snprintf(cmd, sizeof(cmd), "START_REPLICATION %X/%X TIMELINE %u",
-			 (uint32) (startpoint >> 32), (uint32) startpoint,
-			 tli);
+	if (slotname != NULL)
+		snprintf(cmd, sizeof(cmd),
+				 "START_REPLICATION SLOT \"%s\" %X/%X TIMELINE %u", slotname,
+				 (uint32) (startpoint >> 32), (uint32) startpoint, tli);
+	else
+		snprintf(cmd, sizeof(cmd),
+				 "START_REPLICATION %X/%X TIMELINE %u",
+				 (uint32) (startpoint >> 32), (uint32) startpoint, tli);
 	res = libpqrcv_PQexec(cmd);
 
 	if (PQresultStatus(res) == PGRES_COMMAND_OK)
diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y
index 015aa44..d4bd59b 100644
--- a/src/backend/replication/repl_gram.y
+++ b/src/backend/replication/repl_gram.y
@@ -65,7 +65,7 @@ Node *replication_parse_result;
 }
 
 /* Non-keyword tokens */
-%token <str> SCONST
+%token <str> SCONST IDENT
 %token <uintval> UCONST
 %token <recptr> RECPTR
 
@@ -73,6 +73,8 @@ Node *replication_parse_result;
 %token K_BASE_BACKUP
 %token K_IDENTIFY_SYSTEM
 %token K_START_REPLICATION
+%token K_CREATE_REPLICATION_SLOT
+%token K_DROP_REPLICATION_SLOT
 %token K_TIMELINE_HISTORY
 %token K_LABEL
 %token K_PROGRESS
@@ -80,12 +82,15 @@ Node *replication_parse_result;
 %token K_NOWAIT
 %token K_WAL
 %token K_TIMELINE
+%token K_PHYSICAL
+%token K_SLOT
 
 %type <node>	command
-%type <node>	base_backup start_replication identify_system timeline_history
+%type <node>	base_backup start_replication create_replication_slot drop_replication_slot identify_system timeline_history
 %type <list>	base_backup_opt_list
 %type <defelt>	base_backup_opt
 %type <uintval>	opt_timeline
+%type <str>		opt_slot
 %%
 
 firstcmd: command opt_semicolon
@@ -102,6 +107,8 @@ command:
 			identify_system
 			| base_backup
 			| start_replication
+			| create_replication_slot
+			| drop_replication_slot
 			| timeline_history
 			;
 
@@ -158,18 +165,42 @@ base_backup_opt:
 				}
 			;
 
+/* CREATE_REPLICATION_SLOT SLOT slot PHYSICAL */
+create_replication_slot:
+			K_CREATE_REPLICATION_SLOT IDENT K_PHYSICAL
+				{
+					CreateReplicationSlotCmd *cmd;
+					cmd = makeNode(CreateReplicationSlotCmd);
+					cmd->kind = REPLICATION_KIND_PHYSICAL;
+					cmd->slotname = $2;
+					$$ = (Node *) cmd;
+				}
+			;
+
+/* DROP_REPLICATION_SLOT SLOT slot */
+drop_replication_slot:
+			K_DROP_REPLICATION_SLOT IDENT
+				{
+					DropReplicationSlotCmd *cmd;
+					cmd = makeNode(DropReplicationSlotCmd);
+					cmd->slotname = $2;
+					$$ = (Node *) cmd;
+				}
+			;
+
 /*
- * START_REPLICATION %X/%X [TIMELINE %d]
+ * START_REPLICATION [SLOT slot] [PHYSICAL] %X/%X [TIMELINE %d]
  */
 start_replication:
-			K_START_REPLICATION RECPTR opt_timeline
+			K_START_REPLICATION opt_slot opt_physical RECPTR opt_timeline
 				{
 					StartReplicationCmd *cmd;
 
 					cmd = makeNode(StartReplicationCmd);
-					cmd->startpoint = $2;
-					cmd->timeline = $3;
-
+					cmd->kind = REPLICATION_KIND_PHYSICAL;
+					cmd->slotname = $2;
+					cmd->startpoint = $4;
+					cmd->timeline = $5;
 					$$ = (Node *) cmd;
 				}
 			;
@@ -205,6 +236,15 @@ timeline_history:
 					$$ = (Node *) cmd;
 				}
 			;
+
+opt_physical :	K_PHYSICAL | /* EMPTY */;
+
+
+opt_slot :	K_SLOT IDENT
+				{
+					$$ = $2;
+				}
+				| /* nothing */			{ $$ = NULL; }
 %%
 
 #include "repl_scanner.c"
diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l
index 01e5ac6..24195a5 100644
--- a/src/backend/replication/repl_scanner.l
+++ b/src/backend/replication/repl_scanner.l
@@ -16,6 +16,7 @@
 #include "postgres.h"
 
 #include "utils/builtins.h"
+#include "parser/scansup.h"
 
 /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
 #undef fprintf
@@ -48,7 +49,7 @@ static void addlitchar(unsigned char ychar);
 %option warn
 %option prefix="replication_yy"
 
-%x xq
+%x xq xd
 
 /* Extended quote
  * xqdouble implements embedded quote, ''''
@@ -57,12 +58,26 @@ xqstart			{quote}
 xqdouble		{quote}{quote}
 xqinside		[^']+
 
+/* Double quote
+ * Allows embedded spaces and other special characters into identifiers.
+ */
+dquote			\"
+xdstart			{dquote}
+xdstop			{dquote}
+xddouble		{dquote}{dquote}
+xdinside		[^"]+
+
 digit			[0-9]+
 hexdigit		[0-9A-Za-z]+
 
 quote			'
 quotestop		{quote}
 
+ident_start		[A-Za-z\200-\377_]
+ident_cont		[A-Za-z\200-\377_0-9\$]
+
+identifier		{ident_start}{ident_cont}*
+
 %%
 
 BASE_BACKUP			{ return K_BASE_BACKUP; }
@@ -74,9 +89,16 @@ PROGRESS			{ return K_PROGRESS; }
 WAL			{ return K_WAL; }
 TIMELINE			{ return K_TIMELINE; }
 START_REPLICATION	{ return K_START_REPLICATION; }
+CREATE_REPLICATION_SLOT		{ return K_CREATE_REPLICATION_SLOT; }
+DROP_REPLICATION_SLOT		{ return K_DROP_REPLICATION_SLOT; }
 TIMELINE_HISTORY	{ return K_TIMELINE_HISTORY; }
+PHYSICAL			{ return K_PHYSICAL; }
+SLOT				{ return K_SLOT; }
+
 ","				{ return ','; }
 ";"				{ return ';'; }
+"("				{ return '('; }
+")"				{ return ')'; }
 
 [\n]			;
 [\t]			;
@@ -100,20 +122,49 @@ TIMELINE_HISTORY	{ return K_TIMELINE_HISTORY; }
 					BEGIN(xq);
 					startlit();
 				}
+
 <xq>{quotestop}	{
 					yyless(1);
 					BEGIN(INITIAL);
 					yylval.str = litbufdup();
 					return SCONST;
 				}
-<xq>{xqdouble} {
+
+<xq>{xqdouble}	{
 					addlitchar('\'');
 				}
+
 <xq>{xqinside}  {
 					addlit(yytext, yyleng);
 				}
 
-<xq><<EOF>>		{ yyerror("unterminated quoted string"); }
+{xdstart}		{
+					BEGIN(xd);
+					startlit();
+				}
+
+<xd>{xdstop}	{
+					int len;
+					yyless(1);
+					BEGIN(INITIAL);
+					yylval.str = litbufdup();
+					len = strlen(yylval.str);
+					truncate_identifier(yylval.str, len, true);
+					return IDENT;
+				}
+
+<xd>{xdinside}  {
+					addlit(yytext, yyleng);
+				}
+
+{identifier}	{
+					int len = strlen(yytext);
+
+					yylval.str = downcase_truncate_identifier(yytext, len, true);
+					return IDENT;
+				}
+
+<xq,xd><<EOF>>	{ yyerror("unterminated quoted string"); }
 
 
 <<EOF>>			{
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
new file mode 100644
index 0000000..30aff5f
--- /dev/null
+++ b/src/backend/replication/slot.c
@@ -0,0 +1,1066 @@
+/*-------------------------------------------------------------------------
+ *
+ * slot.c
+ *	   Replication slot management.
+ *
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/replication/slot.c
+ *
+ * NOTES
+ *
+ * Replication slots are used to keep state about replication streams
+ * originating from this cluster.  Their primary purpose is to prevent the
+ * premature removal of WAL or of old tuple versions in a manner that would
+ * interfere with replication; they also useful for monitoring purposes.
+ * Slots need to be permanent (to allow restarts), crash-safe, and allocatable
+ * on standbys (to support cascading setups).  The requirement that slots be
+ * usable on standbys precludes storing them in the system catalogs.
+ *
+ * Each replication slot gets its own directory inside the $PGDATA/pg_replslot
+ * directory. Inside that directory the state file will contain the slot's
+ * own data. Additional data can be stored alongside that file if required.
+ * While the server is running, the state data is also cached in memory for
+ * efficiency.
+ *
+ * ReplicationSlotAllocationLock must be taken in exclusive mode to allocate
+ * or free a slot. ReplicationSlotControlLock must be taken in shared mode
+ * to iterate over the slots, and in exclusive mode to change the in_use flag
+ * of a slot.  The remaining data in each slot is protected by its mutex.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "access/transam.h"
+#include "miscadmin.h"
+#include "replication/slot.h"
+#include "storage/fd.h"
+#include "storage/procarray.h"
+
+/*
+ * Replication slot on-disk data structure.
+ */
+typedef struct ReplicationSlotOnDisk
+{
+	/* first part of this struct needs to be version independent */
+
+	/* data not covered by checksum */
+	uint32		magic;
+	pg_crc32	checksum;
+
+	/* data covered by checksum */
+	uint32		version;
+	uint32		length;
+
+	ReplicationSlotPersistentData slotdata;
+} ReplicationSlotOnDisk;
+
+/* size of the part of the slot that is version independent */
+#define ReplicationSlotOnDiskConstantSize \
+	offsetof(ReplicationSlotOnDisk, slotdata)
+/* size of the slots that is not version indepenent */
+#define ReplicationSlotOnDiskDynamicSize \
+	sizeof(ReplicationSlotOnDisk) - ReplicationSlotOnDiskConstantSize
+
+#define SLOT_MAGIC		0x1051CA1		/* format identifier */
+#define SLOT_VERSION	1				/* version for new files */
+
+/* Control array for replication slot management */
+ReplicationSlotCtlData *ReplicationSlotCtl = NULL;
+
+/* My backend's replication slot in the shared memory array */
+ReplicationSlot *MyReplicationSlot = NULL;
+
+/* GUCs */
+int			max_replication_slots = 0;	/* the maximum number of replication slots */
+
+/* internal persistency functions */
+static void RestoreSlotFromDisk(const char *name);
+static void CreateSlotOnDisk(ReplicationSlot *slot);
+static void SaveSlotToPath(ReplicationSlot *slot, const char *path, int elevel);
+
+/*
+ * Report shared-memory space needed by ReplicationSlotShmemInit.
+ */
+Size
+ReplicationSlotsShmemSize(void)
+{
+	Size		size = 0;
+
+	if (max_replication_slots == 0)
+		return size;
+
+	size = offsetof(ReplicationSlotCtlData, replication_slots);
+	size = add_size(size,
+					mul_size(max_replication_slots, sizeof(ReplicationSlot)));
+
+	return size;
+}
+
+/*
+ * Allocate and initialize walsender-related shared memory.
+ */
+void
+ReplicationSlotsShmemInit(void)
+{
+	bool		found;
+
+	if (max_replication_slots == 0)
+		return;
+
+	ReplicationSlotCtl = (ReplicationSlotCtlData *)
+		ShmemInitStruct("ReplicationSlot Ctl", ReplicationSlotsShmemSize(),
+						&found);
+
+	if (!found)
+	{
+		int			i;
+
+		/* First time through, so initialize */
+		MemSet(ReplicationSlotCtl, 0, ReplicationSlotsShmemSize());
+
+		for (i = 0; i < max_replication_slots; i++)
+		{
+			ReplicationSlot *slot = &ReplicationSlotCtl->replication_slots[i];
+
+			/* everything else is zeroed by the memset above */
+			SpinLockInit(&slot->mutex);
+			slot->io_in_progress_lock = LWLockAssign();
+		}
+	}
+}
+
+/*
+ * Check whether the passed slot name is valid and report errors at elevel.
+ *
+ * Slot names may consist out of [a-z0-9_]{1,NAMEDATALEN-1} which should allow
+ * the name to be uses as a directory name on every supported OS.
+ *
+ * Returns whether the directory name is valid or not if elevel < ERROR.
+ */
+bool
+ReplicationSlotValidateName(const char *name, int elevel)
+{
+	const char *cp;
+
+	if (strlen(name) == 0)
+	{
+		ereport(elevel,
+				(errcode(ERRCODE_INVALID_NAME),
+				 errmsg("replication slot name \"%s\" is too short",
+						name)));
+		return false;
+	}
+
+	if (strlen(name) >= NAMEDATALEN)
+	{
+		ereport(elevel,
+				(errcode(ERRCODE_NAME_TOO_LONG),
+				 errmsg("replication slot name \"%s\" is too long",
+						name)));
+		return false;
+	}
+
+	for (cp = name; *cp; cp++)
+	{
+		if (!((*cp >= 'a' && *cp <= 'z')
+			  || (*cp >= '0' && *cp <= '9')
+			  || (*cp == '_')))
+		{
+			ereport(elevel,
+					(errcode(ERRCODE_INVALID_NAME),
+					 errmsg("replication slot name \"%s\" contains invalid character",
+							name),
+					 errhint("Replication slot names may only contain letters, numbers and the underscore character.")));
+			return false;
+		}
+	}
+	return true;
+}
+
+/*
+ * Create a new replication slot and mark it as used by this backend.
+ *
+ * name: Name of the slot
+ * db_specific: changeset extraction is db specific, if the slot is going to
+ *     be used for that pass true, otherwise false.
+ */
+void
+ReplicationSlotCreate(const char *name, bool db_specific)
+{
+	ReplicationSlot *slot = NULL;
+	int			i;
+
+	Assert(MyReplicationSlot == NULL);
+
+	ReplicationSlotValidateName(name, ERROR);
+
+	/*
+	 * If some other backend ran this code currently with us, we'd likely
+	 * both allocate the same slot, and that would be bad.  We'd also be
+	 * at risk of missing a name collision.  Also, we don't want to try to
+	 * create a new slot while somebody's busy cleaning up an old one, because
+	 * we might both be monkeying with the same directory.
+	 */
+	LWLockAcquire(ReplicationSlotAllocationLock, LW_EXCLUSIVE);
+
+	/*
+	 * Check for name collision, and identify an allocatable slot.  We need
+	 * to hold ReplicationSlotControlLock in shared mode for this, so that
+	 * nobody else can change the in_use flags while we're looking at them.
+	 */
+	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
+	for (i = 0; i < max_replication_slots; i++)
+	{
+		ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i];
+
+		if (s->in_use && strcmp(name, NameStr(s->data.name)) == 0)
+			ereport(ERROR,
+					(errcode(ERRCODE_DUPLICATE_OBJECT),
+					 errmsg("replication slot \"%s\" already exists", name)));
+		if (!s->in_use && slot == NULL)
+			slot = s;
+	}
+	LWLockRelease(ReplicationSlotControlLock);
+
+	/* If all slots are in use, we're out of luck. */
+	if (slot == NULL)
+		ereport(ERROR,
+				(errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
+				 errmsg("all replication slots are in use"),
+				 errhint("Free one or increase max_replication_slots.")));
+
+	/*
+	 * Since this slot is not in use, nobody should be looking at any
+	 * part of it other than the in_use field unless they're trying to allocate
+	 * it.  And since we hold ReplicationSlotAllocationLock, nobody except us
+	 * can be doing that.  So it's safe to initialize the slot.
+	 */
+	Assert(!slot->in_use);
+	Assert(!slot->active);
+	slot->data.xmin = InvalidTransactionId;
+	slot->effective_xmin = InvalidTransactionId;
+	strncpy(NameStr(slot->data.name), name, NAMEDATALEN);
+	NameStr(slot->data.name)[NAMEDATALEN - 1] = '\0';
+	slot->data.database = db_specific ? MyDatabaseId : InvalidOid;
+	slot->data.restart_lsn = InvalidXLogRecPtr;
+
+	/*
+	 * Create the slot on disk.  We haven't actually marked the slot allocated
+	 * yet, so no special cleanup is required if this errors out.
+	 */
+	CreateSlotOnDisk(slot);
+
+	/*
+	 * We need to briefly prevent any other backend from iterating over the
+	 * slots while we flip the in_use flag. We also need to set the active
+	 * flag while holding the ControlLock as otherwise a concurrent
+	 * SlotAcquire() could acquire the slot as well.
+	 */
+	LWLockAcquire(ReplicationSlotControlLock, LW_EXCLUSIVE);
+
+	slot->in_use = true;
+
+	/* We can now mark the slot active, and that makes it our slot. */
+	{
+		volatile ReplicationSlot *vslot = slot;
+
+		SpinLockAcquire(&slot->mutex);
+		Assert(!vslot->active);
+		vslot->active = true;
+		SpinLockRelease(&slot->mutex);
+		MyReplicationSlot = slot;
+	}
+
+	LWLockRelease(ReplicationSlotControlLock);
+
+	/*
+	 * Now that the slot has been marked as in_use and in_active, it's safe to
+	 * let somebody else try to allocate a slot.
+	 */
+	LWLockRelease(ReplicationSlotAllocationLock);
+}
+
+/*
+ * Find an previously created slot and mark it as used by this backend.
+ */
+void
+ReplicationSlotAcquire(const char *name)
+{
+	ReplicationSlot *slot = NULL;
+	int			i;
+	bool		active = false;
+
+	Assert(MyReplicationSlot == NULL);
+
+	ReplicationSlotValidateName(name, ERROR);
+
+	/* Search for the named slot and mark it active if we find it. */
+	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
+	for (i = 0; i < max_replication_slots; i++)
+	{
+		ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i];
+
+		if (s->in_use && strcmp(name, NameStr(s->data.name)) == 0)
+		{
+			volatile ReplicationSlot *vslot = s;
+
+			SpinLockAcquire(&s->mutex);
+			active = vslot->active;
+			vslot->active = true;
+			SpinLockRelease(&s->mutex);
+			slot = s;
+			break;
+		}
+	}
+	LWLockRelease(ReplicationSlotControlLock);
+
+	/* If we did not find the slot or it was already active, error out. */
+	if (slot == NULL)
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("replication slot \"%s\" does not exist", name)));
+	if (active)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_IN_USE),
+				 errmsg("replication slot \"%s\" is already active", name)));
+
+	/* We made this slot active, so it's ours now. */
+	MyReplicationSlot = slot;
+}
+
+/*
+ * Release a replication slot, this or another backend can ReAcquire it
+ * later. Resources this slot requires will be preserved.
+ */
+void
+ReplicationSlotRelease(void)
+{
+	ReplicationSlot *slot = MyReplicationSlot;
+
+	Assert(slot != NULL && slot->active);
+
+	/* Mark slot inactive.  We're not freeing it, just disconnecting. */
+	{
+		volatile ReplicationSlot *vslot = slot;
+		SpinLockAcquire(&slot->mutex);
+		vslot->active = false;
+		SpinLockRelease(&slot->mutex);
+		MyReplicationSlot = NULL;
+	}
+}
+
+/*
+ * Permanently drop replication slot identified by the passed in name.
+ */
+void
+ReplicationSlotDrop(const char *name)
+{
+	ReplicationSlot *slot = NULL;
+	int			i;
+	bool		active;
+	char		path[MAXPGPATH];
+	char		tmppath[MAXPGPATH];
+
+	ReplicationSlotValidateName(name, ERROR);
+
+	/*
+	 * If some other backend ran this code currently with us, we might both
+	 * try to free the same slot at the same time.  Or we might try to delete
+	 * a slot with a certain name while someone else was trying to create a
+	 * slot with the same name.
+	 */
+	LWLockAcquire(ReplicationSlotAllocationLock, LW_EXCLUSIVE);
+
+	/* Search for the named slot and mark it active if we find it. */
+	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
+	for (i = 0; i < max_replication_slots; i++)
+	{
+		ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i];
+
+		if (s->in_use && strcmp(name, NameStr(s->data.name)) == 0)
+		{
+			volatile ReplicationSlot *vslot = s;
+
+			SpinLockAcquire(&s->mutex);
+			active = vslot->active;
+			vslot->active = true;
+			SpinLockRelease(&s->mutex);
+			slot = s;
+			break;
+		}
+	}
+	LWLockRelease(ReplicationSlotControlLock);
+
+	/* If we did not find the slot or it was already active, error out. */
+	if (slot == NULL)
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("replication slot \"%s\" does not exist", name)));
+	if (active)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_IN_USE),
+				 errmsg("replication slot \"%s\" is already active", name)));
+
+	/* Generate pathnames. */
+	sprintf(path, "pg_replslot/%s", NameStr(slot->data.name));
+	sprintf(tmppath, "pg_replslot/%s.tmp", NameStr(slot->data.name));
+
+	/*
+	 * Rename the slot directory on disk, so that we'll no longer recognize
+	 * this as a valid slot.  Note that if this fails, we've got to mark the
+	 * slot inactive again before bailing out.
+	 */
+	if (rename(path, tmppath) != 0)
+	{
+		volatile ReplicationSlot *vslot = slot;
+
+		SpinLockAcquire(&slot->mutex);
+		vslot->active = false;
+		SpinLockRelease(&slot->mutex);
+
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not rename \"%s\" to \"%s\": %m",
+						path, tmppath)));
+	}
+
+	/*
+	 * We need to fsync() the directory we just renamed and its parent to make
+	 * sure that our changes are on disk in a crash-safe fashion.  If fsync()
+	 * fails, we can't be sure whether the changes are on disk or not.  For
+	 * now, we handle that by panicking; StartupReplicationSlots() will
+	 * try to straighten it out after restart.
+	 */
+	START_CRIT_SECTION();
+	fsync_fname(tmppath, true);
+	fsync_fname("pg_replslot", true);
+	END_CRIT_SECTION();
+
+	/*
+	 * The slot is definitely gone.  Lock out concurrent scans of the array
+	 * long enough to kill it.  It's OK to clear the active flag here without
+	 * grabbing the mutex because nobody else can be scanning the array here,
+	 * and nobody can be attached to this slot and thus access it without
+	 * scanning the array.
+	 */
+	LWLockAcquire(ReplicationSlotControlLock, LW_EXCLUSIVE);
+	slot->active = false;
+	slot->in_use = false;
+	LWLockRelease(ReplicationSlotControlLock);
+
+	/*
+	 * Slot is dead and doesn't prevent resource removal anymore, recompute
+	 * limits.
+	 */
+	ReplicationSlotsComputeRequiredXmin();
+	ReplicationSlotsComputeRequiredLSN();
+
+	/*
+	 * If removing the directory fails, the worst thing that will happen is
+	 * that the user won't be able to create a new slot with the same name
+	 * until the next server restart.  We warn about it, but that's all.
+	 */
+	if (!rmtree(tmppath, true))
+		ereport(WARNING,
+				(errcode_for_file_access(),
+				 errmsg("could not remove directory \"%s\"", tmppath)));
+
+	/*
+	 * We release this at the very end, so that nobody starts trying to create
+	 * a slot while we're still cleaning up the detritus of the old one.
+	 */
+	LWLockRelease(ReplicationSlotAllocationLock);
+}
+
+/*
+ * Serialize the currently acquired slot's state from memory to disk, thereby
+ * guaranteeing the current state will survive a crash.
+ */
+void
+ReplicationSlotSave(void)
+{
+	char		path[MAXPGPATH];
+
+	Assert(MyReplicationSlot != NULL);
+
+	sprintf(path, "pg_replslot/%s", NameStr(MyReplicationSlot->data.name));
+	SaveSlotToPath(MyReplicationSlot, path, ERROR);
+}
+
+/*
+ * Signal that it would be useful if the currently acquired slot would be
+ * flushed out to disk.
+ *
+ * Note that the actual flush to disk can be delayed for a long time, if
+ * required for correctness explicitly do a ReplicationSlotSave().
+ */
+void
+ReplicationSlotMarkDirty(void)
+{
+	Assert(MyReplicationSlot != NULL);
+
+	{
+		volatile ReplicationSlot *vslot = MyReplicationSlot;
+
+		SpinLockAcquire(&vslot->mutex);
+		MyReplicationSlot->just_dirtied = true;
+		MyReplicationSlot->dirty = true;
+		SpinLockRelease(&vslot->mutex);
+	}
+}
+
+/*
+ * Compute the oldest xmin across all slots and store it in the ProcArray.
+ */
+void
+ReplicationSlotsComputeRequiredXmin(void)
+{
+	int			i;
+	TransactionId agg_xmin = InvalidTransactionId;
+
+	Assert(ReplicationSlotCtl != NULL);
+
+	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
+	for (i = 0; i < max_replication_slots; i++)
+	{
+		ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i];
+		TransactionId	effective_xmin;
+
+		if (!s->in_use)
+			continue;
+
+		{
+			volatile ReplicationSlot *vslot = s;
+
+			SpinLockAcquire(&s->mutex);
+			effective_xmin = vslot->effective_xmin;
+			SpinLockRelease(&s->mutex);
+		}
+
+		/* check the data xmin */
+		if (TransactionIdIsValid(effective_xmin) &&
+			(!TransactionIdIsValid(agg_xmin) ||
+			 TransactionIdPrecedes(effective_xmin, agg_xmin)))
+			agg_xmin = effective_xmin;
+	}
+	LWLockRelease(ReplicationSlotControlLock);
+
+	ProcArraySetReplicationSlotXmin(agg_xmin);
+}
+
+/*
+ * Compute the oldest restart LSN across all slots and inform xlog module.
+ */
+void
+ReplicationSlotsComputeRequiredLSN(void)
+{
+	int			i;
+	XLogRecPtr  min_required = InvalidXLogRecPtr;
+
+	Assert(ReplicationSlotCtl != NULL);
+
+	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
+	for (i = 0; i < max_replication_slots; i++)
+	{
+		ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i];
+		XLogRecPtr restart_lsn;
+
+		if (!s->in_use)
+			continue;
+
+		{
+			volatile ReplicationSlot *vslot = s;
+
+			SpinLockAcquire(&s->mutex);
+			restart_lsn = vslot->data.restart_lsn;
+			SpinLockRelease(&s->mutex);
+		}
+
+		if (restart_lsn != InvalidXLogRecPtr &&
+			(min_required == InvalidXLogRecPtr ||
+			 restart_lsn < min_required))
+			min_required = restart_lsn;
+	}
+	LWLockRelease(ReplicationSlotControlLock);
+
+	XLogSetReplicationSlotMinimumLSN(min_required);
+}
+
+/*
+ * Check whether the server's configuration supports using replication
+ * slots.
+ */
+void
+CheckSlotRequirements(void)
+{
+	if (max_replication_slots == 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 (errmsg("replication slots can only be used if max_replication_slots > 0"))));
+
+	if (wal_level < WAL_LEVEL_ARCHIVE)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("replication slots can only be used if wal_level >= archive")));
+}
+
+/*
+ * Returns whether the string `str' has the postfix `end'.
+ */
+static bool
+string_endswith(const char *str, const char *end)
+{
+	size_t slen = strlen(str);
+	size_t elen = strlen(end);
+
+	/* can't be a postfix if longer */
+	if (elen > slen)
+		return false;
+
+	/* compare the end of the strings */
+	str += slen - elen;
+	return strcmp(str, end) == 0;
+}
+
+/*
+ * Flush all replication slots to disk.
+ *
+ * This needn't actually be part of a checkpoint, but it's a convenient
+ * location.
+ */
+void
+CheckPointReplicationSlots(void)
+{
+	int			i;
+
+	ereport(DEBUG1,
+			(errmsg("performing replication slot checkpoint")));
+
+	/*
+	 * Prevent any slot from being created/dropped while we're active. As we
+	 * explicitly do *not* want to block iterating over replication_slots or
+	 * acquiring a slot we cannot take the control lock - but that's OK,
+	 * because holding ReplicationSlotAllocationLock is strictly stronger,
+	 * and enough to guarantee that nobody can change the in_use bits on us.
+	 */
+	LWLockAcquire(ReplicationSlotAllocationLock, LW_SHARED);
+
+	for (i = 0; i < max_replication_slots; i++)
+	{
+		ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i];
+		char		path[MAXPGPATH];
+
+		if (!s->in_use)
+			continue;
+
+		/* save the slot to disk, locking is handled in SaveSlotToPath() */
+		sprintf(path, "pg_replslot/%s", NameStr(s->data.name));
+		SaveSlotToPath(s, path, LOG);
+	}
+	LWLockRelease(ReplicationSlotAllocationLock);
+}
+
+/*
+ * Load all replication slots from disk into memory at server startup. This
+ * needs to be run before we start crash recovery.
+ */
+void
+StartupReplicationSlots(XLogRecPtr checkPointRedo)
+{
+	DIR		   *replication_dir;
+	struct dirent *replication_de;
+
+	ereport(DEBUG1,
+			(errmsg("starting up replication slots")));
+
+	/* restore all slots by iterating over all on-disk entries */
+	replication_dir = AllocateDir("pg_replslot");
+	while ((replication_de = ReadDir(replication_dir, "pg_replslot")) != NULL)
+	{
+		struct stat	statbuf;
+		char		path[MAXPGPATH];
+
+		if (strcmp(replication_de->d_name, ".") == 0 ||
+			strcmp(replication_de->d_name, "..") == 0)
+			continue;
+
+		snprintf(path, MAXPGPATH, "pg_replslot/%s", replication_de->d_name);
+
+		/* we're only creating directories here, skip if it's not our's */
+		if (lstat(path, &statbuf) == 0 && !S_ISDIR(statbuf.st_mode))
+			continue;
+
+		/* we crashed while a slot was being setup or deleted, clean up */
+		if (string_endswith(replication_de->d_name, ".tmp"))
+		{
+			if (!rmtree(path, true))
+			{
+				ereport(WARNING,
+						(errcode_for_file_access(),
+						 errmsg("could not remove directory \"%s\"", path)));
+				continue;
+			}
+			fsync_fname("pg_replslot", true);
+			continue;
+		}
+
+		/* looks like a slot in a normal state, restore */
+		RestoreSlotFromDisk(replication_de->d_name);
+	}
+	FreeDir(replication_dir);
+
+	/* currently no slots exist, we're done. */
+	if (max_replication_slots <= 0)
+		return;
+
+	/* Now that we have recovered all the data, compute replication xmin */
+	ReplicationSlotsComputeRequiredXmin();
+	ReplicationSlotsComputeRequiredLSN();
+}
+
+/* ----
+ * Manipulation of ondisk state of replication slots
+ *
+ * NB: none of the routines below should take any notice whether a slot is the
+ * current one or not, that's all handled a layer above.
+ * ----
+ */
+static void
+CreateSlotOnDisk(ReplicationSlot *slot)
+{
+	char		tmppath[MAXPGPATH];
+	char		path[MAXPGPATH];
+	struct stat	st;
+
+	/*
+	 * No need to take out the io_in_progress_lock, nobody else can see this
+	 * slot yet, so nobody else wil write. We're reusing SaveSlotToPath which
+	 * takes out the lock, if we'd take the lock here, we'd deadlock.
+	 */
+
+	sprintf(path, "pg_replslot/%s", NameStr(slot->data.name));
+	sprintf(tmppath, "pg_replslot/%s.tmp", NameStr(slot->data.name));
+
+	/*
+	 * It's just barely possible that some previous effort to create or
+	 * drop a slot with this name left a temp directory lying around.
+	 * If that seems to be the case, try to remove it.  If the rmtree()
+	 * fails, we'll error out at the mkdir() below, so we don't bother
+	 * checking success.
+	 */
+	if (stat(tmppath, &st) == 0 && S_ISDIR(st.st_mode))
+		rmtree(tmppath, true);
+
+	/* Create and fsync the temporary slot directory. */
+	if (mkdir(tmppath, S_IRWXU) < 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not create directory \"%s\": %m",
+						tmppath)));
+	fsync_fname(tmppath, true);
+
+	/* Write the actual state file. */
+	slot->dirty = true; /* signal that we really need to write */
+	SaveSlotToPath(slot, tmppath, ERROR);
+
+	/* Rename the directory into place. */
+	if (rename(tmppath, path) != 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not rename file \"%s\" to \"%s\": %m",
+						tmppath, path)));
+
+	/*
+	 * If we'd now fail - really unlikely - we wouldn't know wether this slot
+	 * would persist after an OS crash or not - so, force a restart. The
+	 * restart would try to fysnc this again till it works.
+	 */
+	START_CRIT_SECTION();
+
+	fsync_fname(path, true);
+	fsync_fname("pg_replslot", true);
+
+	END_CRIT_SECTION();
+}
+
+/*
+ * Shared functionality between saving and creating a replication slot.
+ */
+static void
+SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel)
+{
+	char		tmppath[MAXPGPATH];
+	char		path[MAXPGPATH];
+	int			fd;
+	ReplicationSlotOnDisk cp;
+	bool		was_dirty;
+
+	/* first check whether there's something to write out */
+	{
+		volatile ReplicationSlot *vslot = slot;
+
+		SpinLockAcquire(&vslot->mutex);
+		was_dirty = vslot->dirty;
+		vslot->just_dirtied = false;
+		SpinLockRelease(&vslot->mutex);
+	}
+
+	/* and don't do anything if there's nothing to write */
+	if (!was_dirty)
+		return;
+
+	LWLockAcquire(slot->io_in_progress_lock, LW_EXCLUSIVE);
+
+	/* silence valgrind :( */
+	memset(&cp, 0, sizeof(ReplicationSlotOnDisk));
+
+	sprintf(tmppath, "%s/state.tmp", dir);
+	sprintf(path, "%s/state", dir);
+
+	fd = OpenTransientFile(tmppath,
+						   O_CREAT | O_EXCL | O_WRONLY | PG_BINARY,
+						   S_IRUSR | S_IWUSR);
+	if (fd < 0)
+	{
+		ereport(elevel,
+				(errcode_for_file_access(),
+				 errmsg("could not create file \"%s\": %m",
+						tmppath)));
+		return;
+	}
+
+	cp.magic = SLOT_MAGIC;
+	INIT_CRC32(cp.checksum);
+	cp.version = 1;
+	cp.length = ReplicationSlotOnDiskDynamicSize;
+
+	SpinLockAcquire(&slot->mutex);
+
+	memcpy(&cp.slotdata, &slot->data, sizeof(ReplicationSlotPersistentData));
+
+	SpinLockRelease(&slot->mutex);
+
+	COMP_CRC32(cp.checksum,
+			   (char *)(&cp) + ReplicationSlotOnDiskConstantSize,
+			   ReplicationSlotOnDiskDynamicSize);
+
+	if ((write(fd, &cp, sizeof(cp))) != sizeof(cp))
+	{
+		int save_errno = errno;
+		CloseTransientFile(fd);
+		errno = save_errno;
+		ereport(elevel,
+				(errcode_for_file_access(),
+				 errmsg("could not write to file \"%s\": %m",
+						tmppath)));
+		return;
+	}
+
+	/* fsync the temporary file */
+	if (pg_fsync(fd) != 0)
+	{
+		int save_errno = errno;
+		CloseTransientFile(fd);
+		errno = save_errno;
+		ereport(elevel,
+				(errcode_for_file_access(),
+				 errmsg("could not fsync file \"%s\": %m",
+						tmppath)));
+		return;
+	}
+
+	CloseTransientFile(fd);
+
+	/* rename to permanent file, fsync file and directory */
+	if (rename(tmppath, path) != 0)
+	{
+		ereport(elevel,
+				(errcode_for_file_access(),
+				 errmsg("could not rename \"%s\" to \"%s\": %m",
+						tmppath, path)));
+		return;
+	}
+
+	/* Check CreateSlot() for the reasoning of using a crit. section. */
+	START_CRIT_SECTION();
+
+	fsync_fname(path, false);
+	fsync_fname((char *) dir, true);
+	fsync_fname("pg_replslot", true);
+
+	END_CRIT_SECTION();
+
+	/*
+	 * Successfully wrote, unset dirty bit, unless somebody dirtied again
+	 * already.
+	 */
+	{
+		volatile ReplicationSlot *vslot = slot;
+
+		SpinLockAcquire(&vslot->mutex);
+		if (!vslot->just_dirtied)
+			vslot->dirty = false;
+		SpinLockRelease(&vslot->mutex);
+	}
+
+	LWLockRelease(slot->io_in_progress_lock);
+}
+
+/*
+ * Load a single slot from disk into memory.
+ */
+static void
+RestoreSlotFromDisk(const char *name)
+{
+	ReplicationSlotOnDisk cp;
+	int			i;
+	char		path[MAXPGPATH];
+	int			fd;
+	bool		restored = false;
+	int			readBytes;
+	pg_crc32	checksum;
+
+	/* no need to lock here, no concurrent access allowed yet */
+
+	/* delete temp file if it exists */
+	sprintf(path, "pg_replslot/%s/state.tmp", name);
+	if (unlink(path) < 0 && errno != ENOENT)
+		ereport(PANIC,
+				(errcode_for_file_access(),
+				 errmsg("could not unlink file \"%s\": %m", path)));
+
+	sprintf(path, "pg_replslot/%s/state", name);
+
+	elog(DEBUG1, "restoring replication slot from \"%s\"", path);
+
+	fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+
+	/*
+	 * We do not need to handle this as we are rename()ing the directory into
+	 * place only after we fsync()ed the state file.
+	 */
+	if (fd < 0)
+		ereport(PANIC,
+				(errcode_for_file_access(),
+				 errmsg("could not open file \"%s\": %m", path)));
+
+	/*
+	 * Sync state file before we're reading from it. We might have crashed
+	 * while it wasn't synced yet and we shouldn't continue on that basis.
+	 */
+	if (pg_fsync(fd) != 0)
+	{
+		CloseTransientFile(fd);
+		ereport(PANIC,
+				(errcode_for_file_access(),
+				 errmsg("could not fsync file \"%s\": %m",
+						path)));
+	}
+
+	/* Also sync the parent directory */
+	START_CRIT_SECTION();
+	fsync_fname(path, true);
+	END_CRIT_SECTION();
+
+	/* read part of statefile that's guaranteed to be version independent */
+	readBytes = read(fd, &cp, ReplicationSlotOnDiskConstantSize);
+	if (readBytes != ReplicationSlotOnDiskConstantSize)
+	{
+		int			saved_errno = errno;
+
+		CloseTransientFile(fd);
+		errno = saved_errno;
+		ereport(PANIC,
+				(errcode_for_file_access(),
+				 errmsg("could not read file \"%s\", read %d of %u: %m",
+						path, readBytes,
+						(uint32) ReplicationSlotOnDiskConstantSize)));
+	}
+
+	/* verify magic */
+	if (cp.magic != SLOT_MAGIC)
+		ereport(PANIC,
+				(errcode_for_file_access(),
+				 errmsg("replication slot file \"%s\" has wrong magic %u instead of %u",
+						path, cp.magic, SLOT_MAGIC)));
+
+	/* verify version */
+	if (cp.version != SLOT_VERSION)
+		ereport(PANIC,
+				(errcode_for_file_access(),
+				 errmsg("replication slot file \"%s\" has unsupported version %u",
+						path, cp.version)));
+
+	/* boundary check on length */
+	if (cp.length != ReplicationSlotOnDiskDynamicSize)
+		ereport(PANIC,
+				(errcode_for_file_access(),
+				 errmsg("replication slot file \"%s\" has corrupted length %u",
+						path, cp.length)));
+
+	/* Now that we know the size, read the entire file */
+	readBytes = read(fd,
+					 (char *)&cp + ReplicationSlotOnDiskConstantSize,
+					 cp.length);
+	if (readBytes != cp.length)
+	{
+		int			saved_errno = errno;
+
+		CloseTransientFile(fd);
+		errno = saved_errno;
+		ereport(PANIC,
+				(errcode_for_file_access(),
+				 errmsg("could not read file \"%s\", read %d of %u: %m",
+						path, readBytes, cp.length)));
+	}
+
+	CloseTransientFile(fd);
+
+	/* now verify the CRC32 */
+	INIT_CRC32(checksum);
+	COMP_CRC32(checksum,
+			   (char *)&cp + ReplicationSlotOnDiskConstantSize,
+			   ReplicationSlotOnDiskDynamicSize);
+
+	if (!EQ_CRC32(checksum, cp.checksum))
+		ereport(PANIC,
+				(errmsg("replication slot file %s: checksum mismatch, is %u, should be %u",
+						path, checksum, cp.checksum)));
+
+	/* nothing can be active yet, don't lock anything */
+	for (i = 0; i < max_replication_slots; i++)
+	{
+		ReplicationSlot *slot;
+
+		slot = &ReplicationSlotCtl->replication_slots[i];
+
+		if (slot->in_use)
+			continue;
+
+		/* restore the entire set of persistent data */
+		memcpy(&slot->data, &cp.slotdata,
+			   sizeof(ReplicationSlotPersistentData));
+
+		/* initialize in memory state */
+		slot->effective_xmin = cp.slotdata.xmin;
+		slot->in_use = true;
+		slot->active = false;
+
+		restored = true;
+		break;
+	}
+
+	if (!restored)
+		ereport(PANIC,
+				(errmsg("too many replication slots active before shutdown"),
+				 errhint("Increase max_replication_slots and try again.")));
+}
diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c
new file mode 100644
index 0000000..98a860e
--- /dev/null
+++ b/src/backend/replication/slotfuncs.c
@@ -0,0 +1,193 @@
+/*-------------------------------------------------------------------------
+ *
+ * slotfuncs.c
+ *	   Support functions for replication slots
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/backend/replication/slotfuncs.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "access/htup_details.h"
+#include "utils/builtins.h"
+#include "replication/slot.h"
+
+Datum		pg_create_physical_replication_slot(PG_FUNCTION_ARGS);
+Datum		pg_drop_replication_slot(PG_FUNCTION_ARGS);
+
+static void
+check_permissions(void)
+{
+	if (!superuser() && !has_rolreplication(GetUserId()))
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 (errmsg("must be superuser or replication role to use replication slots"))));
+}
+
+/*
+ * SQL function for creating a new physical (streaming replication)
+ * replication slot.
+ */
+Datum
+pg_create_physical_replication_slot(PG_FUNCTION_ARGS)
+{
+	Name		name = PG_GETARG_NAME(0);
+	Datum		values[2];
+	bool		nulls[2];
+	TupleDesc	tupdesc;
+	HeapTuple	tuple;
+	Datum		result;
+
+	check_permissions();
+
+	CheckSlotRequirements();
+
+	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
+
+	/* acquire replication slot, this will check for conflicting names*/
+	ReplicationSlotCreate(NameStr(*name), false);
+
+	values[0] = CStringGetTextDatum(NameStr(MyReplicationSlot->data.name));
+
+	nulls[0] = false;
+	nulls[1] = true;
+
+	tuple = heap_form_tuple(tupdesc, values, nulls);
+	result = HeapTupleGetDatum(tuple);
+
+	ReplicationSlotRelease();
+
+	PG_RETURN_DATUM(result);
+}
+
+/*
+ * SQL function for dropping a replication slot.
+ */
+Datum
+pg_drop_replication_slot(PG_FUNCTION_ARGS)
+{
+	Name		name = PG_GETARG_NAME(0);
+
+	check_permissions();
+
+	CheckSlotRequirements();
+
+	ReplicationSlotDrop(NameStr(*name));
+
+	PG_RETURN_VOID();
+}
+
+/*
+ * pg_get_replication_slots - SQL SRF showing active replication slots.
+ */
+Datum
+pg_get_replication_slots(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_GET_REPLICATION_SLOTS_COLS 6
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+	TupleDesc	tupdesc;
+	Tuplestorestate *tupstore;
+	MemoryContext per_query_ctx;
+	MemoryContext oldcontext;
+	int			slotno;
+
+	/* check to see if caller supports us returning a tuplestore */
+	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("set-valued function called in context that cannot accept a set")));
+	if (!(rsinfo->allowedModes & SFRM_Materialize))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("materialize mode required, but it is not " \
+						"allowed in this context")));
+
+	/* Build a tuple descriptor for our result type */
+	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
+
+	/*
+	 * We don't require any special permission to see this function's data
+	 * because nothing should be sensitive. The most critical being the slot
+	 * name, which shouldn't contain anything particularly sensitive.
+	 */
+
+	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
+	oldcontext = MemoryContextSwitchTo(per_query_ctx);
+
+	tupstore = tuplestore_begin_heap(true, false, work_mem);
+	rsinfo->returnMode = SFRM_Materialize;
+	rsinfo->setResult = tupstore;
+	rsinfo->setDesc = tupdesc;
+
+	MemoryContextSwitchTo(oldcontext);
+
+	for (slotno = 0; slotno < max_replication_slots; slotno++)
+	{
+		ReplicationSlot *slot = &ReplicationSlotCtl->replication_slots[slotno];
+		Datum		values[PG_STAT_GET_REPLICATION_SLOTS_COLS];
+		bool		nulls[PG_STAT_GET_REPLICATION_SLOTS_COLS];
+
+		TransactionId xmin;
+		XLogRecPtr	restart_lsn;
+		bool		active;
+		Oid			database;
+		const char *slot_name;
+
+		char		restart_lsn_s[MAXFNAMELEN];
+		int			i;
+
+		SpinLockAcquire(&slot->mutex);
+		if (!slot->in_use)
+		{
+			SpinLockRelease(&slot->mutex);
+			continue;
+		}
+		else
+		{
+			xmin = slot->data.xmin;
+			database = slot->data.database;
+			restart_lsn = slot->data.restart_lsn;
+			slot_name = pstrdup(NameStr(slot->data.name));
+
+			active = slot->active;
+		}
+		SpinLockRelease(&slot->mutex);
+
+		memset(nulls, 0, sizeof(nulls));
+
+		snprintf(restart_lsn_s, sizeof(restart_lsn_s), "%X/%X",
+				 (uint32) (restart_lsn >> 32), (uint32) restart_lsn);
+
+		i = 0;
+		values[i++] = CStringGetTextDatum(slot_name);
+		if (database == InvalidOid)
+			values[i++] = CStringGetTextDatum("physical");
+		else
+			values[i++] = CStringGetTextDatum("logical");
+		values[i++] = database;
+		values[i++] = BoolGetDatum(active);
+		if (xmin != InvalidTransactionId)
+			values[i++] = TransactionIdGetDatum(xmin);
+		else
+			nulls[i++] = true;
+		if (restart_lsn != InvalidTransactionId)
+			values[i++] = CStringGetTextDatum(restart_lsn_s);
+		else
+			nulls[i++] = true;
+
+		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+	}
+
+	tuplestore_donestoring(tupstore);
+
+	return (Datum) 0;
+}
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 1fbd33e..cc3d775 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -187,6 +187,7 @@ void
 WalReceiverMain(void)
 {
 	char		conninfo[MAXCONNINFO];
+	char		slotname[NAMEDATALEN];
 	XLogRecPtr	startpoint;
 	TimeLineID	startpointTLI;
 	TimeLineID	primaryTLI;
@@ -241,6 +242,7 @@ WalReceiverMain(void)
 
 	/* Fetch information required to start streaming */
 	strlcpy(conninfo, (char *) walrcv->conninfo, MAXCONNINFO);
+	strlcpy(slotname, (char *) walrcv->slotname, NAMEDATALEN);
 	startpoint = walrcv->receiveStart;
 	startpointTLI = walrcv->receiveStartTLI;
 
@@ -355,7 +357,8 @@ WalReceiverMain(void)
 		 * on the new timeline.
 		 */
 		ThisTimeLineID = startpointTLI;
-		if (walrcv_startstreaming(startpointTLI, startpoint))
+		if (walrcv_startstreaming(startpointTLI, startpoint,
+								  slotname[0] != '\0' ? slotname : NULL))
 		{
 			bool		endofwal = false;
 
diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c
index cc96d7c..acadec5 100644
--- a/src/backend/replication/walreceiverfuncs.c
+++ b/src/backend/replication/walreceiverfuncs.c
@@ -219,11 +219,13 @@ ShutdownWalRcv(void)
 /*
  * Request postmaster to start walreceiver.
  *
- * recptr indicates the position where streaming should begin, and conninfo
- * is a libpq connection string to use.
+ * recptr indicates the position where streaming should begin, conninfo
+ * is a libpq connection string to use, and slotname is, optionally, the name
+ * of a replication slot to acquire.
  */
 void
-RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo)
+RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
+					 const char *slotname)
 {
 	/* use volatile pointer to prevent code rearrangement */
 	volatile WalRcvData *walrcv = WalRcv;
@@ -250,6 +252,11 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo)
 	else
 		walrcv->conninfo[0] = '\0';
 
+	if (slotname != NULL)
+		strlcpy((char *) walrcv->slotname, slotname, NAMEDATALEN);
+	else
+		walrcv->slotname[0] = '\0';
+
 	if (walrcv->walRcvState == WALRCV_STOPPED)
 	{
 		launch = true;
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 652487e..119a920 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -53,6 +53,7 @@
 #include "miscadmin.h"
 #include "nodes/replnodes.h"
 #include "replication/basebackup.h"
+#include "replication/slot.h"
 #include "replication/syncrep.h"
 #include "replication/walreceiver.h"
 #include "replication/walsender.h"
@@ -218,12 +219,17 @@ InitWalSender(void)
 void
 WalSndErrorCleanup()
 {
+	LWLockReleaseAll();
+
 	if (sendFile >= 0)
 	{
 		close(sendFile);
 		sendFile = -1;
 	}
 
+	if (MyReplicationSlot != NULL)
+		ReplicationSlotRelease();
+
 	replication_active = false;
 	if (walsender_ready_to_stop)
 		proc_exit(0);
@@ -421,6 +427,15 @@ StartReplication(StartReplicationCmd *cmd)
 	 * written at wal_level='minimal'.
 	 */
 
+	if (cmd->slotname)
+	{
+		ReplicationSlotAcquire(cmd->slotname);
+		if (MyReplicationSlot->data.database != InvalidOid)
+			ereport(ERROR,
+					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+					 (errmsg("cannot use a replication slot created for changeset extraction for streaming replication"))));
+	}
+
 	/*
 	 * Select the timeline. If it was given explicitly by the client, use
 	 * that. Otherwise use the timeline of the last replayed record, which is
@@ -565,6 +580,9 @@ StartReplication(StartReplicationCmd *cmd)
 		Assert(streamingDoneSending && streamingDoneReceiving);
 	}
 
+	if (cmd->slotname)
+		ReplicationSlotRelease();
+
 	/*
 	 * Copy is finished now. Send a single-row result set indicating the next
 	 * timeline.
@@ -623,6 +641,75 @@ StartReplication(StartReplicationCmd *cmd)
 }
 
 /*
+ * Create a new replication slot.
+ */
+static void
+CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
+{
+	const char *slot_name;
+	StringInfoData buf;
+
+	Assert(!MyReplicationSlot);
+
+	/* setup state for XLogReadPage */
+	sendTimeLineIsHistoric = false;
+	sendTimeLine = ThisTimeLineID;
+
+	ReplicationSlotCreate(cmd->slotname, cmd->kind == REPLICATION_KIND_LOGICAL);
+
+	initStringInfo(&output_message);
+
+	slot_name = NameStr(MyReplicationSlot->data.name);
+
+	/*
+	 * It may seem somewhat pointless to send back the same slot name the
+	 * client just requested and nothing else, but logical replication
+	 * will add more fields here.  (We could consider removing the slot
+	 * name from what's sent back, though, since the client has specified
+	 * that.)
+	 */
+
+	pq_beginmessage(&buf, 'T');
+	pq_sendint(&buf, 1, 2);		/* 1 field */
+
+	/* first field: slot name */
+	pq_sendstring(&buf, "slot_name");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
+	pq_endmessage(&buf);
+
+	/* Send a DataRow message */
+	pq_beginmessage(&buf, 'D');
+	pq_sendint(&buf, 1, 2);		/* # of columns */
+
+	/* slot_name */
+	pq_sendint(&buf, strlen(slot_name), 4); /* col1 len */
+	pq_sendbytes(&buf, slot_name, strlen(slot_name));
+
+	pq_endmessage(&buf);
+
+	/*
+	 * release active status again, START_REPLICATION will reacquire it
+	 */
+	ReplicationSlotRelease();
+}
+
+/*
+ * Get rid of a replication slot that is no longer wanted.
+ */
+static void
+DropReplicationSlot(DropReplicationSlotCmd *cmd)
+{
+	ReplicationSlotDrop(cmd->slotname);
+	EndCommand("DROP_REPLICATION_SLOT", DestRemote);
+}
+
+/*
  * Execute an incoming replication command.
  */
 void
@@ -660,14 +747,28 @@ exec_replication_command(const char *cmd_string)
 			IdentifySystem();
 			break;
 
-		case T_StartReplicationCmd:
-			StartReplication((StartReplicationCmd *) cmd_node);
-			break;
-
 		case T_BaseBackupCmd:
 			SendBaseBackup((BaseBackupCmd *) cmd_node);
 			break;
 
+		case T_CreateReplicationSlotCmd:
+			CreateReplicationSlot((CreateReplicationSlotCmd *) cmd_node);
+			break;
+
+		case T_DropReplicationSlotCmd:
+			DropReplicationSlot((DropReplicationSlotCmd *) cmd_node);
+			break;
+
+		case T_StartReplicationCmd:
+			{
+				StartReplicationCmd *cmd = (StartReplicationCmd *) cmd_node;
+				if (cmd->kind == REPLICATION_KIND_PHYSICAL)
+					StartReplication(cmd);
+				else
+					elog(ERROR, "cannot handle changeset extraction yet");
+				break;
+			}
+
 		case T_TimeLineHistoryCmd:
 			SendTimeLineHistory((TimeLineHistoryCmd *) cmd_node);
 			break;
@@ -831,6 +932,39 @@ ProcessStandbyMessage(void)
 }
 
 /*
+ * Remember that a walreceiver just confirmed receipt of lsn `lsn`.
+ */
+static void
+PhysicalConfirmReceivedLocation(XLogRecPtr lsn)
+{
+	bool changed = false;
+	/* use volatile pointer to prevent code rearrangement */
+	volatile ReplicationSlot *slot = MyReplicationSlot;
+
+	Assert(lsn != InvalidXLogRecPtr);
+	SpinLockAcquire(&slot->mutex);
+	if (slot->data.restart_lsn != lsn)
+	{
+		changed = true;
+		slot->data.restart_lsn = lsn;
+	}
+	SpinLockRelease(&slot->mutex);
+
+	if (changed)
+	{
+		ReplicationSlotMarkDirty();
+		ReplicationSlotsComputeRequiredLSN();
+	}
+
+	/*
+	 * One could argue that the slot should saved to disk now, but that'd be
+	 * energy wasted - the worst lost information can do here is give us wrong
+	 * information in a statistics view - we'll just potentially be more
+	 * conservative in removing files.
+	 */
+}
+
+/*
  * Regular reply from standby advising of WAL positions on standby server.
  */
 static void
@@ -875,6 +1009,48 @@ ProcessStandbyReplyMessage(void)
 
 	if (!am_cascading_walsender)
 		SyncRepReleaseWaiters();
+
+	/*
+	 * Advance our local xmin horizon when the client confirmed a flush.
+	 */
+	if (MyReplicationSlot && flushPtr != InvalidXLogRecPtr)
+	{
+		if (MyReplicationSlot->data.database != InvalidOid)
+			elog(ERROR, "cannot handle changeset extraction yet");
+		else
+			PhysicalConfirmReceivedLocation(flushPtr);
+	}
+}
+
+/* compute new replication slot xmin horizon if needed */
+static void
+PhysicalReplicationSlotNewXmin(TransactionId feedbackXmin)
+{
+	bool changed = false;
+	volatile ReplicationSlot *slot = MyReplicationSlot;
+
+	SpinLockAcquire(&slot->mutex);
+	MyPgXact->xmin = InvalidTransactionId;
+	/*
+	 * For physical replication we don't need the the interlock provided
+	 * by xmin and effective_xmin since the consequences of a missed increase
+	 * are limited to query cancellations, so set both at once.
+	 */
+	if (!TransactionIdIsNormal(slot->data.xmin) ||
+		!TransactionIdIsNormal(feedbackXmin) ||
+		TransactionIdPrecedes(slot->data.xmin, feedbackXmin))
+	{
+		changed = true;
+		slot->data.xmin = feedbackXmin;
+		slot->effective_xmin = feedbackXmin;
+	}
+	SpinLockRelease(&slot->mutex);
+
+	if (changed)
+	{
+		ReplicationSlotMarkDirty();
+		ReplicationSlotsComputeRequiredXmin();
+	}
 }
 
 /*
@@ -904,6 +1080,8 @@ ProcessStandbyHSFeedbackMessage(void)
 	if (!TransactionIdIsNormal(feedbackXmin))
 	{
 		MyPgXact->xmin = InvalidTransactionId;
+		if (MyReplicationSlot != NULL)
+			PhysicalReplicationSlotNewXmin(feedbackXmin);
 		return;
 	}
 
@@ -951,8 +1129,17 @@ ProcessStandbyHSFeedbackMessage(void)
 	 * GetOldestXmin.  (If we're moving our xmin forward, this is obviously
 	 * safe, and if we're moving it backwards, well, the data is at risk
 	 * already since a VACUUM could have just finished calling GetOldestXmin.)
+	 *
+	 * If we're using a replication slot we reserve the xmin via that,
+	 * otherwise via the walsender's PGXACT entry.
+
+	 * XXX: It might make sense to introduce ephemeral slots and always use
+	 * the slot mechanism.
 	 */
-	MyPgXact->xmin = feedbackXmin;
+	if (MyReplicationSlot != NULL) /* XXX: persistency configurable? */
+		PhysicalReplicationSlotNewXmin(feedbackXmin);
+	else
+		MyPgXact->xmin = feedbackXmin;
 }
 
 /* Main loop of walsender process that streams the WAL over Copy messages. */
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 2e71745..c392d4f 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -27,6 +27,7 @@
 #include "postmaster/bgworker_internals.h"
 #include "postmaster/bgwriter.h"
 #include "postmaster/postmaster.h"
+#include "replication/slot.h"
 #include "replication/walreceiver.h"
 #include "replication/walsender.h"
 #include "storage/bufmgr.h"
@@ -126,6 +127,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 		size = add_size(size, ProcSignalShmemSize());
 		size = add_size(size, CheckpointerShmemSize());
 		size = add_size(size, AutoVacuumShmemSize());
+		size = add_size(size, ReplicationSlotsShmemSize());
 		size = add_size(size, WalSndShmemSize());
 		size = add_size(size, WalRcvShmemSize());
 		size = add_size(size, BTreeShmemSize());
@@ -230,6 +232,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 	ProcSignalShmemInit();
 	CheckpointerShmemInit();
 	AutoVacuumShmemInit();
+	ReplicationSlotsShmemInit();
 	WalSndShmemInit();
 	WalRcvShmemInit();
 
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index b68c956..082115b 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -82,6 +82,9 @@ typedef struct ProcArrayStruct
 	 */
 	TransactionId lastOverflowedXid;
 
+	/* oldest xmin of any replication slot */
+	TransactionId replication_slot_xmin;
+
 	/*
 	 * We declare pgprocnos[] as 1 entry because C wants a fixed-size array,
 	 * but actually it is maxProcs entries long.
@@ -228,6 +231,7 @@ CreateSharedProcArray(void)
 		 */
 		procArray->numProcs = 0;
 		procArray->maxProcs = PROCARRAY_MAXPROCS;
+		procArray->replication_slot_xmin = InvalidTransactionId;
 		procArray->maxKnownAssignedXids = TOTAL_MAX_CACHED_SUBXIDS;
 		procArray->numKnownAssignedXids = 0;
 		procArray->tailKnownAssignedXids = 0;
@@ -1153,6 +1157,7 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum)
 	ProcArrayStruct *arrayP = procArray;
 	TransactionId result;
 	int			index;
+	volatile TransactionId replication_slot_xmin = InvalidTransactionId;
 
 	/* Cannot look for individual databases during recovery */
 	Assert(allDbs || !RecoveryInProgress());
@@ -1204,6 +1209,9 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum)
 		}
 	}
 
+	/* fetch into volatile var while ProcArrayLock is held */
+	replication_slot_xmin = procArray->replication_slot_xmin;
+
 	if (RecoveryInProgress())
 	{
 		/*
@@ -1244,6 +1252,13 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum)
 			result = FirstNormalTransactionId;
 	}
 
+	/*
+	 * Check whether there are replication slots requiring an older xmin.
+	 */
+	if (TransactionIdIsValid(replication_slot_xmin) &&
+		NormalTransactionIdPrecedes(replication_slot_xmin, result))
+		result = replication_slot_xmin;
+
 	return result;
 }
 
@@ -1313,6 +1328,7 @@ GetSnapshotData(Snapshot snapshot)
 	int			count = 0;
 	int			subcount = 0;
 	bool		suboverflowed = false;
+	volatile TransactionId replication_slot_xmin = InvalidTransactionId;
 
 	Assert(snapshot != NULL);
 
@@ -1490,8 +1506,13 @@ GetSnapshotData(Snapshot snapshot)
 			suboverflowed = true;
 	}
 
+
+	/* fetch into volatile var while ProcArrayLock is held */
+	replication_slot_xmin = procArray->replication_slot_xmin;
+
 	if (!TransactionIdIsValid(MyPgXact->xmin))
 		MyPgXact->xmin = TransactionXmin = xmin;
+
 	LWLockRelease(ProcArrayLock);
 
 	/*
@@ -1506,6 +1527,12 @@ GetSnapshotData(Snapshot snapshot)
 	RecentGlobalXmin = globalxmin - vacuum_defer_cleanup_age;
 	if (!TransactionIdIsNormal(RecentGlobalXmin))
 		RecentGlobalXmin = FirstNormalTransactionId;
+
+	/* Check whether there's a replication slot requiring an older xmin. */
+	if (TransactionIdIsValid(replication_slot_xmin) &&
+		NormalTransactionIdPrecedes(replication_slot_xmin, RecentGlobalXmin))
+		RecentGlobalXmin = replication_slot_xmin;
+
 	RecentXmin = xmin;
 
 	snapshot->xmin = xmin;
@@ -2491,6 +2518,21 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
 	return true;				/* timed out, still conflicts */
 }
 
+/*
+ * ProcArraySetReplicationSlotXmin
+ *
+ * Install limits to future computations of the xmin horizon to prevent vacuum
+ * and HOT pruning from removing affected rows still needed by clients with
+ * replicaton slots.
+ */
+void
+ProcArraySetReplicationSlotXmin(TransactionId xmin)
+{
+	LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+	procArray->replication_slot_xmin = xmin;
+	LWLockRelease(ProcArrayLock);
+}
+
 
 #define XidCacheRemove(i) \
 	do { \
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 55d9d78..82ef440 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -27,6 +27,7 @@
 #include "commands/async.h"
 #include "miscadmin.h"
 #include "pg_trace.h"
+#include "replication/slot.h"
 #include "storage/ipc.h"
 #include "storage/predicate.h"
 #include "storage/proc.h"
@@ -238,6 +239,9 @@ NumLWLocks(void)
 	/* predicate.c needs one per old serializable xid buffer */
 	numLocks += NUM_OLDSERXID_BUFFERS;
 
+	/* slot.c needs one for each slot */
+	numLocks += max_replication_slots;
+
 	/*
 	 * Add any requested by loadable modules; for backwards-compatibility
 	 * reasons, allocate at least NUM_USER_DEFINED_LWLOCKS of them even if
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 1a683b8..45a4822 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -40,6 +40,7 @@
 #include "access/xact.h"
 #include "miscadmin.h"
 #include "postmaster/autovacuum.h"
+#include "replication/slot.h"
 #include "replication/syncrep.h"
 #include "storage/ipc.h"
 #include "storage/lmgr.h"
@@ -779,6 +780,10 @@ ProcKill(int code, Datum arg)
 	/* Make sure we're out of the sync rep lists */
 	SyncRepCleanupAtProcExit();
 
+	/* Make sure active replication slots are released */
+	if (MyReplicationSlot != NULL)
+		ReplicationSlotRelease();
+
 #ifdef USE_ASSERT_CHECKING
 	if (assert_enabled)
 	{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index a9b9794..70d73d9 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -57,6 +57,7 @@
 #include "postmaster/postmaster.h"
 #include "postmaster/syslogger.h"
 #include "postmaster/walwriter.h"
+#include "replication/slot.h"
 #include "replication/syncrep.h"
 #include "replication/walreceiver.h"
 #include "replication/walsender.h"
@@ -2124,6 +2125,17 @@ static struct config_int ConfigureNamesInt[] =
 	},
 
 	{
+		/* see max_connections */
+		{"max_replication_slots", PGC_POSTMASTER, REPLICATION_SENDING,
+			gettext_noop("Sets the maximum number of simultaneously defined replication slots."),
+			NULL
+		},
+		&max_replication_slots,
+		0, 0, MAX_BACKENDS /* XXX?*/,
+		NULL, NULL, NULL
+	},
+
+	{
 		{"wal_sender_timeout", PGC_SIGHUP, REPLICATION_SENDING,
 			gettext_noop("Sets the maximum time to wait for WAL replication."),
 			NULL,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index c8673b3..d10e8a5 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -226,6 +226,9 @@
 #wal_keep_segments = 0		# in logfile segments, 16MB each; 0 disables
 #wal_sender_timeout = 60s	# in milliseconds; 0 disables
 
+#max_replication_slots = 0	# max number of replication slots.
+				# (change requires restart)
+
 # - Master Server -
 
 # These settings are ignored on a standby server.
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 6b5302f..a71320d 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -195,6 +195,7 @@ const char *subdirs[] = {
 	"pg_multixact/offsets",
 	"base",
 	"base/1",
+	"pg_replslot",
 	"pg_tblspc",
 	"pg_stat",
 	"pg_stat_tmp"
diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c
index 3c6ab9a..8a702e3 100644
--- a/src/bin/pg_basebackup/pg_receivexlog.c
+++ b/src/bin/pg_basebackup/pg_receivexlog.c
@@ -67,6 +67,7 @@ usage(void)
 	printf(_("  -U, --username=NAME    connect as specified database user\n"));
 	printf(_("  -w, --no-password      never prompt for password\n"));
 	printf(_("  -W, --password         force password prompt (should happen automatically)\n"));
+	printf(_("      --slot             replication slot to use\n"));
 	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
 }
 
@@ -343,6 +344,7 @@ main(int argc, char **argv)
 		{"no-password", no_argument, NULL, 'w'},
 		{"password", no_argument, NULL, 'W'},
 		{"status-interval", required_argument, NULL, 's'},
+		{"slot", required_argument, NULL, 'S'},
 		{"verbose", no_argument, NULL, 'v'},
 		{NULL, 0, NULL, 0}
 	};
@@ -409,6 +411,9 @@ main(int argc, char **argv)
 					exit(1);
 				}
 				break;
+			case 'S':
+				replication_slot = pg_strdup(optarg);
+				break;
 			case 'n':
 				noloop = 1;
 				break;
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index 2555904..7d3c76c 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -31,6 +31,8 @@
 /* fd and filename for currently open WAL file */
 static int	walfile = -1;
 static char current_walfile_name[MAXPGPATH] = "";
+static bool reportFlushPosition = false;
+static XLogRecPtr lastFlushPosition = InvalidXLogRecPtr;
 
 static PGresult *HandleCopyStream(PGconn *conn, XLogRecPtr startpos,
 				 uint32 timeline, char *basedir,
@@ -133,7 +135,7 @@ open_walfile(XLogRecPtr startpoint, uint32 timeline, char *basedir,
  * and returns false, otherwise returns true.
  */
 static bool
-close_walfile(char *basedir, char *partial_suffix)
+close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos)
 {
 	off_t		currpos;
 
@@ -187,6 +189,7 @@ close_walfile(char *basedir, char *partial_suffix)
 				_("%s: not renaming \"%s%s\", segment is not complete\n"),
 				progname, current_walfile_name, partial_suffix);
 
+	lastFlushPosition = pos;
 	return true;
 }
 
@@ -421,7 +424,10 @@ sendFeedback(PGconn *conn, XLogRecPtr blockpos, int64 now, bool replyRequested)
 	len += 1;
 	sendint64(blockpos, &replybuf[len]);		/* write */
 	len += 8;
-	sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
+	if (reportFlushPosition)
+		sendint64(lastFlushPosition, &replybuf[len]);		/* flush */
+	else
+		sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
 	len += 8;
 	sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
 	len += 8;
@@ -511,6 +517,7 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 				  int standby_message_timeout, char *partial_suffix)
 {
 	char		query[128];
+	char		slotcmd[128];
 	PGresult   *res;
 	XLogRecPtr	stoppos;
 
@@ -521,6 +528,29 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 	if (!CheckServerVersionForStreaming(conn))
 		return false;
 
+	if (replication_slot != NULL)
+	{
+		/*
+		 * Report the flush position, so the primary can know what WAL we'll
+		 * possibly re-request, and remove older WAL safely.
+		 *
+		 * We only report it when a slot has explicitly been used, because
+		 * reporting the flush position makes one elegible as a synchronous
+		 * replica. People shouldn't include generic names in
+		 * synchronous_standby_names, but we've protected them against it so
+		 * far, so let's continue to do so in the situations when possible.
+		 * If they've got a slot, though, we need to report the flush position,
+		 * so that the master can remove WAL.
+		 */
+		reportFlushPosition = true;
+		sprintf(slotcmd, "SLOT \"%s\" ", replication_slot);
+	}
+	else
+	{
+		reportFlushPosition = false;
+		slotcmd[0] = 0;
+	}
+
 	if (sysidentifier != NULL)
 	{
 		/* Validate system identifier hasn't changed */
@@ -560,6 +590,12 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 		PQclear(res);
 	}
 
+	/*
+	 * initialize flush position to starting point, it's the caller's
+	 * responsibility that that's sane.
+	 */
+	lastFlushPosition = startpos;
+
 	while (1)
 	{
 		/*
@@ -606,7 +642,8 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 			return true;
 
 		/* Initiate the replication stream at specified location */
-		snprintf(query, sizeof(query), "START_REPLICATION %X/%X TIMELINE %u",
+		snprintf(query, sizeof(query), "START_REPLICATION %s%X/%X TIMELINE %u",
+				 slotcmd,
 				 (uint32) (startpos >> 32), (uint32) startpos,
 				 timeline);
 		res = PQexec(conn, query);
@@ -810,7 +847,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 		 */
 		if (still_sending && stream_stop(blockpos, timeline, false))
 		{
-			if (!close_walfile(basedir, partial_suffix))
+			if (!close_walfile(basedir, partial_suffix, blockpos))
 			{
 				/* Potential error message is written by close_walfile */
 				goto error;
@@ -909,7 +946,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 			 */
 			if (still_sending)
 			{
-				if (!close_walfile(basedir, partial_suffix))
+				if (!close_walfile(basedir, partial_suffix, blockpos))
 				{
 					/* Error message written in close_walfile() */
 					goto error;
@@ -1074,7 +1111,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 				/* Did we reach the end of a WAL segment? */
 				if (blockpos % XLOG_SEG_SIZE == 0)
 				{
-					if (!close_walfile(basedir, partial_suffix))
+					if (!close_walfile(basedir, partial_suffix, blockpos))
 						/* Error message written in close_walfile() */
 						goto error;
 
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 96fbed8..041076f 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -22,6 +22,7 @@ char	   *connection_string = NULL;
 char	   *dbhost = NULL;
 char	   *dbuser = NULL;
 char	   *dbport = NULL;
+char	   *replication_slot = NULL;
 int			dbgetpassword = 0;	/* 0=auto, -1=never, 1=always */
 static char *dbpassword = NULL;
 PGconn	   *conn = NULL;
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index 77d6b86..bb3c34d 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -6,6 +6,7 @@ extern char *dbhost;
 extern char *dbuser;
 extern char *dbport;
 extern int	dbgetpassword;
+extern char *replication_slot;
 
 /* Connection kept global so we can disconnect easily */
 extern PGconn *conn;
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 47e3022..11ab277 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -289,6 +289,7 @@ extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std);
 
 extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);
 extern void XLogSetAsyncXactLSN(XLogRecPtr record);
+extern void XLogSetReplicationSlotMinimumLSN(XLogRecPtr lsn);
 
 extern Buffer RestoreBackupBlock(XLogRecPtr lsn, XLogRecord *record,
 				   int block_index,
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 9fc61eb..a8d2fb1 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -4778,6 +4778,14 @@ DESCR("SP-GiST support for quad tree over range");
 DATA(insert OID = 3473 (  spg_range_quad_leaf_consistent	PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "2281 2281" _null_ _null_ _null_ _null_  spg_range_quad_leaf_consistent _null_ _null_ _null_ ));
 DESCR("SP-GiST support for quad tree over range");
 
+/* replication slots */
+DATA(insert OID = 3780 (  pg_create_physical_replication_slot PGNSP PGUID 12 1 0 0 0 f f f f f f v 1 0 2249 "19" "{19,25,25}" "{i,o,o}" "{slotname,slotname,xlog_position}" _null_ pg_create_physical_replication_slot _null_ _null_ _null_ ));
+DESCR("create a physical replication slot");
+DATA(insert OID = 3781 (  pg_drop_replication_slot PGNSP PGUID 12 1 0 0 0 f f f f f f v 1 0 2278 "19" _null_ _null_ _null_ _null_ pg_drop_replication_slot _null_ _null_ _null_ ));
+DESCR("drop a replication slot");
+DATA(insert OID = 3475 (  pg_get_replication_slots	PGNSP PGUID 12 1 10 0 0 f f f f f t s 0 0 2249 "" "{25,25,26,16,28,25}" "{o,o,o,o,o,o}" "{slot_name,slot_type,datoid,active,xmin,restart_lsn}" _null_ pg_get_replication_slots _null_ _null_ _null_ ));
+DESCR("information about replication slots currently in use");
+
 /* event triggers */
 DATA(insert OID = 3566 (  pg_event_trigger_dropped_objects		PGNSP PGUID 12 10 100 0 0 f f f f t t s 0 0 2249 "" "{26,26,23,25,25,25,25}" "{o,o,o,o,o,o,o}" "{classid, objid, objsubid, object_type, schema_name, object_name, object_identity}" _null_ pg_event_trigger_dropped_objects _null_ _null_ _null_ ));
 DESCR("list objects dropped by the current command");
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index dfcc013..5b8df59 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -412,6 +412,8 @@ typedef enum NodeTag
 	 */
 	T_IdentifySystemCmd,
 	T_BaseBackupCmd,
+	T_CreateReplicationSlotCmd,
+	T_DropReplicationSlotCmd,
 	T_StartReplicationCmd,
 	T_TimeLineHistoryCmd,
 
diff --git a/src/include/nodes/replnodes.h b/src/include/nodes/replnodes.h
index 4097115..aac75fd 100644
--- a/src/include/nodes/replnodes.h
+++ b/src/include/nodes/replnodes.h
@@ -17,6 +17,11 @@
 #include "access/xlogdefs.h"
 #include "nodes/pg_list.h"
 
+typedef enum ReplicationKind {
+	REPLICATION_KIND_PHYSICAL,
+	REPLICATION_KIND_LOGICAL
+} ReplicationKind;
+
 
 /* ----------------------
  *		IDENTIFY_SYSTEM command
@@ -40,14 +45,41 @@ typedef struct BaseBackupCmd
 
 
 /* ----------------------
+ *		CREATE_REPLICATION_SLOT command
+ * ----------------------
+ */
+typedef struct CreateReplicationSlotCmd
+{
+	NodeTag		type;
+	char       *slotname;
+	ReplicationKind kind;
+	char       *plugin;
+} CreateReplicationSlotCmd;
+
+
+/* ----------------------
+ *		DROP_REPLICATION_SLOT command
+ * ----------------------
+ */
+typedef struct DropReplicationSlotCmd
+{
+	NodeTag		type;
+	char       *slotname;
+} DropReplicationSlotCmd;
+
+
+/* ----------------------
  *		START_REPLICATION command
  * ----------------------
  */
 typedef struct StartReplicationCmd
 {
 	NodeTag		type;
+	ReplicationKind kind;
+	char	   *slotname;
 	TimeLineID	timeline;
 	XLogRecPtr	startpoint;
+	List       *options;
 } StartReplicationCmd;
 
 
diff --git a/src/include/replication/slot.h b/src/include/replication/slot.h
new file mode 100644
index 0000000..089b0f4
--- /dev/null
+++ b/src/include/replication/slot.h
@@ -0,0 +1,120 @@
+/*-------------------------------------------------------------------------
+ * slot.h
+ *	   Replication slot management.
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SLOT_H
+#define SLOT_H
+
+#include "fmgr.h"
+#include "access/xlog.h"
+#include "access/xlogreader.h"
+#include "storage/lwlock.h"
+#include "storage/shmem.h"
+#include "storage/spin.h"
+
+typedef struct ReplicationSlotPersistentData
+{
+	/* The slot's identifier */
+	NameData	name;
+
+	/* database the slot is active on */
+	Oid			database;
+
+	/*
+	 * xmin horizon for data
+	 *
+	 * NB: This may represent a value that hasn't been written to disk yet;
+	 * see notes for effective_xmin, below.
+	 */
+	TransactionId xmin;
+
+	/* oldest LSN that might be required by this replication slot */
+	XLogRecPtr	restart_lsn;
+
+} ReplicationSlotPersistentData;
+
+/*
+ * Shared memory state of a single replication slot.
+ */
+typedef struct ReplicationSlot
+{
+	/* lock, on same cacheline as effective_xmin */
+	slock_t		mutex;
+
+	/* is this slot defined */
+	bool		in_use;
+
+	/* is somebody streaming out changes for this slot */
+	bool		active;
+
+	/* any outstanding modifications? */
+	bool		just_dirtied;
+	bool		dirty;
+
+	/*
+	 * For logical decoding, it's extremely important that we never remove any
+	 * data that's still needed for decoding purposes, even after a crash;
+	 * otherwise, decoding will produce wrong answers.  Ordinary streaming
+	 * replication also needs to prevent old row versions from being removed
+	 * too soon, but the worst consequence we might encounter there is unwanted
+	 * query cancellations on the standby.  Thus, for logical decoding,
+	 * this value represents the latest xmin that has actually been
+	 * written to disk, whereas for streaming replication, it's just the
+	 * same as the persistent value (data.xmin).
+	 */
+	TransactionId effective_xmin;
+
+	/* data surviving shutdowns and crashes */
+	ReplicationSlotPersistentData data;
+
+	/* is somebody performing io on this slot? */
+	LWLock	   *io_in_progress_lock;
+} ReplicationSlot;
+
+/*
+ * Shared memory control area for all of replication slots.
+ */
+typedef struct ReplicationSlotCtlData
+{
+	ReplicationSlot replication_slots[1];
+} ReplicationSlotCtlData;
+
+/*
+ * Pointers to shared memory
+ */
+extern ReplicationSlotCtlData *ReplicationSlotCtl;
+extern ReplicationSlot *MyReplicationSlot;
+
+/* GUCs */
+extern PGDLLIMPORT int max_replication_slots;
+
+/* shmem initialization functions */
+extern Size ReplicationSlotsShmemSize(void);
+extern void ReplicationSlotsShmemInit(void);
+
+/* management of individual slots */
+extern void ReplicationSlotCreate(const char *name, bool db_specific);
+extern void ReplicationSlotDrop(const char *name);
+extern void ReplicationSlotAcquire(const char *name);
+extern void ReplicationSlotRelease(void);
+extern void ReplicationSlotSave(void);
+extern void ReplicationSlotMarkDirty(void);
+
+/* misc stuff */
+extern bool ReplicationSlotValidateName(const char *name, int elevel);
+extern void ReplicationSlotsComputeRequiredXmin(void);
+extern void ReplicationSlotsComputeRequiredLSN(void);
+extern void StartupReplicationSlots(XLogRecPtr checkPointRedo);
+extern void CheckPointReplicationSlots(void);
+
+extern void CheckSlotRequirements(void);
+extern void ReplicationSlotAtProcExit(void);
+
+/* SQL callable functions */
+extern Datum pg_get_replication_slots(PG_FUNCTION_ARGS);
+
+#endif /* SLOT_H */
diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h
index 3c65619..3d94010 100644
--- a/src/include/replication/walreceiver.h
+++ b/src/include/replication/walreceiver.h
@@ -103,6 +103,12 @@ typedef struct
 	 */
 	char		conninfo[MAXCONNINFO];
 
+	/*
+	 * replication slot name; is also used for walreceiver to connect with
+	 * the primary
+	 */
+	char		slotname[NAMEDATALEN];
+
 	slock_t		mutex;			/* locks shared variables shown above */
 
 	/*
@@ -125,7 +131,7 @@ extern PGDLLIMPORT walrcv_identify_system_type walrcv_identify_system;
 typedef void (*walrcv_readtimelinehistoryfile_type) (TimeLineID tli, char **filename, char **content, int *size);
 extern PGDLLIMPORT walrcv_readtimelinehistoryfile_type walrcv_readtimelinehistoryfile;
 
-typedef bool (*walrcv_startstreaming_type) (TimeLineID tli, XLogRecPtr startpoint);
+typedef bool (*walrcv_startstreaming_type) (TimeLineID tli, XLogRecPtr startpoint, char *slotname);
 extern PGDLLIMPORT walrcv_startstreaming_type walrcv_startstreaming;
 
 typedef void (*walrcv_endstreaming_type) (TimeLineID *next_tli);
@@ -149,7 +155,8 @@ extern void WalRcvShmemInit(void);
 extern void ShutdownWalRcv(void);
 extern bool WalRcvStreaming(void);
 extern bool WalRcvRunning(void);
-extern void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo);
+extern void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr,
+					 const char *conninfo, const char *slotname);
 extern XLogRecPtr GetWalRcvWriteRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI);
 extern int	GetReplicationApplyDelay(void);
 extern int	GetReplicationTransferLatency(void);
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 4507926..c8ff4eb 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -125,7 +125,9 @@ extern LWLockPadded *MainLWLockArray;
 #define BackgroundWorkerLock		(&MainLWLockArray[33].lock)
 #define DynamicSharedMemoryControlLock		(&MainLWLockArray[34].lock)
 #define AutoFileLock				(&MainLWLockArray[35].lock)
-#define NUM_INDIVIDUAL_LWLOCKS		36
+#define ReplicationSlotAllocationLock	(&MainLWLockArray[36].lock)
+#define ReplicationSlotControlLock		(&MainLWLockArray[37].lock)
+#define NUM_INDIVIDUAL_LWLOCKS		38
 
 /*
  * It's a bit odd to declare NUM_BUFFER_PARTITIONS and NUM_LOCK_PARTITIONS
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index 2947cc4..d1a58a3 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -77,4 +77,6 @@ extern void XidCacheRemoveRunningXids(TransactionId xid,
 						  int nxids, const TransactionId *xids,
 						  TransactionId latestXid);
 
+extern void ProcArraySetReplicationSlotXmin(TransactionId xmin);
+
 #endif   /* PROCARRAY_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 540373d..220e18b 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1367,6 +1367,15 @@ pg_prepared_xacts| SELECT p.transaction,
    FROM ((pg_prepared_xact() p(transaction, gid, prepared, ownerid, dbid)
    LEFT JOIN pg_authid u ON ((p.ownerid = u.oid)))
    LEFT JOIN pg_database d ON ((p.dbid = d.oid)));
+pg_replication_slots| SELECT l.slot_name,
+    l.slot_type,
+    l.datoid,
+    d.datname AS database,
+    l.active,
+    l.xmin,
+    l.restart_lsn
+   FROM (pg_get_replication_slots() l(slot_name, slot_type, datoid, active, xmin, restart_lsn)
+   LEFT JOIN pg_database d ON ((l.datoid = d.oid)));
 pg_roles| SELECT pg_authid.rolname,
     pg_authid.rolsuper,
     pg_authid.rolinherit,
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index ad40735..3b7f61e 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -343,6 +343,7 @@ CreateOpClassItem
 CreateOpClassStmt
 CreateOpFamilyStmt
 CreatePLangStmt
+CreateReplicationSlotCmd
 CreateRangeStmt
 CreateRoleStmt
 CreateSchemaStmt
@@ -416,6 +417,7 @@ DomainConstraintType
 DomainIOData
 DropBehavior
 DropOwnedStmt
+DropReplicationSlotCmd
 DropRoleStmt
 DropStmt
 DropTableSpaceStmt
#45Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#1)
5 attachment(s)
Re: Changeset Extraction v7.5

Hi,

attached you can find the next version of the patchset.

Changes:
* rebased ontop the committed slot patch (Thanks Robert!), that required
a fair amount of work
* adjusted naming of the SQL interface functions, to be consisted with ^
* several patches of the patchseries were merged
* Large amount of comment copy-editing
* Some code restructuring

There's one major things I am not yet really happy with which is the is
the integration of how decoding snapshots are integrated. I've gone back
and forth over it today, but I think I need a decent night of sleep to
bring it to a conclusion...

The patches are currently:

0001: wal_decoding: Introduce logical changeset extraction.
The meat of the functionality, including the SQL interface.

0002: wal_decoding: logical changeset extraction walsender interface
Walsender integration of changeset extraction, including support for
synchronous replication.

0003: wal_decoding: pg_recvlogical: Introduce pg_receivexlog equivalent for logical changes
Simple tool for receiving the changes over the walsender interface.

0004: wal_decoding: Documentation for replication slots and changeset extraction
...

0005: wal_decoding: Temporarily add logical decoding regression tests to everything
This is a patch I don't think should be finally applied, but which is
very helpful during debugging. It simply adds tests to the beginning/end of
the normal regression tests, decoding it in its entirety.

As always it's also pushed to
http://git.postgresql.org/gitweb/?p=users/andresfreund/postgres.git;a=summary
branch xlog-decoding-rebasing-remapping

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-wal_decoding-Introduce-logical-changeset-extraction.patchtext/x-patch; charset=us-asciiDownload
From 12e7eb0e34a09ea3c2778b7ef8f8799f46026671 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 27 Jan 2014 17:13:48 +0100
Subject: [PATCH 1/5] wal_decoding: Introduce logical changeset extraction.

This feature allows to extract changes made to database tables in a
consistent transactional order, in a user configurable format with a
low added overhead. The output format is determined by so called
output plugins, which can be externally supplied extensions.
One example output plugin "test_decoding" is included and used in
regression tests.

Internally this adds several new components:
* The 'reorderbuffer' module which reassembles transactions from a
  stream of interspersed changes
* 'snapbuilder' which builds catalog snapshots so that tuples from WAL
  can be understood
* wal decoding into an reorderbuffer
* output plugin infrastructure with 5 callbacks
 * startup
 * begin
 * change
 * commit
 * shutdown

Code By:
Andres Freund

Contributions By:
Robert Haas
Alvaro Herrera
Abhijit Menon-Sen
Craig Ringer

Input, Testing and Review by:
Peter Gheogegan
Kevin Grittner
Robert Haas
Heikki Linnakangas
Fujii Masao
Abhijit Menon-Sen
Michael Paquier
Simon Riggs
Steve Singer
---
 contrib/Makefile                                   |    1 +
 contrib/test_decoding/Makefile                     |   71 +
 contrib/test_decoding/README                       |    3 +
 contrib/test_decoding/expected/ddl.out             |  645 +++++
 contrib/test_decoding/expected/delayed_startup.out |   38 +
 contrib/test_decoding/expected/mxact.out           |   66 +
 contrib/test_decoding/expected/permissions.out     |  131 +
 contrib/test_decoding/expected/rewrite.out         |  109 +
 contrib/test_decoding/expected/slot.out            |  178 ++
 contrib/test_decoding/expected/toast.out           |   95 +
 contrib/test_decoding/logical.conf                 |    2 +
 contrib/test_decoding/specs/delayed_startup.spec   |   27 +
 contrib/test_decoding/specs/mxact.spec             |   41 +
 contrib/test_decoding/sql/ddl.sql                  |  331 +++
 contrib/test_decoding/sql/permissions.sql          |   70 +
 contrib/test_decoding/sql/rewrite.sql              |   64 +
 contrib/test_decoding/sql/slot.sql                 |   75 +
 contrib/test_decoding/sql/toast.sql                |   54 +
 contrib/test_decoding/test_decoding--1.0.sql       |    2 +
 contrib/test_decoding/test_decoding.c              |  340 +++
 contrib/test_decoding/test_decoding.control        |    5 +
 contrib/test_decoding/test_decoding_regsupport.c   |  129 +
 doc/src/sgml/contrib.sgml                          |    1 +
 doc/src/sgml/test-decoding.sgml                    |   55 +
 src/Makefile.global.in                             |    2 +
 src/backend/access/heap/heapam.c                   |   22 +-
 src/backend/access/heap/rewriteheap.c              |  600 +++-
 src/backend/access/index/indexam.c                 |   14 +-
 src/backend/access/rmgrdesc/heapdesc.c             |    4 +
 src/backend/access/transam/xlog.c                  |   17 +-
 src/backend/catalog/index.c                        |   12 +-
 src/backend/catalog/system_views.sql               |    2 +
 src/backend/commands/analyze.c                     |    5 +-
 src/backend/commands/cluster.c                     |   10 +-
 src/backend/commands/dbcommands.c                  |   16 +
 src/backend/commands/vacuum.c                      |    5 +-
 src/backend/commands/vacuumlazy.c                  |    3 +
 src/backend/replication/Makefile                   |    2 +
 src/backend/replication/logical/Makefile           |   19 +
 src/backend/replication/logical/decode.c           |  801 ++++++
 src/backend/replication/logical/logical.c          |  809 ++++++
 src/backend/replication/logical/logicalfuncs.c     |  550 ++++
 src/backend/replication/logical/reorderbuffer.c    | 2923 ++++++++++++++++++++
 src/backend/replication/logical/snapbuild.c        | 1874 +++++++++++++
 src/backend/replication/slot.c                     |   63 +-
 src/backend/replication/slotfuncs.c                |   16 +-
 src/backend/replication/walreceiver.c              |    2 +-
 src/backend/replication/walsender.c                |    3 +-
 src/backend/storage/ipc/procarray.c                |  175 +-
 src/backend/storage/ipc/standby.c                  |   15 +
 src/backend/utils/cache/inval.c                    |    4 +-
 src/backend/utils/cache/relcache.c                 |   52 +-
 src/backend/utils/time/snapmgr.c                   |   12 +-
 src/backend/utils/time/tqual.c                     |  275 +-
 src/bin/initdb/initdb.c                            |    5 +-
 src/include/access/heapam_xlog.h                   |   14 +-
 src/include/access/rewriteheap.h                   |   30 +-
 src/include/access/transam.h                       |    5 +
 src/include/catalog/pg_proc.h                      |   12 +-
 src/include/commands/vacuum.h                      |    2 +-
 src/include/replication/decode.h                   |   19 +
 src/include/replication/logical.h                  |  107 +
 src/include/replication/logicalfuncs.h             |   25 +
 src/include/replication/output_plugin.h            |   83 +
 src/include/replication/reorderbuffer.h            |  349 +++
 src/include/replication/slot.h                     |   29 +-
 src/include/replication/snapbuild.h                |   83 +
 src/include/storage/itemptr.h                      |    3 +
 src/include/storage/proc.h                         |    6 +-
 src/include/storage/procarray.h                    |    9 +-
 src/include/storage/sinval.h                       |    2 +
 src/include/utils/inval.h                          |    1 +
 src/include/utils/snapmgr.h                        |    3 +
 src/include/utils/tqual.h                          |   23 +-
 src/test/regress/expected/rules.out                |    4 +-
 src/tools/pgindent/typedefs.list                   |   33 +
 76 files changed, 11628 insertions(+), 59 deletions(-)
 create mode 100644 contrib/test_decoding/Makefile
 create mode 100644 contrib/test_decoding/README
 create mode 100644 contrib/test_decoding/expected/ddl.out
 create mode 100644 contrib/test_decoding/expected/delayed_startup.out
 create mode 100644 contrib/test_decoding/expected/mxact.out
 create mode 100644 contrib/test_decoding/expected/permissions.out
 create mode 100644 contrib/test_decoding/expected/rewrite.out
 create mode 100644 contrib/test_decoding/expected/slot.out
 create mode 100644 contrib/test_decoding/expected/toast.out
 create mode 100644 contrib/test_decoding/logical.conf
 create mode 100644 contrib/test_decoding/specs/delayed_startup.spec
 create mode 100644 contrib/test_decoding/specs/mxact.spec
 create mode 100644 contrib/test_decoding/sql/ddl.sql
 create mode 100644 contrib/test_decoding/sql/permissions.sql
 create mode 100644 contrib/test_decoding/sql/rewrite.sql
 create mode 100644 contrib/test_decoding/sql/slot.sql
 create mode 100644 contrib/test_decoding/sql/toast.sql
 create mode 100644 contrib/test_decoding/test_decoding--1.0.sql
 create mode 100644 contrib/test_decoding/test_decoding.c
 create mode 100644 contrib/test_decoding/test_decoding.control
 create mode 100644 contrib/test_decoding/test_decoding_regsupport.c
 create mode 100644 doc/src/sgml/test-decoding.sgml
 create mode 100644 src/backend/replication/logical/Makefile
 create mode 100644 src/backend/replication/logical/decode.c
 create mode 100644 src/backend/replication/logical/logical.c
 create mode 100644 src/backend/replication/logical/logicalfuncs.c
 create mode 100644 src/backend/replication/logical/reorderbuffer.c
 create mode 100644 src/backend/replication/logical/snapbuild.c
 create mode 100644 src/include/replication/decode.h
 create mode 100644 src/include/replication/logical.h
 create mode 100644 src/include/replication/logicalfuncs.h
 create mode 100644 src/include/replication/output_plugin.h
 create mode 100644 src/include/replication/reorderbuffer.h
 create mode 100644 src/include/replication/snapbuild.h

diff --git a/contrib/Makefile b/contrib/Makefile
index c90fe29..8dc40f7 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -50,6 +50,7 @@ SUBDIRS = \
 		spi		\
 		tablefunc	\
 		tcn		\
+		test_decoding	\
 		test_parser	\
 		test_shm_mq	\
 		tsearch2	\
diff --git a/contrib/test_decoding/Makefile b/contrib/test_decoding/Makefile
new file mode 100644
index 0000000..ab14544
--- /dev/null
+++ b/contrib/test_decoding/Makefile
@@ -0,0 +1,71 @@
+# contrib/test_decoding/Makefile
+
+MODULES = test_decoding test_decoding_regsupport
+EXTENSION = test_decoding
+OBJS = test_decoding.o test_decoding_regsupport.o
+DATA = test_decoding--1.0.sql
+
+# Note: because we don't tell the Makefile there are any regression tests,
+# we have to clean those result files explicitly
+EXTRA_CLEAN = -r $(pg_regress_clean_files)
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/test_decoding
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
+
+# Disabled because these tests require "wal_level=logical", which
+# typical installcheck users do not have (e.g. buildfarm clients).
+installcheck:;
+
+# But it can nonetheless be very helpful to run tests on preexisting
+# installation, allow to do so, but only if requested explicitly.
+installcheck-force: regresscheck-install-force isolationcheck-install-force
+
+check: regresscheck isolationcheck
+
+submake-regress:
+	$(MAKE) -C $(top_builddir)/src/test/regress all
+
+submake-isolation:
+	$(MAKE) -C $(top_builddir)/src/test/isolation all
+
+submake-test_decoding:
+	$(MAKE) -C $(top_builddir)/contrib/test_decoding
+
+REGRESSCHECKS=slot ddl rewrite toast permissions
+
+regresscheck: all | submake-regress submake-test_decoding
+	$(pg_regress_check) \
+	    --temp-config $(top_srcdir)/contrib/test_decoding/logical.conf \
+	    --temp-install=./tmp_check \
+	    --extra-install=contrib/test_decoding \
+	    $(REGRESSCHECKS)
+
+regresscheck-install-force: | submake-regress submake-test_decoding
+	$(pg_regress_installcheck) \
+	    --extra-install=contrib/test_decoding \
+	    $(REGRESSCHECKS)
+
+ISOLATIONCHECKS=mxact delayed_startup
+
+isolationcheck: all | submake-isolation submake-test_decoding
+	$(pg_isolation_regress_check) \
+	    --temp-config $(top_srcdir)/contrib/test_decoding/logical.conf \
+	    --extra-install=contrib/test_decoding \
+	    $(ISOLATIONCHECKS)
+
+isolationcheck-install-force: all | submake-isolation submake-test_decoding
+	$(pg_isolation_regress_installcheck) \
+	    --extra-install=contrib/test_decoding \
+	    $(ISOLATIONCHECKS)
+
+PHONY: submake-test_decoding submake-regress check \
+	regresscheck regresscheck-install-force \
+	isolationcheck isolationcheck-install-force
diff --git a/contrib/test_decoding/README b/contrib/test_decoding/README
new file mode 100644
index 0000000..dce3712
--- /dev/null
+++ b/contrib/test_decoding/README
@@ -0,0 +1,3 @@
+The test_decoding extension is a plug-in for changeset extraction / logical
+replication in PostgreSQL. See the main changeset extraction documentation,
+source comments, and the contrib docs entry for this module.
diff --git a/contrib/test_decoding/expected/ddl.out b/contrib/test_decoding/expected/ddl.out
new file mode 100644
index 0000000..422a69c
--- /dev/null
+++ b/contrib/test_decoding/expected/ddl.out
@@ -0,0 +1,645 @@
+CREATE EXTENSION test_decoding;
+-- predictability
+SET synchronous_commit = on;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+-- fail because of an already existing slot
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ERROR:  replication slot "regression_slot" already exists
+-- fail because of an invalid name
+SELECT 'init' FROM pg_create_decoding_replication_slot('Invalid Name', 'test_decoding');
+ERROR:  replication slot name "Invalid Name" contains invalid character
+HINT:  Replication slot names may only contain letters, numbers and the underscore character.
+-- fail twice because of an invalid parameter values
+SELECT 'init' FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', 'frakbar');
+ERROR:  could not parse value "frakbar" for parameter "include-xids"
+CONTEXT:  slot "regression_slot", output plugin "test_decoding" during the pg_decode_startup callback
+SELECT 'init' FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'nonexistant-option', 'frakbar');
+ERROR:  option "nonexistant-option" = "frakbar" is unknown
+CONTEXT:  slot "regression_slot", output plugin "test_decoding" during the pg_decode_startup callback
+SELECT 'init' FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', 'frakbar');
+ERROR:  could not parse value "frakbar" for parameter "include-xids"
+CONTEXT:  slot "regression_slot", output plugin "test_decoding" during the pg_decode_startup callback
+-- succeed once
+SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+-- fail
+SELECT pg_drop_replication_slot('regression_slot');
+ERROR:  replication slot "regression_slot" does not exist
+-- check that we're detecting a streaming rep slot used for changeset extraction
+SELECT 'init' FROM pg_create_physical_replication_slot('repl');
+ ?column? 
+----------
+ init
+(1 row)
+
+SELECT data FROM pg_decoding_slot_get_changes('repl', 'now', 'include-xids', '0');
+ERROR:  cannot use a replication slot created for streaming replication for changeset extraction
+SELECT pg_drop_replication_slot('repl');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+/* check whether status function reports us, only reproduceable columns */
+SELECT slot_name, plugin, slot_type, active,
+    NOT catalog_xmin IS NULL AS catalog_xmin_set,
+    xmin IS NULl  AS data_xmin_not_set,
+    pg_xlog_location_diff(restart_lsn, '0/01000000') > 0 AS some_wal
+FROM pg_replication_slots;
+    slot_name    |    plugin     | slot_type | active | catalog_xmin_set | data_xmin_not_set | some_wal 
+-----------------+---------------+-----------+--------+------------------+-------------------+----------
+ regression_slot | test_decoding | logical   | f      | f                | t                 | t
+(1 row)
+
+/*
+ * Check that changes are handled correctly when interleaved with ddl
+ */
+CREATE TABLE replication_example(id SERIAL PRIMARY KEY, somedata int, text varchar(120));
+BEGIN;
+INSERT INTO replication_example(somedata, text) VALUES (1, 1);
+INSERT INTO replication_example(somedata, text) VALUES (1, 2);
+COMMIT;
+ALTER TABLE replication_example ADD COLUMN bar int;
+INSERT INTO replication_example(somedata, text, bar) VALUES (2, 1, 4);
+BEGIN;
+INSERT INTO replication_example(somedata, text, bar) VALUES (2, 2, 4);
+INSERT INTO replication_example(somedata, text, bar) VALUES (2, 3, 4);
+INSERT INTO replication_example(somedata, text, bar) VALUES (2, 4, NULL);
+COMMIT;
+ALTER TABLE replication_example DROP COLUMN bar;
+INSERT INTO replication_example(somedata, text) VALUES (3, 1);
+BEGIN;
+INSERT INTO replication_example(somedata, text) VALUES (3, 2);
+INSERT INTO replication_example(somedata, text) VALUES (3, 3);
+COMMIT;
+ALTER TABLE replication_example RENAME COLUMN text TO somenum;
+INSERT INTO replication_example(somedata, somenum) VALUES (4, 1);
+-- collect all changes
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                                               data                                                
+---------------------------------------------------------------------------------------------------
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:1 somedata[int4]:1 text[varchar]:1
+ table "replication_example": INSERT: id[int4]:2 somedata[int4]:1 text[varchar]:2
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:3 somedata[int4]:2 text[varchar]:1 bar[int4]:4
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:4 somedata[int4]:2 text[varchar]:2 bar[int4]:4
+ table "replication_example": INSERT: id[int4]:5 somedata[int4]:2 text[varchar]:3 bar[int4]:4
+ table "replication_example": INSERT: id[int4]:6 somedata[int4]:2 text[varchar]:4 bar[int4]:(null)
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:7 somedata[int4]:3 text[varchar]:1
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:8 somedata[int4]:3 text[varchar]:2
+ table "replication_example": INSERT: id[int4]:9 somedata[int4]:3 text[varchar]:3
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:10 somedata[int4]:4 somenum[varchar]:1
+ COMMIT
+(30 rows)
+
+ALTER TABLE replication_example ALTER COLUMN somenum TYPE int4 USING (somenum::int4);
+-- throw away changes, they contain oids
+SELECT count(data) FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ count 
+-------
+    12
+(1 row)
+
+INSERT INTO replication_example(somedata, somenum) VALUES (5, 1);
+BEGIN;
+INSERT INTO replication_example(somedata, somenum) VALUES (6, 1);
+ALTER TABLE replication_example ADD COLUMN zaphod1 int;
+INSERT INTO replication_example(somedata, somenum, zaphod1) VALUES (6, 2, 1);
+ALTER TABLE replication_example ADD COLUMN zaphod2 int;
+INSERT INTO replication_example(somedata, somenum, zaphod2) VALUES (6, 3, 1);
+INSERT INTO replication_example(somedata, somenum, zaphod1) VALUES (6, 4, 2);
+COMMIT;
+-- show changes
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                                                          data                                                          
+------------------------------------------------------------------------------------------------------------------------
+ BEGIN
+ table "replication_example": INSERT: id[int4]:11 somedata[int4]:5 somenum[int4]:1
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:12 somedata[int4]:6 somenum[int4]:1
+ table "replication_example": INSERT: id[int4]:13 somedata[int4]:6 somenum[int4]:2 zaphod1[int4]:1
+ table "replication_example": INSERT: id[int4]:14 somedata[int4]:6 somenum[int4]:3 zaphod1[int4]:(null) zaphod2[int4]:1
+ table "replication_example": INSERT: id[int4]:15 somedata[int4]:6 somenum[int4]:4 zaphod1[int4]:2 zaphod2[int4]:(null)
+ COMMIT
+(9 rows)
+
+-- hide changes bc of oid visible in full table rewrites
+CREATE TABLE tr_unique(id2 serial unique NOT NULL, data int);
+INSERT INTO tr_unique(data) VALUES(10);
+ALTER TABLE tr_unique RENAME TO tr_pkey;
+ALTER TABLE tr_pkey ADD COLUMN id serial primary key;
+SELECT count(data) FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ count 
+-------
+    10
+(1 row)
+
+INSERT INTO tr_pkey(data) VALUES(1);
+--show deletion with primary key
+DELETE FROM tr_pkey;
+/* display results */
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                             data                             
+--------------------------------------------------------------
+ BEGIN
+ table "tr_pkey": INSERT: id2[int4]:2 data[int4]:1 id[int4]:2
+ COMMIT
+ BEGIN
+ table "tr_pkey": DELETE: id[int4]:1
+ table "tr_pkey": DELETE: id[int4]:2
+ COMMIT
+(7 rows)
+
+/*
+ * check that disk spooling works
+ */
+BEGIN;
+CREATE TABLE tr_etoomuch (id serial primary key, data int);
+INSERT INTO tr_etoomuch(data) SELECT g.i FROM generate_series(1, 10234) g(i);
+DELETE FROM tr_etoomuch WHERE id < 5000;
+UPDATE tr_etoomuch SET data = - data WHERE id > 5000;
+COMMIT;
+/* display results, but hide most of the output */
+SELECT count(*), min(data), max(data)
+FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0')
+GROUP BY substring(data, 1, 24)
+ORDER BY 1;
+ count |                              min                              |                             max                             
+-------+---------------------------------------------------------------+-------------------------------------------------------------
+     1 | COMMIT                                                        | COMMIT
+     1 | BEGIN                                                         | BEGIN
+  4999 | table "tr_etoomuch": DELETE: id[int4]:1                       | table "tr_etoomuch": DELETE: id[int4]:999
+  5234 | table "tr_etoomuch": UPDATE: id[int4]:10000 data[int4]:-10000 | table "tr_etoomuch": UPDATE: id[int4]:9999 data[int4]:-9999
+ 10234 | table "tr_etoomuch": INSERT: id[int4]:10000 data[int4]:10000  | table "tr_etoomuch": INSERT: id[int4]:9 data[int4]:9
+(5 rows)
+
+/*
+ * check whether we decode subtransactions correctly in relation with each
+ * other
+ */
+CREATE TABLE tr_sub (id serial primary key, path text);
+-- toplevel, subtxn, toplevel, subtxn, subtxn
+BEGIN;
+INSERT INTO tr_sub(path) VALUES ('1-top-#1');
+SAVEPOINT a;
+INSERT INTO tr_sub(path) VALUES ('1-top-1-#1');
+INSERT INTO tr_sub(path) VALUES ('1-top-1-#2');
+RELEASE SAVEPOINT a;
+SAVEPOINT b;
+SAVEPOINT c;
+INSERT INTO tr_sub(path) VALUES ('1-top-2-1-#1');
+INSERT INTO tr_sub(path) VALUES ('1-top-2-1-#2');
+RELEASE SAVEPOINT c;
+INSERT INTO tr_sub(path) VALUES ('1-top-2-#1');
+RELEASE SAVEPOINT b;
+COMMIT;
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                            data                            
+------------------------------------------------------------
+ BEGIN
+ COMMIT
+ BEGIN
+ table "tr_sub": INSERT: id[int4]:1 path[text]:1-top-#1
+ table "tr_sub": INSERT: id[int4]:2 path[text]:1-top-1-#1
+ table "tr_sub": INSERT: id[int4]:3 path[text]:1-top-1-#2
+ table "tr_sub": INSERT: id[int4]:4 path[text]:1-top-2-1-#1
+ table "tr_sub": INSERT: id[int4]:5 path[text]:1-top-2-1-#2
+ table "tr_sub": INSERT: id[int4]:6 path[text]:1-top-2-#1
+ COMMIT
+(10 rows)
+
+-- check that we handle xlog assignments correctly
+BEGIN;
+-- nest 80 subtxns
+SAVEPOINT subtop;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+-- assign xid by inserting
+INSERT INTO tr_sub(path) VALUES ('2-top-1...--#1');
+INSERT INTO tr_sub(path) VALUES ('2-top-1...--#2');
+INSERT INTO tr_sub(path) VALUES ('2-top-1...--#3');
+RELEASE SAVEPOINT subtop;
+INSERT INTO tr_sub(path) VALUES ('2-top-#1');
+COMMIT;
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                             data                             
+--------------------------------------------------------------
+ BEGIN
+ table "tr_sub": INSERT: id[int4]:7 path[text]:2-top-1...--#1
+ table "tr_sub": INSERT: id[int4]:8 path[text]:2-top-1...--#2
+ table "tr_sub": INSERT: id[int4]:9 path[text]:2-top-1...--#3
+ table "tr_sub": INSERT: id[int4]:10 path[text]:2-top-#1
+ COMMIT
+(6 rows)
+
+-- make sure rollbacked subtransactions aren't decoded
+BEGIN;
+INSERT INTO tr_sub(path) VALUES ('3-top-2-#1');
+SAVEPOINT a;
+INSERT INTO tr_sub(path) VALUES ('3-top-2-1-#1');
+SAVEPOINT b;
+INSERT INTO tr_sub(path) VALUES ('3-top-2-2-#1');
+ROLLBACK TO SAVEPOINT b;
+INSERT INTO tr_sub(path) VALUES ('3-top-2-#2');
+COMMIT;
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                            data                             
+-------------------------------------------------------------
+ BEGIN
+ table "tr_sub": INSERT: id[int4]:11 path[text]:3-top-2-#1
+ table "tr_sub": INSERT: id[int4]:12 path[text]:3-top-2-1-#1
+ table "tr_sub": INSERT: id[int4]:14 path[text]:3-top-2-#2
+ COMMIT
+(5 rows)
+
+-- test whether a known, but not yet logged toplevel xact, followed by a
+-- subxact commit is handled correctly
+BEGIN;
+SELECT txid_current() != 0; -- so no fixed xid apears in the outfile
+ ?column? 
+----------
+ t
+(1 row)
+
+SAVEPOINT a;
+INSERT INTO tr_sub(path) VALUES ('4-top-1-#1');
+RELEASE SAVEPOINT a;
+COMMIT;
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ data 
+------
+(0 rows)
+
+/*
+ * Check whether treating a table as a catalog table works somewhat
+ */
+CREATE TABLE replication_metadata (
+    id serial primary key,
+    relation name NOT NULL,
+    options text[]
+)
+WITH (user_catalog_table = true)
+;
+\d+ replication_metadata
+                                              Table "public.replication_metadata"
+  Column  |  Type   |                             Modifiers                             | Storage  | Stats target | Description 
+----------+---------+-------------------------------------------------------------------+----------+--------------+-------------
+ id       | integer | not null default nextval('replication_metadata_id_seq'::regclass) | plain    |              | 
+ relation | name    | not null                                                          | plain    |              | 
+ options  | text[]  |                                                                   | extended |              | 
+Indexes:
+    "replication_metadata_pkey" PRIMARY KEY, btree (id)
+Has OIDs: no
+Options: user_catalog_table=true
+
+INSERT INTO replication_metadata(relation, options)
+VALUES ('foo', ARRAY['a', 'b']);
+ALTER TABLE replication_metadata RESET (user_catalog_table);
+\d+ replication_metadata
+                                              Table "public.replication_metadata"
+  Column  |  Type   |                             Modifiers                             | Storage  | Stats target | Description 
+----------+---------+-------------------------------------------------------------------+----------+--------------+-------------
+ id       | integer | not null default nextval('replication_metadata_id_seq'::regclass) | plain    |              | 
+ relation | name    | not null                                                          | plain    |              | 
+ options  | text[]  |                                                                   | extended |              | 
+Indexes:
+    "replication_metadata_pkey" PRIMARY KEY, btree (id)
+Has OIDs: no
+
+INSERT INTO replication_metadata(relation, options)
+VALUES ('bar', ARRAY['a', 'b']);
+ALTER TABLE replication_metadata SET (user_catalog_table = true);
+\d+ replication_metadata
+                                              Table "public.replication_metadata"
+  Column  |  Type   |                             Modifiers                             | Storage  | Stats target | Description 
+----------+---------+-------------------------------------------------------------------+----------+--------------+-------------
+ id       | integer | not null default nextval('replication_metadata_id_seq'::regclass) | plain    |              | 
+ relation | name    | not null                                                          | plain    |              | 
+ options  | text[]  |                                                                   | extended |              | 
+Indexes:
+    "replication_metadata_pkey" PRIMARY KEY, btree (id)
+Has OIDs: no
+Options: user_catalog_table=true
+
+INSERT INTO replication_metadata(relation, options)
+VALUES ('blub', NULL);
+-- make sure rewrites don't work
+ALTER TABLE replication_metadata ADD COLUMN rewritemeornot int;
+ALTER TABLE replication_metadata ALTER COLUMN rewritemeornot TYPE text;
+ERROR:  cannot rewrite table "replication_metadata" used as a catalog table
+ALTER TABLE replication_metadata SET (user_catalog_table = false);
+\d+ replication_metadata
+                                                 Table "public.replication_metadata"
+     Column     |  Type   |                             Modifiers                             | Storage  | Stats target | Description 
+----------------+---------+-------------------------------------------------------------------+----------+--------------+-------------
+ id             | integer | not null default nextval('replication_metadata_id_seq'::regclass) | plain    |              | 
+ relation       | name    | not null                                                          | plain    |              | 
+ options        | text[]  |                                                                   | extended |              | 
+ rewritemeornot | integer |                                                                   | plain    |              | 
+Indexes:
+    "replication_metadata_pkey" PRIMARY KEY, btree (id)
+Has OIDs: no
+Options: user_catalog_table=false
+
+INSERT INTO replication_metadata(relation, options)
+VALUES ('zaphod', NULL);
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                                                           data                                                           
+--------------------------------------------------------------------------------------------------------------------------
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_metadata": INSERT: id[int4]:1 relation[name]:foo options[_text]:{a,b}
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_metadata": INSERT: id[int4]:2 relation[name]:bar options[_text]:{a,b}
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_metadata": INSERT: id[int4]:3 relation[name]:blub options[_text]:(null)
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_metadata": INSERT: id[int4]:4 relation[name]:zaphod options[_text]:(null) rewritemeornot[int4]:(null)
+ COMMIT
+(22 rows)
+
+/*
+ * check whether we handle updates/deletes correct with & without a pkey
+ */
+/* we should handle the case without a key at all more gracefully */
+CREATE TABLE table_without_key(id serial, data int);
+INSERT INTO table_without_key(data) VALUES(1),(2);
+DELETE FROM table_without_key WHERE data = 1;
+-- won't log old keys
+UPDATE table_without_key SET data = 3 WHERE data = 2;
+UPDATE table_without_key SET id = -id;
+UPDATE table_without_key SET id = -id;
+-- should log the full old row now
+ALTER TABLE table_without_key REPLICA IDENTITY FULL;
+UPDATE table_without_key SET data = 3 WHERE data = 2;
+UPDATE table_without_key SET id = -id;
+UPDATE table_without_key SET id = -id;
+DELETE FROM table_without_key WHERE data = 3;
+CREATE TABLE table_with_pkey(id serial primary key, data int);
+INSERT INTO table_with_pkey(data) VALUES(1), (2);
+DELETE FROM table_with_pkey WHERE data = 1;
+-- should log the old pkey
+UPDATE table_with_pkey SET data = 3 WHERE data = 2;
+UPDATE table_with_pkey SET id = -id;
+UPDATE table_with_pkey SET id = -id;
+-- check that we log nothing despite having a pkey
+ALTER TABLE table_without_key REPLICA IDENTITY NOTHING;
+UPDATE table_with_pkey SET id = -id;
+-- check that we log everything despite having a pkey
+ALTER TABLE table_without_key REPLICA IDENTITY FULL;
+UPDATE table_with_pkey SET id = -id;
+DELETE FROM table_with_pkey WHERE data = 3;
+CREATE TABLE table_with_unique_not_null(id serial unique, data int);
+ALTER TABLE table_with_unique_not_null ALTER COLUMN id SET NOT NULL; --already set
+-- won't log anything, replica identity not setup
+INSERT INTO table_with_unique_not_null(data) VALUES(1), (2);
+DELETE FROM table_with_unique_not_null WHERE data = 1;
+UPDATE table_with_unique_not_null SET data = 3 WHERE data = 2;
+UPDATE table_with_unique_not_null SET id = -id;
+UPDATE table_with_unique_not_null SET id = -id;
+DELETE FROM table_with_unique_not_null WHERE data = 3;
+-- should log old key
+ALTER TABLE table_with_unique_not_null REPLICA IDENTITY USING INDEX table_with_unique_not_null_id_key;
+INSERT INTO table_with_unique_not_null(data) VALUES(1), (2);
+DELETE FROM table_with_unique_not_null WHERE data = 1;
+UPDATE table_with_unique_not_null SET data = 3 WHERE data = 2;
+UPDATE table_with_unique_not_null SET id = -id;
+UPDATE table_with_unique_not_null SET id = -id;
+DELETE FROM table_with_unique_not_null WHERE data = 3;
+-- check toast support
+SELECT setseed(0);
+ setseed 
+---------
+ 
+(1 row)
+
+CREATE TABLE toasttable(
+       id serial primary key,
+       toasted_col1 text,
+       rand1 float8 DEFAULT random(),
+       toasted_col2 text,
+       rand2 float8 DEFAULT random()
+       );
+-- uncompressed external toast data
+INSERT INTO toasttable(toasted_col1) SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i);
+-- compressed external toast data
+INSERT INTO toasttable(toasted_col2) SELECT repeat(string_agg(to_char(g.i, 'FM0000'), ''), 50) FROM generate_series(1, 500) g(i);
+-- update of existing column
+UPDATE toasttable
+    SET toasted_col1 = (SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i))
+WHERE id = 1;
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         data                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ BEGIN
+ COMMIT
+ BEGIN
+ table "table_without_key": INSERT: id[int4]:1 data[int4]:1
+ table "table_without_key": INSERT: id[int4]:2 data[int4]:2
+ COMMIT
+ BEGIN
+ table "table_without_key": DELETE: (no-tuple-data)
+ COMMIT
+ BEGIN
+ table "table_without_key": UPDATE: id[int4]:2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_without_key": UPDATE: id[int4]:-2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_without_key": UPDATE: id[int4]:2 data[int4]:3
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "table_without_key": UPDATE: old-key: id[int4]:2 data[int4]:3 new-tuple: id[int4]:-2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_without_key": UPDATE: old-key: id[int4]:-2 data[int4]:3 new-tuple: id[int4]:2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_without_key": DELETE: id[int4]:2 data[int4]:3
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "table_with_pkey": INSERT: id[int4]:1 data[int4]:1
+ table "table_with_pkey": INSERT: id[int4]:2 data[int4]:2
+ COMMIT
+ BEGIN
+ table "table_with_pkey": DELETE: id[int4]:1
+ COMMIT
+ BEGIN
+ table "table_with_pkey": UPDATE: id[int4]:2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_pkey": UPDATE: old-key: id[int4]:2 new-tuple: id[int4]:-2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_pkey": UPDATE: old-key: id[int4]:-2 new-tuple: id[int4]:2 data[int4]:3
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "table_with_pkey": UPDATE: old-key: id[int4]:2 new-tuple: id[int4]:-2 data[int4]:3
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "table_with_pkey": UPDATE: old-key: id[int4]:-2 new-tuple: id[int4]:2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_pkey": DELETE: id[int4]:2
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": INSERT: id[int4]:1 data[int4]:1
+ table "table_with_unique_not_null": INSERT: id[int4]:2 data[int4]:2
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": DELETE: (no-tuple-data)
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": UPDATE: id[int4]:2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": UPDATE: id[int4]:-2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": UPDATE: id[int4]:2 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": DELETE: (no-tuple-data)
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": INSERT: id[int4]:3 data[int4]:1
+ table "table_with_unique_not_null": INSERT: id[int4]:4 data[int4]:2
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": DELETE: id[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": UPDATE: id[int4]:4 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": UPDATE: old-key: id[int4]:4 new-tuple: id[int4]:-4 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": UPDATE: old-key: id[int4]:-4 new-tuple: id[int4]:4 data[int4]:3
+ COMMIT
+ BEGIN
+ table "table_with_unique_not_null": DELETE: id[int4]:4
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "toasttable": INSERT: id[int4]:1 toasted_col1[text]:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000 rand1[float8]:0.840187716763467 toasted_col2[text]:(null) rand2[float8]:0.394382926635444
+ COMMIT
+ BEGIN
+ table "toasttable": INSERT: id[int4]:2 toasted_col1[text]:(null) rand1[float8]:0.783099223393947 toasted_col2[text]:0001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200230024002500260027002800290030003100320033003400350036003700380039004000410042004300440045004600470048004900500051005200530054005500560057005800590060006100620063006400650066006700680069007000710072007300740075007600770078007900800081008200830084008500860087008800890090009100920093009400950096009700980099010001010102010301040105010601070108010901100111011201130114011501160117011801190120012101220123012401250126012701280129013001310132013301340135013601370138013901400141014201430144014501460147014801490150015101520153015401550156015701580159016001610162016301640165016601670168016901700171017201730174017501760177017801790180018101820183018401850186018701880189019001910192019301940195019601970198019902000201020202030204020502060207020802090210021102120213021402150216021702180219022002210222022302240225022602270228022902300231023202330234023502360237023802390240024102420243024402450246024702480249025002510252025302540255025602570258025902600261026202630264026502660267026802690270027102720273027402750276027702780279028002810282028302840285028602870288028902900291029202930294029502960297029802990300030103020303030403050306030703080309031003110312031303140315031603170318031903200321032203230324032503260327032803290330033103320333033403350336033703380339034003410342034303440345034603470348034903500351035203530354035503560357035803590360036103620363036403650366036703680369037003710372037303740375037603770378037903800381038203830384038503860387038803890390039103920393039403950396039703980399040004010402040304040405040604070408040904100411041204130414041504160417041804190420042104220423042404250426042704280429043004310432043304340435043604370438043904400441044204430444044504460447044804490450045104520453045404550456045704580459046004610462046304640465046604670468046904700471047204730474047504760477047804790480048104820483048404850486048704880489049004910492049304940495049604970498049905000001000200030004000500060007000800090010001100120013001400150016001700180019002000210022002300240025002600270028002900300031003200330034003500360037003800390040004100420043004400450046004700480049005000510052005300540055005600570058005900600061006200630064006500660067006800690070007100720073007400750076007700780079008000810082008300840085008600870088008900900091009200930094009500960097009800990100010101020103010401050106010701080109011001110112011301140115011601170118011901200121012201230124012501260127012801290130013101320133013401350136013701380139014001410142014301440145014601470148014901500151015201530154015501560157015801590160016101620163016401650166016701680169017001710172017301740175017601770178017901800181018201830184018501860187018801890190019101920193019401950196019701980199020002010202020302040205020602070208020902100211021202130214021502160217021802190220022102220223022402250226022702280229023002310232023302340235023602370238023902400241024202430244024502460247024802490250025102520253025402550256025702580259026002610262026302640265026602670268026902700271027202730274027502760277027802790280028102820283028402850286028702880289029002910292029302940295029602970298029903000301030203030304030503060307030803090310031103120313031403150316031703180319032003210322032303240325032603270328032903300331033203330334033503360337033803390340034103420343034403450346034703480349035003510352035303540355035603570358035903600361036203630364036503660367036803690370037103720373037403750376037703780379038003810382038303840385038603870388038903900391039203930394039503960397039803990400040104020403040404050406040704080409041004110412041304140415041604170418041904200421042204230424042504260427042804290430043104320433043404350436043704380439044004410442044304440445044604470448044904500451045204530454045504560457045804590460046104620463046404650466046704680469047004710472047304740475047604770478047904800481048204830484048504860487048804890490049104920493049404950496049704980499050000010002000300040005000600070008000900100011001200130014001500160017001800190020002100220023002400250026002700280029003000310032003300340035003600370038003900400041004200430044004500460047004800490050005100520053005400550056005700580059006000610062006300640065006600670068006900700071007200730074007500760077007800790080008100820083008400850086008700880089009000910092009300940095009600970098009901000101010201030104010501060107010801090110011101120113011401150116011701180119012001210122012301240125012601270128012901300131013201330134013501360137013801390140014101420143014401450146014701480149015001510152015301540155015601570158015901600161016201630164016501660167016801690170017101720173017401750176017701780179018001810182018301840185018601870188018901900191019201930194019501960197019801990200020102020203020402050206020702080209021002110212021302140215021602170218021902200221022202230224022502260227022802290230023102320233023402350236023702380239024002410242024302440245024602470248024902500251025202530254025502560257025802590260026102620263026402650266026702680269027002710272027302740275027602770278027902800281028202830284028502860287028802890290029102920293029402950296029702980299030003010302030303040305030603070308030903100311031203130314031503160317031803190320032103220323032403250326032703280329033003310332033303340335033603370338033903400341034203430344034503460347034803490350035103520353035403550356035703580359036003610362036303640365036603670368036903700371037203730374037503760377037803790380038103820383038403850386038703880389039003910392039303940395039603970398039904000401040204030404040504060407040804090410041104120413041404150416041704180419042004210422042304240425042604270428042904300431043204330434043504360437043804390440044104420443044404450446044704480449045004510452045304540455045604570458045904600461046204630464046504660467046804690470047104720473047404750476047704780479048004810482048304840485048604870488048904900491049204930494049504960497049804990500 rand2[float8]:0.798440033104271
+ COMMIT
+ BEGIN
+ table "toasttable": UPDATE: id[int4]:1 toasted_col1[text]:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000 rand1[float8]:0.840187716763467 toasted_col2[text]:(null) rand2[float8]:0.394382926635444
+ COMMIT
+(113 rows)
+
+INSERT INTO toasttable(toasted_col1) SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i);
+-- update of second column, first column unchanged
+UPDATE toasttable
+    SET toasted_col2 = (SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i))
+WHERE id = 1;
+-- make sure we decode correctly even if the toast table is gone
+DROP TABLE toasttable;
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        data                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ BEGIN
+ table "toasttable": INSERT: id[int4]:3 toasted_col1[text]:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000 rand1[float8]:0.911647357512265 toasted_col2[text]:(null) rand2[float8]:0.197551369201392
+ COMMIT
+ BEGIN
+ table "toasttable": UPDATE: id[int4]:1 toasted_col1[text]:(unchanged-toast-datum) rand1[float8]:0.840187716763467 toasted_col2[text]:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000 rand2[float8]:0.394382926635444
+ COMMIT
+ BEGIN
+ COMMIT
+(8 rows)
+
+-- done, free logical replication slot
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ data 
+------
+(0 rows)
+
+SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+/* check that we aren't visible anymore now */
+SELECT * FROM pg_stat_logical_decoding;
+ERROR:  relation "pg_stat_logical_decoding" does not exist
+LINE 2: SELECT * FROM pg_stat_logical_decoding;
+                      ^
+DROP EXTENSION test_decoding;
diff --git a/contrib/test_decoding/expected/delayed_startup.out b/contrib/test_decoding/expected/delayed_startup.out
new file mode 100644
index 0000000..84957020
--- /dev/null
+++ b/contrib/test_decoding/expected/delayed_startup.out
@@ -0,0 +1,38 @@
+Parsed test spec with 2 sessions
+
+starting permutation: s1b s1w s2init s1c s2start s1b s1w s1c s2start s1b s1w s2start s1c s2start
+step s1b: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s1w: INSERT INTO do_write DEFAULT VALUES;
+step s2init: SELECT 'init' FROM pg_create_decoding_replication_slot('isolation_slot', 'test_decoding'); <waiting ...>
+step s1c: COMMIT;
+step s2init: <... completed>
+?column?       
+
+init           
+step s2start: SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');
+data           
+
+step s1b: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s1w: INSERT INTO do_write DEFAULT VALUES;
+step s1c: COMMIT;
+step s2start: SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');
+data           
+
+BEGIN          
+table "do_write": INSERT: id[int4]:2
+COMMIT         
+step s1b: BEGIN ISOLATION LEVEL SERIALIZABLE;
+step s1w: INSERT INTO do_write DEFAULT VALUES;
+step s2start: SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');
+data           
+
+step s1c: COMMIT;
+step s2start: SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');
+data           
+
+BEGIN          
+table "do_write": INSERT: id[int4]:3
+COMMIT         
+?column?       
+
+stop           
diff --git a/contrib/test_decoding/expected/mxact.out b/contrib/test_decoding/expected/mxact.out
new file mode 100644
index 0000000..9982a28
--- /dev/null
+++ b/contrib/test_decoding/expected/mxact.out
@@ -0,0 +1,66 @@
+Parsed test spec with 3 sessions
+
+starting permutation: s0init s0start s1begin s1sharepgclass s2begin s2sharepgclass s0w s0start s2commit s1commit
+step s0init: SELECT 'init' FROM pg_create_decoding_replication_slot('isolation_slot', 'test_decoding');
+?column?       
+
+init           
+step s0start: SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');
+data           
+
+step s1begin: BEGIN;
+step s1sharepgclass: SELECT count(*) > 1 FROM (SELECT * FROM pg_class FOR SHARE) s;
+?column?       
+
+t              
+step s2begin: BEGIN;
+step s2sharepgclass: SELECT count(*) > 1 FROM (SELECT * FROM pg_class FOR SHARE) s;
+?column?       
+
+t              
+step s0w: INSERT INTO do_write DEFAULT VALUES;
+step s0start: SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');
+data           
+
+BEGIN          
+table "do_write": INSERT: id[int4]:1
+COMMIT         
+step s2commit: COMMIT;
+step s1commit: COMMIT;
+?column?       
+
+stop           
+
+starting permutation: s0init s0start s1begin s1keysharepgclass s2begin s2keysharepgclass s0alter s0w s0start s2commit s1commit
+step s0init: SELECT 'init' FROM pg_create_decoding_replication_slot('isolation_slot', 'test_decoding');
+?column?       
+
+init           
+step s0start: SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');
+data           
+
+step s1begin: BEGIN;
+step s1keysharepgclass: SELECT count(*) > 1 FROM (SELECT * FROM pg_class FOR KEY SHARE) s;
+?column?       
+
+t              
+step s2begin: BEGIN;
+step s2keysharepgclass: SELECT count(*) > 1 FROM (SELECT * FROM pg_class FOR KEY SHARE) s;
+?column?       
+
+t              
+step s0alter: ALTER TABLE do_write ADD column ts timestamptz;
+step s0w: INSERT INTO do_write DEFAULT VALUES;
+step s0start: SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');
+data           
+
+BEGIN          
+COMMIT         
+BEGIN          
+table "do_write": INSERT: id[int4]:1 ts[timestamptz]:(null)
+COMMIT         
+step s2commit: COMMIT;
+step s1commit: COMMIT;
+?column?       
+
+stop           
diff --git a/contrib/test_decoding/expected/permissions.out b/contrib/test_decoding/expected/permissions.out
new file mode 100644
index 0000000..0a7c1e3
--- /dev/null
+++ b/contrib/test_decoding/expected/permissions.out
@@ -0,0 +1,131 @@
+CREATE EXTENSION test_decoding;
+-- predictability
+SET synchronous_commit = on;
+-- setup
+CREATE ROLE lr_normal;
+CREATE ROLE lr_superuser SUPERUSER;
+CREATE ROLE lr_replication REPLICATION;
+CREATE TABLE lr_test(data text);
+-- superuser can control replication
+SET ROLE lr_superuser;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+INSERT INTO lr_test VALUES('lr_superuser_init');
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                         data                          
+-------------------------------------------------------
+ BEGIN
+ table "lr_test": INSERT: data[text]:lr_superuser_init
+ COMMIT
+(3 rows)
+
+SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+RESET ROLE;
+-- replication user can control replication
+SET ROLE lr_replication;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+INSERT INTO lr_test VALUES('lr_superuser_init');
+ERROR:  permission denied for relation lr_test
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ data 
+------
+(0 rows)
+
+SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+RESET ROLE;
+-- plain user *can't* can control replication
+SET ROLE lr_normal;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ERROR:  must be superuser or replication role to use changeset extraction
+INSERT INTO lr_test VALUES('lr_superuser_init');
+ERROR:  permission denied for relation lr_test
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ERROR:  must be superuser or replication role to use changeset extraction
+SELECT pg_drop_replication_slot('regression_slot');
+ERROR:  must be superuser or replication role to use replication slots
+RESET ROLE;
+-- replication users can drop superuser created slots
+SET ROLE lr_superuser;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+RESET ROLE;
+SET ROLE lr_replication;
+SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+RESET ROLE;
+-- normal users can't drop existing slots
+SET ROLE lr_superuser;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+RESET ROLE;
+SET ROLE lr_normal;
+SELECT pg_drop_replication_slot('regression_slot');
+ERROR:  must be superuser or replication role to use replication slots
+RESET ROLE;
+-- all users can see existing slots
+SET ROLE lr_superuser;
+SELECT slot_name, plugin FROM pg_replication_slots;
+    slot_name    |    plugin     
+-----------------+---------------
+ regression_slot | test_decoding
+(1 row)
+
+RESET ROLE;
+SET ROLE lr_replication;
+SELECT slot_name, plugin FROM pg_replication_slots;
+    slot_name    |    plugin     
+-----------------+---------------
+ regression_slot | test_decoding
+(1 row)
+
+RESET ROLE;
+SET ROLE lr_normal;
+SELECT slot_name, plugin FROM pg_replication_slots;
+    slot_name    |    plugin     
+-----------------+---------------
+ regression_slot | test_decoding
+(1 row)
+
+RESET ROLE;
+-- cleanup
+SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+DROP ROLE lr_normal;
+DROP ROLE lr_superuser;
+DROP ROLE lr_replication;
+DROP TABLE lr_test;
diff --git a/contrib/test_decoding/expected/rewrite.out b/contrib/test_decoding/expected/rewrite.out
new file mode 100644
index 0000000..39608dc
--- /dev/null
+++ b/contrib/test_decoding/expected/rewrite.out
@@ -0,0 +1,109 @@
+CREATE EXTENSION test_decoding;
+-- predictability
+SET synchronous_commit = on;
+DROP TABLE IF EXISTS replication_example;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+CREATE TABLE replication_example(id SERIAL PRIMARY KEY, somedata int, text varchar(120));
+INSERT INTO replication_example(somedata) VALUES (1);
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                                         data                                          
+---------------------------------------------------------------------------------------
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:1 somedata[int4]:1 text[varchar]:(null)
+ COMMIT
+(5 rows)
+
+BEGIN;
+INSERT INTO replication_example(somedata) VALUES (2);
+ALTER TABLE replication_example ADD COLUMN testcolumn1 int;
+INSERT INTO replication_example(somedata, testcolumn1) VALUES (3,  1);
+COMMIT;
+BEGIN;
+INSERT INTO replication_example(somedata) VALUES (3);
+ALTER TABLE replication_example ADD COLUMN testcolumn2 int;
+INSERT INTO replication_example(somedata, testcolumn1, testcolumn2) VALUES (4,  2, 1);
+COMMIT;
+VACUUM FULL pg_am;
+VACUUM FULL pg_amop;
+VACUUM FULL pg_proc;
+VACUUM FULL pg_opclass;
+VACUUM FULL pg_type;
+VACUUM FULL pg_index;
+VACUUM FULL pg_database;
+-- repeated rewrites that fail
+BEGIN;
+CLUSTER pg_class USING pg_class_oid_index;
+CLUSTER pg_class USING pg_class_oid_index;
+ROLLBACK;
+-- repeated rewrites that succeed
+BEGIN;
+CLUSTER pg_class USING pg_class_oid_index;
+CLUSTER pg_class USING pg_class_oid_index;
+CLUSTER pg_class USING pg_class_oid_index;
+COMMIT;
+ -- repeated rewrites in different transactions
+VACUUM FULL pg_class;
+VACUUM FULL pg_class;
+INSERT INTO replication_example(somedata, testcolumn1) VALUES (5, 3);
+BEGIN;
+INSERT INTO replication_example(somedata, testcolumn1) VALUES (6, 4);
+ALTER TABLE replication_example ADD COLUMN testcolumn3 int;
+INSERT INTO replication_example(somedata, testcolumn1, testcolumn3) VALUES (7, 5, 1);
+COMMIT;
+-- make old files go away
+CHECKPOINT;
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                                                                          data                                                                          
+--------------------------------------------------------------------------------------------------------------------------------------------------------
+ BEGIN
+ table "replication_example": INSERT: id[int4]:2 somedata[int4]:2 text[varchar]:(null)
+ table "replication_example": INSERT: id[int4]:3 somedata[int4]:3 text[varchar]:(null) testcolumn1[int4]:1
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:4 somedata[int4]:3 text[varchar]:(null) testcolumn1[int4]:(null)
+ table "replication_example": INSERT: id[int4]:5 somedata[int4]:4 text[varchar]:(null) testcolumn1[int4]:2 testcolumn2[int4]:1
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:6 somedata[int4]:5 text[varchar]:(null) testcolumn1[int4]:3 testcolumn2[int4]:(null)
+ COMMIT
+ BEGIN
+ table "replication_example": INSERT: id[int4]:7 somedata[int4]:6 text[varchar]:(null) testcolumn1[int4]:4 testcolumn2[int4]:(null)
+ table "replication_example": INSERT: id[int4]:8 somedata[int4]:7 text[varchar]:(null) testcolumn1[int4]:5 testcolumn2[int4]:(null) testcolumn3[int4]:1
+ COMMIT
+(35 rows)
+
+SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+DROP TABLE IF EXISTS replication_example;
+DROP EXTENSION test_decoding;
diff --git a/contrib/test_decoding/expected/slot.out b/contrib/test_decoding/expected/slot.out
new file mode 100644
index 0000000..2c7c12b
--- /dev/null
+++ b/contrib/test_decoding/expected/slot.out
@@ -0,0 +1,178 @@
+CREATE FUNCTION pg_catalog.pg_td_mkdir(text)
+RETURNS void
+AS '$libdir/test_decoding_regsupport', 'pg_td_mkdir'
+LANGUAGE C VOLATILE STRICT;
+CREATE FUNCTION pg_catalog.pg_td_rmdir(text)
+RETURNS void
+AS '$libdir/test_decoding_regsupport', 'pg_td_rmdir'
+LANGUAGE C VOLATILE STRICT;
+CREATE FUNCTION pg_catalog.pg_td_unlink(text)
+RETURNS void
+AS '$libdir/test_decoding_regsupport', 'pg_td_unlink'
+LANGUAGE C VOLATILE STRICT;
+CREATE FUNCTION pg_catalog.pg_td_chmod(text, text)
+RETURNS void
+AS '$libdir/test_decoding_regsupport', 'pg_td_chmod'
+LANGUAGE C VOLATILE STRICT;
+-- drop all slots
+SELECT pg_drop_replication_slot(slot_name)
+FROM pg_replication_slots
+WHERE slot_name LIKE 'slottest_%';
+ pg_drop_replication_slot 
+--------------------------
+(0 rows)
+
+-- succeed
+SELECT * FROM pg_create_physical_replication_slot('slottest_1');
+  slotname  | xlog_position 
+------------+---------------
+ slottest_1 | 
+(1 row)
+
+SELECT * FROM pg_create_physical_replication_slot('slottest_2');
+  slotname  | xlog_position 
+------------+---------------
+ slottest_2 | 
+(1 row)
+
+-- fail, duplicate
+SELECT * FROM pg_create_physical_replication_slot('slottest_1');
+ERROR:  replication slot "slottest_1" already exists
+-- succeed
+SELECT pg_drop_replication_slot('slottest_1');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+SELECT pg_td_chmod('pg_replslot', '0');
+ pg_td_chmod 
+-------------
+ 
+(1 row)
+
+-- fail, no permissions on entire pg_replslot director
+SELECT * FROM pg_create_physical_replication_slot('slottest_3');
+ERROR:  could not create directory "pg_replslot/slottest_3.tmp": Permission denied
+SELECT * FROM pg_drop_replication_slot('slottest_2');
+ERROR:  could not rename "pg_replslot/slottest_2" to "pg_replslot/slottest_2.tmp": Permission denied
+SELECT pg_td_chmod('pg_replslot', '700');
+ pg_td_chmod 
+-------------
+ 
+(1 row)
+
+-- succeed, we have permissions again
+SELECT * FROM pg_drop_replication_slot('slottest_2');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+SELECT * FROM pg_create_physical_replication_slot('slottest_4');
+  slotname  | xlog_position 
+------------+---------------
+ slottest_4 | 
+(1 row)
+
+SELECT pg_td_chmod('pg_replslot/slottest_4', '000');
+ pg_td_chmod 
+-------------
+ 
+(1 row)
+
+-- succeed as the rename works, with WARNINGs
+SELECT * FROM pg_drop_replication_slot('slottest_4');
+WARNING:  could not open directory "pg_replslot/slottest_4.tmp": Permission denied
+WARNING:  could not remove directory "pg_replslot/slottest_4.tmp"
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+-- fail, temp director exists
+SELECT * FROM pg_create_physical_replication_slot('slottest_4');
+WARNING:  could not open directory "pg_replslot/slottest_4.tmp": Permission denied
+ERROR:  could not create directory "pg_replslot/slottest_4.tmp": File exists
+-- cleanup half-deleted slot
+SELECT pg_td_chmod('pg_replslot/slottest_4.tmp', '700');
+ pg_td_chmod 
+-------------
+ 
+(1 row)
+
+SELECT pg_td_unlink('pg_replslot/slottest_4.tmp/state');
+ pg_td_unlink 
+--------------
+ 
+(1 row)
+
+SELECT pg_td_rmdir('pg_replslot/slottest_4.tmp');
+ pg_td_rmdir 
+-------------
+ 
+(1 row)
+
+-- check cleanup
+SELECT * FROM pg_create_physical_replication_slot('slottest_4');
+  slotname  | xlog_position 
+------------+---------------
+ slottest_4 | 
+(1 row)
+
+SELECT * FROM pg_drop_replication_slot('slottest_4');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+-- fail, slot directory exists
+SELECT pg_td_mkdir('pg_replslot/slottest_5');
+ pg_td_mkdir 
+-------------
+ 
+(1 row)
+
+SELECT * FROM pg_drop_replication_slot('slottest_5');
+ERROR:  replication slot "slottest_5" does not exist
+SELECT pg_td_rmdir('pg_replslot/slottest_5');
+ pg_td_rmdir 
+-------------
+ 
+(1 row)
+
+SELECT pg_td_mkdir('pg_replslot/slottest_6.tmp');
+ pg_td_mkdir 
+-------------
+ 
+(1 row)
+
+SELECT pg_td_mkdir('pg_replslot/slottest_6.tmp/blub');
+ pg_td_mkdir 
+-------------
+ 
+(1 row)
+
+-- suceed, temp directory exists, but we remove it
+SELECT * FROM pg_create_physical_replication_slot('slottest_6');
+  slotname  | xlog_position 
+------------+---------------
+ slottest_6 | 
+(1 row)
+
+-- succeed, temp directory removed
+SELECT * FROM pg_create_physical_replication_slot('slottest_6');
+ERROR:  replication slot "slottest_6" already exists
+SELECT * FROM pg_drop_replication_slot('slottest_6');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+SELECT pg_drop_replication_slot(slot_name)
+FROM pg_replication_slots
+WHERE slot_name LIKE 'slottest_%';
+ pg_drop_replication_slot 
+--------------------------
+(0 rows)
+
diff --git a/contrib/test_decoding/expected/toast.out b/contrib/test_decoding/expected/toast.out
new file mode 100644
index 0000000..66cba19
--- /dev/null
+++ b/contrib/test_decoding/expected/toast.out
@@ -0,0 +1,95 @@
+CREATE EXTENSION test_decoding;
+-- predictability
+SET synchronous_commit = on;
+DROP TABLE IF EXISTS xpto;
+NOTICE:  table "xpto" does not exist, skipping
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+SELECT setseed(0);
+ setseed 
+---------
+ 
+(1 row)
+
+CREATE TABLE xpto (
+    id serial primary key,
+    toasted_col1 text,
+    rand1 float8 DEFAULT random(),
+    toasted_col2 text,
+    rand2 float8 DEFAULT random()
+);
+-- uncompressed external toast data
+INSERT INTO xpto (toasted_col1, toasted_col2) SELECT string_agg(g.i::text, ''), string_agg((g.i*2)::text, '') FROM generate_series(1, 2000) g(i);
+-- compressed external toast data
+INSERT INTO xpto (toasted_col2) SELECT repeat(string_agg(to_char(g.i, 'FM0000'), ''), 50) FROM generate_series(1, 500) g(i);
+-- update of existing column
+UPDATE xpto SET toasted_col1 = (SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i)) WHERE id = 1;
+UPDATE xpto SET rand1 = 123.456 WHERE id = 1;
+DELETE FROM xpto WHERE id = 1;
+DROP TABLE IF EXISTS toasted_key;
+NOTICE:  table "toasted_key" does not exist, skipping
+CREATE TABLE toasted_key (
+    id serial,
+    toasted_key text PRIMARY KEY,
+    toasted_col1 text,
+    toasted_col2 text
+);
+ALTER TABLE toasted_key ALTER COLUMN toasted_key SET STORAGE EXTERNAL;
+ALTER TABLE toasted_key ALTER COLUMN toasted_col1 SET STORAGE EXTERNAL;
+INSERT INTO toasted_key(toasted_key, toasted_col1) VALUES(repeat('1234567890', 200), repeat('9876543210', 200));
+-- test update of a toasted key without changing it
+UPDATE toasted_key SET toasted_col2 = toasted_col1;
+-- test update of a toasted key, changing it
+UPDATE toasted_key SET toasted_key = toasted_key || '1';
+DELETE FROM toasted_key;
+SELECT substr(data, 1, 200) FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+                                                                                                  substr                                                                                                  
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ BEGIN
+ COMMIT
+ BEGIN
+ table "xpto": INSERT: id[int4]:1 toasted_col1[text]:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787
+ COMMIT
+ BEGIN
+ table "xpto": INSERT: id[int4]:2 toasted_col1[text]:(null) rand1[float8]:0.783099223393947 toasted_col2[text]:000100020003000400050006000700080009001000110012001300140015001600170018001900200021002200
+ COMMIT
+ BEGIN
+ table "xpto": UPDATE: id[int4]:1 toasted_col1[text]:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787
+ COMMIT
+ BEGIN
+ table "xpto": UPDATE: id[int4]:1 toasted_col1[text]:(unchanged-toast-datum) rand1[float8]:123.456 toasted_col2[text]:(unchanged-toast-datum) rand2[float8]:0.394382926635444
+ COMMIT
+ BEGIN
+ table "xpto": DELETE: id[int4]:1
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ COMMIT
+ BEGIN
+ table "toasted_key": INSERT: id[int4]:1 toasted_key[text]:1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
+ COMMIT
+ BEGIN
+ table "toasted_key": UPDATE: id[int4]:1 toasted_key[text]:(unchanged-toast-datum) toasted_col1[text]:(unchanged-toast-datum) toasted_col2[text]:98765432109876543210987654321098765432109876543210987654
+ COMMIT
+ BEGIN
+ table "toasted_key": UPDATE: old-key: toasted_key[text]:123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234
+ COMMIT
+ BEGIN
+ table "toasted_key": DELETE: toasted_key[text]:123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123
+ COMMIT
+(35 rows)
+
+SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
+DROP EXTENSION test_decoding;
diff --git a/contrib/test_decoding/logical.conf b/contrib/test_decoding/logical.conf
new file mode 100644
index 0000000..367f706
--- /dev/null
+++ b/contrib/test_decoding/logical.conf
@@ -0,0 +1,2 @@
+wal_level = logical
+max_replication_slots = 4
diff --git a/contrib/test_decoding/specs/delayed_startup.spec b/contrib/test_decoding/specs/delayed_startup.spec
new file mode 100644
index 0000000..cf16ef6
--- /dev/null
+++ b/contrib/test_decoding/specs/delayed_startup.spec
@@ -0,0 +1,27 @@
+setup
+{
+    DROP TABLE IF EXISTS do_write;
+    DROP EXTENSION IF EXISTS test_decoding;
+    CREATE EXTENSION test_decoding;
+    CREATE TABLE do_write(id serial primary key);
+}
+
+teardown
+{
+    DROP TABLE do_write;
+    DROP EXTENSION test_decoding;
+    SELECT 'stop' FROM pg_drop_replication_slot('isolation_slot');
+}
+
+session "s1"
+setup { SET synchronous_commit=on; }
+step "s1b" { BEGIN ISOLATION LEVEL SERIALIZABLE; }
+step "s1w" { INSERT INTO do_write DEFAULT VALUES; }
+step "s1c" { COMMIT; }
+session "s2"
+setup { SET synchronous_commit=on; }
+step "s2init" {SELECT 'init' FROM pg_create_decoding_replication_slot('isolation_slot', 'test_decoding');}
+step "s2start" {SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');}
+
+
+permutation "s1b" "s1w" "s2init" "s1c" "s2start" "s1b" "s1w" "s1c" "s2start" "s1b" "s1w" "s2start" "s1c" "s2start"
diff --git a/contrib/test_decoding/specs/mxact.spec b/contrib/test_decoding/specs/mxact.spec
new file mode 100644
index 0000000..f5c0623
--- /dev/null
+++ b/contrib/test_decoding/specs/mxact.spec
@@ -0,0 +1,41 @@
+setup
+{
+    DROP TABLE IF EXISTS do_write;
+    DROP EXTENSION IF EXISTS test_decoding;
+    CREATE EXTENSION test_decoding;
+    CREATE TABLE do_write(id serial primary key);
+}
+
+teardown
+{
+    DROP TABLE IF EXISTS do_write;
+    DROP EXTENSION test_decoding;
+    SELECT 'stop' FROM pg_drop_replication_slot('isolation_slot');
+}
+
+session "s0"
+setup { SET synchronous_commit=on; }
+step "s0init" {SELECT 'init' FROM pg_create_decoding_replication_slot('isolation_slot', 'test_decoding');}
+step "s0start" {SELECT data FROM pg_decoding_slot_get_changes('isolation_slot', 'now', 'include-xids', 'false');}
+step "s0alter" {ALTER TABLE do_write ADD column ts timestamptz; }
+step "s0w" { INSERT INTO do_write DEFAULT VALUES; }
+
+session "s1"
+setup { SET synchronous_commit=on; }
+step "s1begin" {BEGIN;}
+step "s1sharepgclass" { SELECT count(*) > 1 FROM (SELECT * FROM pg_class FOR SHARE) s; }
+step "s1keysharepgclass" { SELECT count(*) > 1 FROM (SELECT * FROM pg_class FOR KEY SHARE) s; }
+step "s1commit" {COMMIT;}
+
+session "s2"
+setup { SET synchronous_commit=on; }
+step "s2begin" {BEGIN;}
+step "s2sharepgclass" { SELECT count(*) > 1 FROM (SELECT * FROM pg_class FOR SHARE) s; }
+step "s2keysharepgclass" { SELECT count(*) > 1 FROM (SELECT * FROM pg_class FOR KEY SHARE) s; }
+step "s2commit" {COMMIT;}
+
+# test that we're handling an update-only mxact xmax correctly
+permutation "s0init" "s0start" "s1begin" "s1sharepgclass" "s2begin" "s2sharepgclass" "s0w" "s0start" "s2commit" "s1commit"
+
+# test that we're handling an update-only mxact xmax correctly
+permutation "s0init" "s0start" "s1begin" "s1keysharepgclass" "s2begin" "s2keysharepgclass" "s0alter" "s0w" "s0start" "s2commit" "s1commit"
diff --git a/contrib/test_decoding/sql/ddl.sql b/contrib/test_decoding/sql/ddl.sql
new file mode 100644
index 0000000..e7428be
--- /dev/null
+++ b/contrib/test_decoding/sql/ddl.sql
@@ -0,0 +1,331 @@
+CREATE EXTENSION test_decoding;
+-- predictability
+SET synchronous_commit = on;
+
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+-- fail because of an already existing slot
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+-- fail because of an invalid name
+SELECT 'init' FROM pg_create_decoding_replication_slot('Invalid Name', 'test_decoding');
+
+-- fail twice because of an invalid parameter values
+SELECT 'init' FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', 'frakbar');
+SELECT 'init' FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'nonexistant-option', 'frakbar');
+SELECT 'init' FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', 'frakbar');
+
+-- succeed once
+SELECT pg_drop_replication_slot('regression_slot');
+-- fail
+SELECT pg_drop_replication_slot('regression_slot');
+
+-- check that we're detecting a streaming rep slot used for changeset extraction
+SELECT 'init' FROM pg_create_physical_replication_slot('repl');
+SELECT data FROM pg_decoding_slot_get_changes('repl', 'now', 'include-xids', '0');
+SELECT pg_drop_replication_slot('repl');
+
+
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+
+/* check whether status function reports us, only reproduceable columns */
+SELECT slot_name, plugin, slot_type, active,
+    NOT catalog_xmin IS NULL AS catalog_xmin_set,
+    xmin IS NULl  AS data_xmin_not_set,
+    pg_xlog_location_diff(restart_lsn, '0/01000000') > 0 AS some_wal
+FROM pg_replication_slots;
+
+/*
+ * Check that changes are handled correctly when interleaved with ddl
+ */
+CREATE TABLE replication_example(id SERIAL PRIMARY KEY, somedata int, text varchar(120));
+BEGIN;
+INSERT INTO replication_example(somedata, text) VALUES (1, 1);
+INSERT INTO replication_example(somedata, text) VALUES (1, 2);
+COMMIT;
+
+ALTER TABLE replication_example ADD COLUMN bar int;
+
+INSERT INTO replication_example(somedata, text, bar) VALUES (2, 1, 4);
+
+BEGIN;
+INSERT INTO replication_example(somedata, text, bar) VALUES (2, 2, 4);
+INSERT INTO replication_example(somedata, text, bar) VALUES (2, 3, 4);
+INSERT INTO replication_example(somedata, text, bar) VALUES (2, 4, NULL);
+COMMIT;
+
+ALTER TABLE replication_example DROP COLUMN bar;
+INSERT INTO replication_example(somedata, text) VALUES (3, 1);
+
+BEGIN;
+INSERT INTO replication_example(somedata, text) VALUES (3, 2);
+INSERT INTO replication_example(somedata, text) VALUES (3, 3);
+COMMIT;
+
+ALTER TABLE replication_example RENAME COLUMN text TO somenum;
+
+INSERT INTO replication_example(somedata, somenum) VALUES (4, 1);
+
+-- collect all changes
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+ALTER TABLE replication_example ALTER COLUMN somenum TYPE int4 USING (somenum::int4);
+-- throw away changes, they contain oids
+SELECT count(data) FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+INSERT INTO replication_example(somedata, somenum) VALUES (5, 1);
+
+BEGIN;
+INSERT INTO replication_example(somedata, somenum) VALUES (6, 1);
+ALTER TABLE replication_example ADD COLUMN zaphod1 int;
+INSERT INTO replication_example(somedata, somenum, zaphod1) VALUES (6, 2, 1);
+ALTER TABLE replication_example ADD COLUMN zaphod2 int;
+INSERT INTO replication_example(somedata, somenum, zaphod2) VALUES (6, 3, 1);
+INSERT INTO replication_example(somedata, somenum, zaphod1) VALUES (6, 4, 2);
+COMMIT;
+
+-- show changes
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+-- hide changes bc of oid visible in full table rewrites
+CREATE TABLE tr_unique(id2 serial unique NOT NULL, data int);
+INSERT INTO tr_unique(data) VALUES(10);
+ALTER TABLE tr_unique RENAME TO tr_pkey;
+ALTER TABLE tr_pkey ADD COLUMN id serial primary key;
+SELECT count(data) FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+INSERT INTO tr_pkey(data) VALUES(1);
+--show deletion with primary key
+DELETE FROM tr_pkey;
+
+/* display results */
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+/*
+ * check that disk spooling works
+ */
+BEGIN;
+CREATE TABLE tr_etoomuch (id serial primary key, data int);
+INSERT INTO tr_etoomuch(data) SELECT g.i FROM generate_series(1, 10234) g(i);
+DELETE FROM tr_etoomuch WHERE id < 5000;
+UPDATE tr_etoomuch SET data = - data WHERE id > 5000;
+COMMIT;
+
+/* display results, but hide most of the output */
+SELECT count(*), min(data), max(data)
+FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0')
+GROUP BY substring(data, 1, 24)
+ORDER BY 1;
+
+/*
+ * check whether we decode subtransactions correctly in relation with each
+ * other
+ */
+CREATE TABLE tr_sub (id serial primary key, path text);
+
+-- toplevel, subtxn, toplevel, subtxn, subtxn
+BEGIN;
+INSERT INTO tr_sub(path) VALUES ('1-top-#1');
+
+SAVEPOINT a;
+INSERT INTO tr_sub(path) VALUES ('1-top-1-#1');
+INSERT INTO tr_sub(path) VALUES ('1-top-1-#2');
+RELEASE SAVEPOINT a;
+
+SAVEPOINT b;
+SAVEPOINT c;
+INSERT INTO tr_sub(path) VALUES ('1-top-2-1-#1');
+INSERT INTO tr_sub(path) VALUES ('1-top-2-1-#2');
+RELEASE SAVEPOINT c;
+INSERT INTO tr_sub(path) VALUES ('1-top-2-#1');
+RELEASE SAVEPOINT b;
+COMMIT;
+
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+-- check that we handle xlog assignments correctly
+BEGIN;
+-- nest 80 subtxns
+SAVEPOINT subtop;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;SAVEPOINT a;
+-- assign xid by inserting
+INSERT INTO tr_sub(path) VALUES ('2-top-1...--#1');
+INSERT INTO tr_sub(path) VALUES ('2-top-1...--#2');
+INSERT INTO tr_sub(path) VALUES ('2-top-1...--#3');
+RELEASE SAVEPOINT subtop;
+INSERT INTO tr_sub(path) VALUES ('2-top-#1');
+COMMIT;
+
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+-- make sure rollbacked subtransactions aren't decoded
+BEGIN;
+INSERT INTO tr_sub(path) VALUES ('3-top-2-#1');
+SAVEPOINT a;
+INSERT INTO tr_sub(path) VALUES ('3-top-2-1-#1');
+SAVEPOINT b;
+INSERT INTO tr_sub(path) VALUES ('3-top-2-2-#1');
+ROLLBACK TO SAVEPOINT b;
+INSERT INTO tr_sub(path) VALUES ('3-top-2-#2');
+COMMIT;
+
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+-- test whether a known, but not yet logged toplevel xact, followed by a
+-- subxact commit is handled correctly
+BEGIN;
+SELECT txid_current() != 0; -- so no fixed xid apears in the outfile
+SAVEPOINT a;
+INSERT INTO tr_sub(path) VALUES ('4-top-1-#1');
+RELEASE SAVEPOINT a;
+COMMIT;
+
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+
+/*
+ * Check whether treating a table as a catalog table works somewhat
+ */
+CREATE TABLE replication_metadata (
+    id serial primary key,
+    relation name NOT NULL,
+    options text[]
+)
+WITH (user_catalog_table = true)
+;
+\d+ replication_metadata
+
+INSERT INTO replication_metadata(relation, options)
+VALUES ('foo', ARRAY['a', 'b']);
+
+ALTER TABLE replication_metadata RESET (user_catalog_table);
+\d+ replication_metadata
+
+INSERT INTO replication_metadata(relation, options)
+VALUES ('bar', ARRAY['a', 'b']);
+
+ALTER TABLE replication_metadata SET (user_catalog_table = true);
+\d+ replication_metadata
+
+INSERT INTO replication_metadata(relation, options)
+VALUES ('blub', NULL);
+
+-- make sure rewrites don't work
+ALTER TABLE replication_metadata ADD COLUMN rewritemeornot int;
+ALTER TABLE replication_metadata ALTER COLUMN rewritemeornot TYPE text;
+
+ALTER TABLE replication_metadata SET (user_catalog_table = false);
+\d+ replication_metadata
+
+INSERT INTO replication_metadata(relation, options)
+VALUES ('zaphod', NULL);
+
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+/*
+ * check whether we handle updates/deletes correct with & without a pkey
+ */
+
+/* we should handle the case without a key at all more gracefully */
+CREATE TABLE table_without_key(id serial, data int);
+INSERT INTO table_without_key(data) VALUES(1),(2);
+DELETE FROM table_without_key WHERE data = 1;
+-- won't log old keys
+UPDATE table_without_key SET data = 3 WHERE data = 2;
+UPDATE table_without_key SET id = -id;
+UPDATE table_without_key SET id = -id;
+-- should log the full old row now
+ALTER TABLE table_without_key REPLICA IDENTITY FULL;
+UPDATE table_without_key SET data = 3 WHERE data = 2;
+UPDATE table_without_key SET id = -id;
+UPDATE table_without_key SET id = -id;
+DELETE FROM table_without_key WHERE data = 3;
+
+CREATE TABLE table_with_pkey(id serial primary key, data int);
+INSERT INTO table_with_pkey(data) VALUES(1), (2);
+DELETE FROM table_with_pkey WHERE data = 1;
+-- should log the old pkey
+UPDATE table_with_pkey SET data = 3 WHERE data = 2;
+UPDATE table_with_pkey SET id = -id;
+UPDATE table_with_pkey SET id = -id;
+-- check that we log nothing despite having a pkey
+ALTER TABLE table_without_key REPLICA IDENTITY NOTHING;
+UPDATE table_with_pkey SET id = -id;
+-- check that we log everything despite having a pkey
+ALTER TABLE table_without_key REPLICA IDENTITY FULL;
+UPDATE table_with_pkey SET id = -id;
+DELETE FROM table_with_pkey WHERE data = 3;
+
+CREATE TABLE table_with_unique_not_null(id serial unique, data int);
+ALTER TABLE table_with_unique_not_null ALTER COLUMN id SET NOT NULL; --already set
+-- won't log anything, replica identity not setup
+INSERT INTO table_with_unique_not_null(data) VALUES(1), (2);
+DELETE FROM table_with_unique_not_null WHERE data = 1;
+UPDATE table_with_unique_not_null SET data = 3 WHERE data = 2;
+UPDATE table_with_unique_not_null SET id = -id;
+UPDATE table_with_unique_not_null SET id = -id;
+DELETE FROM table_with_unique_not_null WHERE data = 3;
+-- should log old key
+ALTER TABLE table_with_unique_not_null REPLICA IDENTITY USING INDEX table_with_unique_not_null_id_key;
+INSERT INTO table_with_unique_not_null(data) VALUES(1), (2);
+DELETE FROM table_with_unique_not_null WHERE data = 1;
+UPDATE table_with_unique_not_null SET data = 3 WHERE data = 2;
+UPDATE table_with_unique_not_null SET id = -id;
+UPDATE table_with_unique_not_null SET id = -id;
+DELETE FROM table_with_unique_not_null WHERE data = 3;
+
+-- check toast support
+SELECT setseed(0);
+CREATE TABLE toasttable(
+       id serial primary key,
+       toasted_col1 text,
+       rand1 float8 DEFAULT random(),
+       toasted_col2 text,
+       rand2 float8 DEFAULT random()
+       );
+
+-- uncompressed external toast data
+INSERT INTO toasttable(toasted_col1) SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i);
+
+-- compressed external toast data
+INSERT INTO toasttable(toasted_col2) SELECT repeat(string_agg(to_char(g.i, 'FM0000'), ''), 50) FROM generate_series(1, 500) g(i);
+
+-- update of existing column
+UPDATE toasttable
+    SET toasted_col1 = (SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i))
+WHERE id = 1;
+
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+INSERT INTO toasttable(toasted_col1) SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i);
+
+-- update of second column, first column unchanged
+UPDATE toasttable
+    SET toasted_col2 = (SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i))
+WHERE id = 1;
+
+-- make sure we decode correctly even if the toast table is gone
+DROP TABLE toasttable;
+
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+-- done, free logical replication slot
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+SELECT pg_drop_replication_slot('regression_slot');
+
+/* check that we aren't visible anymore now */
+SELECT * FROM pg_stat_logical_decoding;
+
+DROP EXTENSION test_decoding;
diff --git a/contrib/test_decoding/sql/permissions.sql b/contrib/test_decoding/sql/permissions.sql
new file mode 100644
index 0000000..b467e2c
--- /dev/null
+++ b/contrib/test_decoding/sql/permissions.sql
@@ -0,0 +1,70 @@
+CREATE EXTENSION test_decoding;
+-- predictability
+SET synchronous_commit = on;
+
+-- setup
+CREATE ROLE lr_normal;
+CREATE ROLE lr_superuser SUPERUSER;
+CREATE ROLE lr_replication REPLICATION;
+CREATE TABLE lr_test(data text);
+
+-- superuser can control replication
+SET ROLE lr_superuser;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+INSERT INTO lr_test VALUES('lr_superuser_init');
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+SELECT pg_drop_replication_slot('regression_slot');
+RESET ROLE;
+
+-- replication user can control replication
+SET ROLE lr_replication;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+INSERT INTO lr_test VALUES('lr_superuser_init');
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+SELECT pg_drop_replication_slot('regression_slot');
+RESET ROLE;
+
+-- plain user *can't* can control replication
+SET ROLE lr_normal;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+INSERT INTO lr_test VALUES('lr_superuser_init');
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+SELECT pg_drop_replication_slot('regression_slot');
+RESET ROLE;
+
+-- replication users can drop superuser created slots
+SET ROLE lr_superuser;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+RESET ROLE;
+SET ROLE lr_replication;
+SELECT pg_drop_replication_slot('regression_slot');
+RESET ROLE;
+
+-- normal users can't drop existing slots
+SET ROLE lr_superuser;
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+RESET ROLE;
+SET ROLE lr_normal;
+SELECT pg_drop_replication_slot('regression_slot');
+RESET ROLE;
+
+-- all users can see existing slots
+SET ROLE lr_superuser;
+SELECT slot_name, plugin FROM pg_replication_slots;
+RESET ROLE;
+
+SET ROLE lr_replication;
+SELECT slot_name, plugin FROM pg_replication_slots;
+RESET ROLE;
+
+SET ROLE lr_normal;
+SELECT slot_name, plugin FROM pg_replication_slots;
+RESET ROLE;
+
+-- cleanup
+SELECT pg_drop_replication_slot('regression_slot');
+
+DROP ROLE lr_normal;
+DROP ROLE lr_superuser;
+DROP ROLE lr_replication;
+DROP TABLE lr_test;
diff --git a/contrib/test_decoding/sql/rewrite.sql b/contrib/test_decoding/sql/rewrite.sql
new file mode 100644
index 0000000..27193ea
--- /dev/null
+++ b/contrib/test_decoding/sql/rewrite.sql
@@ -0,0 +1,64 @@
+CREATE EXTENSION test_decoding;
+-- predictability
+SET synchronous_commit = on;
+
+DROP TABLE IF EXISTS replication_example;
+
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+CREATE TABLE replication_example(id SERIAL PRIMARY KEY, somedata int, text varchar(120));
+INSERT INTO replication_example(somedata) VALUES (1);
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+
+BEGIN;
+INSERT INTO replication_example(somedata) VALUES (2);
+ALTER TABLE replication_example ADD COLUMN testcolumn1 int;
+INSERT INTO replication_example(somedata, testcolumn1) VALUES (3,  1);
+COMMIT;
+
+BEGIN;
+INSERT INTO replication_example(somedata) VALUES (3);
+ALTER TABLE replication_example ADD COLUMN testcolumn2 int;
+INSERT INTO replication_example(somedata, testcolumn1, testcolumn2) VALUES (4,  2, 1);
+COMMIT;
+
+VACUUM FULL pg_am;
+VACUUM FULL pg_amop;
+VACUUM FULL pg_proc;
+VACUUM FULL pg_opclass;
+VACUUM FULL pg_type;
+VACUUM FULL pg_index;
+VACUUM FULL pg_database;
+
+-- repeated rewrites that fail
+BEGIN;
+CLUSTER pg_class USING pg_class_oid_index;
+CLUSTER pg_class USING pg_class_oid_index;
+ROLLBACK;
+
+-- repeated rewrites that succeed
+BEGIN;
+CLUSTER pg_class USING pg_class_oid_index;
+CLUSTER pg_class USING pg_class_oid_index;
+CLUSTER pg_class USING pg_class_oid_index;
+COMMIT;
+
+ -- repeated rewrites in different transactions
+VACUUM FULL pg_class;
+VACUUM FULL pg_class;
+
+INSERT INTO replication_example(somedata, testcolumn1) VALUES (5, 3);
+
+BEGIN;
+INSERT INTO replication_example(somedata, testcolumn1) VALUES (6, 4);
+ALTER TABLE replication_example ADD COLUMN testcolumn3 int;
+INSERT INTO replication_example(somedata, testcolumn1, testcolumn3) VALUES (7, 5, 1);
+COMMIT;
+
+-- make old files go away
+CHECKPOINT;
+
+SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+SELECT pg_drop_replication_slot('regression_slot');
+
+DROP TABLE IF EXISTS replication_example;
+DROP EXTENSION test_decoding;
diff --git a/contrib/test_decoding/sql/slot.sql b/contrib/test_decoding/sql/slot.sql
new file mode 100644
index 0000000..46dea1c
--- /dev/null
+++ b/contrib/test_decoding/sql/slot.sql
@@ -0,0 +1,75 @@
+CREATE FUNCTION pg_catalog.pg_td_mkdir(text)
+RETURNS void
+AS '$libdir/test_decoding_regsupport', 'pg_td_mkdir'
+LANGUAGE C VOLATILE STRICT;
+
+CREATE FUNCTION pg_catalog.pg_td_rmdir(text)
+RETURNS void
+AS '$libdir/test_decoding_regsupport', 'pg_td_rmdir'
+LANGUAGE C VOLATILE STRICT;
+
+CREATE FUNCTION pg_catalog.pg_td_unlink(text)
+RETURNS void
+AS '$libdir/test_decoding_regsupport', 'pg_td_unlink'
+LANGUAGE C VOLATILE STRICT;
+
+CREATE FUNCTION pg_catalog.pg_td_chmod(text, text)
+RETURNS void
+AS '$libdir/test_decoding_regsupport', 'pg_td_chmod'
+LANGUAGE C VOLATILE STRICT;
+
+-- drop all slots
+SELECT pg_drop_replication_slot(slot_name)
+FROM pg_replication_slots
+WHERE slot_name LIKE 'slottest_%';
+
+-- succeed
+SELECT * FROM pg_create_physical_replication_slot('slottest_1');
+SELECT * FROM pg_create_physical_replication_slot('slottest_2');
+-- fail, duplicate
+SELECT * FROM pg_create_physical_replication_slot('slottest_1');
+-- succeed
+SELECT pg_drop_replication_slot('slottest_1');
+
+SELECT pg_td_chmod('pg_replslot', '0');
+-- fail, no permissions on entire pg_replslot director
+SELECT * FROM pg_create_physical_replication_slot('slottest_3');
+SELECT * FROM pg_drop_replication_slot('slottest_2');
+
+SELECT pg_td_chmod('pg_replslot', '700');
+
+-- succeed, we have permissions again
+SELECT * FROM pg_drop_replication_slot('slottest_2');
+
+SELECT * FROM pg_create_physical_replication_slot('slottest_4');
+SELECT pg_td_chmod('pg_replslot/slottest_4', '000');
+-- succeed as the rename works, with WARNINGs
+SELECT * FROM pg_drop_replication_slot('slottest_4');
+-- fail, temp director exists
+SELECT * FROM pg_create_physical_replication_slot('slottest_4');
+-- cleanup half-deleted slot
+SELECT pg_td_chmod('pg_replslot/slottest_4.tmp', '700');
+SELECT pg_td_unlink('pg_replslot/slottest_4.tmp/state');
+SELECT pg_td_rmdir('pg_replslot/slottest_4.tmp');
+-- check cleanup
+SELECT * FROM pg_create_physical_replication_slot('slottest_4');
+SELECT * FROM pg_drop_replication_slot('slottest_4');
+
+-- fail, slot directory exists
+SELECT pg_td_mkdir('pg_replslot/slottest_5');
+SELECT * FROM pg_drop_replication_slot('slottest_5');
+SELECT pg_td_rmdir('pg_replslot/slottest_5');
+
+SELECT pg_td_mkdir('pg_replslot/slottest_6.tmp');
+SELECT pg_td_mkdir('pg_replslot/slottest_6.tmp/blub');
+
+-- suceed, temp directory exists, but we remove it
+SELECT * FROM pg_create_physical_replication_slot('slottest_6');
+
+-- succeed, temp directory removed
+SELECT * FROM pg_create_physical_replication_slot('slottest_6');
+SELECT * FROM pg_drop_replication_slot('slottest_6');
+
+SELECT pg_drop_replication_slot(slot_name)
+FROM pg_replication_slots
+WHERE slot_name LIKE 'slottest_%';
diff --git a/contrib/test_decoding/sql/toast.sql b/contrib/test_decoding/sql/toast.sql
new file mode 100644
index 0000000..ec69420
--- /dev/null
+++ b/contrib/test_decoding/sql/toast.sql
@@ -0,0 +1,54 @@
+CREATE EXTENSION test_decoding;
+-- predictability
+SET synchronous_commit = on;
+
+DROP TABLE IF EXISTS xpto;
+
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+
+SELECT setseed(0);
+CREATE TABLE xpto (
+    id serial primary key,
+    toasted_col1 text,
+    rand1 float8 DEFAULT random(),
+    toasted_col2 text,
+    rand2 float8 DEFAULT random()
+);
+
+-- uncompressed external toast data
+INSERT INTO xpto (toasted_col1, toasted_col2) SELECT string_agg(g.i::text, ''), string_agg((g.i*2)::text, '') FROM generate_series(1, 2000) g(i);
+
+-- compressed external toast data
+INSERT INTO xpto (toasted_col2) SELECT repeat(string_agg(to_char(g.i, 'FM0000'), ''), 50) FROM generate_series(1, 500) g(i);
+
+-- update of existing column
+UPDATE xpto SET toasted_col1 = (SELECT string_agg(g.i::text, '') FROM generate_series(1, 2000) g(i)) WHERE id = 1;
+
+UPDATE xpto SET rand1 = 123.456 WHERE id = 1;
+
+DELETE FROM xpto WHERE id = 1;
+
+DROP TABLE IF EXISTS toasted_key;
+CREATE TABLE toasted_key (
+    id serial,
+    toasted_key text PRIMARY KEY,
+    toasted_col1 text,
+    toasted_col2 text
+);
+
+ALTER TABLE toasted_key ALTER COLUMN toasted_key SET STORAGE EXTERNAL;
+ALTER TABLE toasted_key ALTER COLUMN toasted_col1 SET STORAGE EXTERNAL;
+
+INSERT INTO toasted_key(toasted_key, toasted_col1) VALUES(repeat('1234567890', 200), repeat('9876543210', 200));
+
+-- test update of a toasted key without changing it
+UPDATE toasted_key SET toasted_col2 = toasted_col1;
+-- test update of a toasted key, changing it
+UPDATE toasted_key SET toasted_key = toasted_key || '1';
+
+DELETE FROM toasted_key;
+
+SELECT substr(data, 1, 200) FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+SELECT pg_drop_replication_slot('regression_slot');
+
+DROP EXTENSION test_decoding;
diff --git a/contrib/test_decoding/test_decoding--1.0.sql b/contrib/test_decoding/test_decoding--1.0.sql
new file mode 100644
index 0000000..919e263
--- /dev/null
+++ b/contrib/test_decoding/test_decoding--1.0.sql
@@ -0,0 +1,2 @@
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_decoding" to load this file. \quit
diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding/test_decoding.c
new file mode 100644
index 0000000..7298e36
--- /dev/null
+++ b/contrib/test_decoding/test_decoding.c
@@ -0,0 +1,340 @@
+/*-------------------------------------------------------------------------
+ *
+ * test_decoding.c
+ *		  example changeset extraction output plugin
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		  contrib/test_decoding/test_decoding.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/sysattr.h"
+
+#include "catalog/pg_class.h"
+#include "catalog/pg_type.h"
+
+#include "nodes/parsenodes.h"
+
+#include "replication/output_plugin.h"
+#include "replication/logical.h"
+
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/rel.h"
+#include "utils/relcache.h"
+#include "utils/syscache.h"
+#include "utils/typcache.h"
+
+
+PG_MODULE_MAGIC;
+
+extern void		_PG_init(void);
+extern void		_PG_output_plugin_init(OutputPluginCallbacks *cb);
+
+typedef struct
+{
+	MemoryContext context;
+	bool		include_xids;
+	bool		include_timestamp;
+} TestDecodingData;
+
+/* These must be available to pg_dlsym() */
+static void pg_decode_startup(LogicalDecodingContext *ctx, bool is_init);
+static void pg_decode_shutdown(LogicalDecodingContext *ctx);
+static void pg_decode_begin_txn(LogicalDecodingContext *ctx,
+					ReorderBufferTXN *txn);
+static void pg_decode_commit_txn(LogicalDecodingContext *ctx,
+					 ReorderBufferTXN *txn, XLogRecPtr commit_lsn);
+static void pg_decode_change(LogicalDecodingContext *ctx,
+				 ReorderBufferTXN *txn, Relation rel,
+				 ReorderBufferChange *change);
+
+void
+_PG_init(void)
+{
+	/* other plugins can perform things here */
+}
+
+/* specify output plugin callbacks */
+void
+_PG_output_plugin_init(OutputPluginCallbacks *cb)
+{
+	AssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);
+
+	cb->startup_cb = pg_decode_startup;
+	cb->begin_cb = pg_decode_begin_txn;
+	cb->change_cb = pg_decode_change;
+	cb->commit_cb = pg_decode_commit_txn;
+	cb->shutdown_cb = pg_decode_shutdown;
+}
+
+
+/* initialize this plugin */
+static void
+pg_decode_startup(LogicalDecodingContext *ctx, bool is_init)
+{
+	ListCell   *option;
+	TestDecodingData *data;
+
+	data = palloc(sizeof(TestDecodingData));
+	data->context = AllocSetContextCreate(ctx->context,
+										  "text conversion context",
+										  ALLOCSET_DEFAULT_MINSIZE,
+										  ALLOCSET_DEFAULT_INITSIZE,
+										  ALLOCSET_DEFAULT_MAXSIZE);
+	data->include_xids = true;
+	data->include_timestamp = false;
+
+	ctx->output_plugin_private = data;
+
+	foreach(option, ctx->output_plugin_options)
+	{
+		DefElem    *elem = lfirst(option);
+
+		Assert(elem->arg == NULL || IsA(elem->arg, String));
+
+		if (strcmp(elem->defname, "include-xids") == 0)
+		{
+			/* if option does not provide a value, it means its value is true */
+			if (elem->arg == NULL)
+				data->include_xids = true;
+			else if (!parse_bool(strVal(elem->arg), &data->include_xids))
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("could not parse value \"%s\" for parameter \"%s\"",
+								strVal(elem->arg), elem->defname)));
+		}
+		else if (strcmp(elem->defname, "include-timestamp") == 0)
+		{
+			if (elem->arg == NULL)
+				data->include_timestamp = true;
+			else if (!parse_bool(strVal(elem->arg), &data->include_timestamp))
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("could not parse value \"%s\" for parameter \"%s\"",
+								strVal(elem->arg), elem->defname)));
+		}
+		else
+		{
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("option \"%s\" = \"%s\" is unknown",
+							elem->defname,
+							elem->arg ? strVal(elem->arg) : "(null)")));
+		}
+	}
+}
+
+/* cleanup this plugin's resources */
+static void
+pg_decode_shutdown(LogicalDecodingContext *ctx)
+{
+	TestDecodingData *data = ctx->output_plugin_private;
+
+	/* cleanup our own resources via memory context reset */
+	MemoryContextDelete(data->context);
+}
+
+/* BEGIN callback */
+static void
+pg_decode_begin_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
+{
+	TestDecodingData *data = ctx->output_plugin_private;
+
+	OutputPluginPrepareWrite(ctx, true);
+	if (data->include_xids)
+		appendStringInfo(ctx->out, "BEGIN %u", txn->xid);
+	else
+		appendStringInfoString(ctx->out, "BEGIN");
+	OutputPluginWrite(ctx, true);
+}
+
+/* COMMIT callback */
+static void
+pg_decode_commit_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
+					 XLogRecPtr commit_lsn)
+{
+	TestDecodingData *data = ctx->output_plugin_private;
+
+	OutputPluginPrepareWrite(ctx, true);
+	if (data->include_xids)
+		appendStringInfo(ctx->out, "COMMIT %u", txn->xid);
+	else
+		appendStringInfoString(ctx->out, "COMMIT");
+
+	if (data->include_timestamp)
+		appendStringInfo(ctx->out, " (at %s)",
+						 timestamptz_to_str(txn->commit_time));
+
+	OutputPluginWrite(ctx, true);
+}
+
+/* print the tuple 'tuple' into the StringInfo s */
+static void
+tuple_to_stringinfo(StringInfo s, TupleDesc tupdesc, HeapTuple tuple, bool skip_nulls)
+{
+	int			natt;
+	Oid			oid;
+
+	/* print oid of tuple, it's not included in the TupleDesc */
+	if ((oid = HeapTupleHeaderGetOid(tuple->t_data)) != InvalidOid)
+	{
+		appendStringInfo(s, " oid[oid]:%u", oid);
+	}
+
+	/* print all columns individually */
+	for (natt = 0; natt < tupdesc->natts; natt++)
+	{
+		Form_pg_attribute attr; /* the attribute itself */
+		Oid			typid;		/* type of current attribute */
+		HeapTuple	type_tuple; /* information about a type */
+		Form_pg_type type_form;
+		Oid			typoutput;	/* output function */
+		bool		typisvarlena;
+		Datum		origval;	/* possibly toasted Datum */
+		Datum		val;		/* definitely detoasted Datum */
+		char	   *outputstr = NULL;
+		bool		isnull;		/* column is null? */
+
+		attr = tupdesc->attrs[natt];
+
+		/*
+		 * don't print dropped columns, we can't be sure everything is
+		 * available for them
+		 */
+		if (attr->attisdropped)
+			continue;
+
+		/*
+		 * Don't print system columns, oid will already have been printed if
+		 * present.
+		 */
+		if (attr->attnum < 0)
+			continue;
+
+		typid = attr->atttypid;
+
+		/* gather type name */
+		type_tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
+		if (!HeapTupleIsValid(type_tuple))
+			elog(ERROR, "cache lookup failed for type %u", typid);
+		type_form = (Form_pg_type) GETSTRUCT(type_tuple);
+
+		/* get Datum from tuple */
+		origval = fastgetattr(tuple, natt + 1, tupdesc, &isnull);
+
+		if (isnull && skip_nulls)
+			continue;
+
+		/* print attribute name */
+		appendStringInfoChar(s, ' ');
+		appendStringInfoString(s, NameStr(attr->attname));
+
+		/* print attribute type */
+		appendStringInfoChar(s, '[');
+		appendStringInfoString(s, NameStr(type_form->typname));
+		appendStringInfoChar(s, ']');
+
+		/* query output function */
+		getTypeOutputInfo(typid,
+						  &typoutput, &typisvarlena);
+
+		ReleaseSysCache(type_tuple);
+
+		if (isnull)
+			outputstr = "(null)";
+		else if (typisvarlena && VARATT_IS_EXTERNAL_ONDISK(origval))
+			outputstr = "(unchanged-toast-datum)";
+		else if (typisvarlena)
+			val = PointerGetDatum(PG_DETOAST_DATUM(origval));
+		else
+			val = origval;
+
+		/* call output function if necessary */
+		if (outputstr == NULL)
+			outputstr = OidOutputFunctionCall(typoutput, val);
+
+		/* print data */
+		appendStringInfoChar(s, ':');
+		appendStringInfoString(s, outputstr);
+	}
+}
+
+/*
+ * callback for individual changed tuples
+ */
+static void
+pg_decode_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
+				 Relation relation, ReorderBufferChange *change)
+{
+	TestDecodingData *data;
+	Form_pg_class class_form;
+	TupleDesc	tupdesc;
+	MemoryContext old;
+
+	data = ctx->output_plugin_private;
+	class_form = RelationGetForm(relation);
+	tupdesc = RelationGetDescr(relation);
+
+	/* Avoid leaking memory by using and resetting our own context */
+	old = MemoryContextSwitchTo(data->context);
+
+	OutputPluginPrepareWrite(ctx, true);
+
+	appendStringInfoString(ctx->out, "table \"");
+	appendStringInfoString(ctx->out, NameStr(class_form->relname));
+	appendStringInfoString(ctx->out, "\":");
+
+	switch (change->action)
+	{
+		case REORDER_BUFFER_CHANGE_INSERT:
+			appendStringInfoString(ctx->out, " INSERT:");
+			if (change->tp.newtuple == NULL)
+				appendStringInfoString(ctx->out, " (no-tuple-data)");
+			else
+				tuple_to_stringinfo(ctx->out, tupdesc,
+									&change->tp.newtuple->tuple,
+									false);
+			break;
+		case REORDER_BUFFER_CHANGE_UPDATE:
+			appendStringInfoString(ctx->out, " UPDATE:");
+			if (change->tp.oldtuple != NULL)
+			{
+				appendStringInfoString(ctx->out, " old-key:");
+				tuple_to_stringinfo(ctx->out, tupdesc,
+									&change->tp.oldtuple->tuple,
+									true);
+				appendStringInfoString(ctx->out, " new-tuple:");
+			}
+
+			if (change->tp.newtuple == NULL)
+				appendStringInfoString(ctx->out, " (no-tuple-data)");
+			else
+				tuple_to_stringinfo(ctx->out, tupdesc,
+									&change->tp.newtuple->tuple,
+									false);
+			break;
+		case REORDER_BUFFER_CHANGE_DELETE:
+			appendStringInfoString(ctx->out, " DELETE:");
+
+			/* if there was no PK, we only know that a delete happened */
+			if (change->tp.oldtuple == NULL)
+				appendStringInfoString(ctx->out, " (no-tuple-data)");
+			/* In DELETE, only the replica identity is present; display that */
+			else
+				tuple_to_stringinfo(ctx->out, tupdesc,
+									&change->tp.oldtuple->tuple,
+									true);
+			break;
+	}
+
+	MemoryContextSwitchTo(old);
+	MemoryContextReset(data->context);
+
+	OutputPluginWrite(ctx, true);
+}
diff --git a/contrib/test_decoding/test_decoding.control b/contrib/test_decoding/test_decoding.control
new file mode 100644
index 0000000..8e8058b
--- /dev/null
+++ b/contrib/test_decoding/test_decoding.control
@@ -0,0 +1,5 @@
+# test_decoding extension
+comment = 'test output plugin for changeset extraction / logical replication'
+default_version = '1.0'
+module_pathname = '$libdir/test_decoding'
+relocatable = true
diff --git a/contrib/test_decoding/test_decoding_regsupport.c b/contrib/test_decoding/test_decoding_regsupport.c
new file mode 100644
index 0000000..99d5b51
--- /dev/null
+++ b/contrib/test_decoding/test_decoding_regsupport.c
@@ -0,0 +1,129 @@
+/*-------------------------------------------------------------------------
+ *
+ * test_decoding_regsupport.c
+ *		  regression test functions
+ *
+ * Copyright (c) 2014, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		  contrib/test_decoding/test_decoding_regsupport.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "access/sysattr.h"
+
+#include "catalog/pg_class.h"
+#include "catalog/pg_type.h"
+
+#include "nodes/parsenodes.h"
+
+#include "replication/output_plugin.h"
+#include "replication/logical.h"
+
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/rel.h"
+#include "utils/relcache.h"
+#include "utils/syscache.h"
+#include "utils/typcache.h"
+
+
+PG_MODULE_MAGIC;
+
+Datum		pg_td_mkdir(PG_FUNCTION_ARGS);
+Datum		pg_td_rmdir(PG_FUNCTION_ARGS);
+Datum		pg_td_unlink(PG_FUNCTION_ARGS);
+Datum		pg_td_chmod(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(pg_td_mkdir);
+PG_FUNCTION_INFO_V1(pg_td_rmdir);
+PG_FUNCTION_INFO_V1(pg_td_unlink);
+PG_FUNCTION_INFO_V1(pg_td_chmod);
+
+
+Datum
+pg_td_mkdir(PG_FUNCTION_ARGS)
+{
+	text	   *dirname_t = PG_GETARG_TEXT_P(0);
+	const char *dirname;
+
+	dirname = text_to_cstring(dirname_t);
+
+	if (mkdir(dirname, S_IRWXU) < 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not create directory \"%s\": %m",
+						dirname)));
+
+	PG_RETURN_VOID();
+}
+
+Datum
+pg_td_rmdir(PG_FUNCTION_ARGS)
+{
+	text	   *dirname_t = PG_GETARG_TEXT_P(0);
+	const char *dirname;
+
+	dirname = text_to_cstring(dirname_t);
+
+	if (rmdir(dirname) < 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not remove directory \"%s\": %m",
+						dirname)));
+
+	PG_RETURN_VOID();
+}
+
+Datum
+pg_td_unlink(PG_FUNCTION_ARGS)
+{
+	text	   *filename_t = PG_GETARG_TEXT_P(0);
+	const char *filename;
+
+	filename = text_to_cstring(filename_t);
+
+	if (unlink(filename) < 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not unlink \"%s\": %m",
+						filename)));
+
+	PG_RETURN_VOID();
+}
+
+
+Datum
+pg_td_chmod(PG_FUNCTION_ARGS)
+{
+	text	   *fname_t = PG_GETARG_TEXT_P(0);
+	text	   *modes_t = PG_GETARG_TEXT_P(1);
+	const char *fname;
+	const char *modes;
+	mode_t mode;
+
+	fname = text_to_cstring(fname_t);
+	modes = text_to_cstring(modes_t);
+
+	errno = 0;
+	mode = (mode_t) strtoul(modes, NULL, 8);
+
+	if (errno != 0)
+		ereport(ERROR,
+				(errmsg("could not parse mode \"%s\": %m",
+						modes)));
+
+	if (chmod(fname, mode) < 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not chmod(\"%s\", %x): %m",
+						fname, mode)));
+
+	PG_RETURN_VOID();
+}
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index 0195916..6c6c3fe 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -140,6 +140,7 @@ CREATE EXTENSION <replaceable>module_name</> FROM unpackaged;
  &sslinfo;
  &tablefunc;
  &tcn;
+ &test-decoding;
  &test-parser;
  &test-shm-mq;
  &tsearch2;
diff --git a/doc/src/sgml/test-decoding.sgml b/doc/src/sgml/test-decoding.sgml
new file mode 100644
index 0000000..c0e0c91
--- /dev/null
+++ b/doc/src/sgml/test-decoding.sgml
@@ -0,0 +1,55 @@
+<!-- doc/src/sgml/test-decoding.sgml -->
+
+<sect1 id="test-decoding" xreflabel="test_decoding">
+ <title>test_decoding</title>
+
+ <indexterm zone="test-decoding">
+  <primary>test_decoding</primary>
+ </indexterm>
+
+ <para>
+  <filename>test_decoding</> is an example of a logical changeset decoding
+  output plugin. It doesn't do anything especially useful, but can serve as
+  a starting point for developing your own decoder.
+ </para>
+
+ <para>
+  <filename>test_decoding</> receives WAL through the changeset decoding
+  mechanism and decodes it into text representations of the operations
+  performed. Changeset decoding is discussed in detail in <xref
+  linkend="changesetextraction">.
+ </para>
+
+ <para>
+  Typical output from this plugin, used over the SQL changeset decoding
+  interface, might be:
+
+  <programlisting>
+postgres=# SELECT * FROM decoding_slot_get_changes('test_slot', 'now', 'include-xids', '0');
+ location  | xid |                       data                       
+-----------+-----+--------------------------------------------------
+ 0/16D30F8 | 691 | BEGIN
+ 0/16D32A0 | 691 | table "data": INSERT: id[int4]:2 data[text]:arg
+ 0/16D32A0 | 691 | table "data": INSERT: id[int4]:3 data[text]:demo
+ 0/16D32A0 | 691 | COMMIT
+ 0/16D32D8 | 692 | BEGIN
+ 0/16D3398 | 692 | table "data": DELETE: id[int4]:2
+ 0/16D3398 | 692 | table "data": DELETE: id[int4]:3
+ 0/16D3398 | 692 | COMMIT
+(8 rows)
+  </programlisting>
+ </para>
+
+ <sect2>
+  <title>Usage</title>
+
+  <para>
+   <literal>CREATE EXTENSION</literal> has no significant effect for this
+   extension, beyond registering that it is available and in use. The extension
+   library may be used from any database without explicit installation, but
+   only via changeset extraction controlled by a superuser or replication user.
+  </para>
+
+ </sect2>
+
+</sect1>
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index e0e9b79..6db4ad1 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -463,6 +463,8 @@ pg_regress_installcheck = $(top_builddir)/src/test/regress/pg_regress --inputdir
 
 pg_regress_clean_files = results/ regression.diffs regression.out tmp_check/ log/
 
+pg_isolation_regress_check = $(top_builddir)/src/test/isolation/pg_isolation_regress --inputdir=$(srcdir) --temp-install=./tmp_check --top-builddir=$(top_builddir) $(pg_regress_locale_flags)
+pg_isolation_regress_installcheck = $(top_builddir)/src/test/isolation/pg_isolation_regress --inputdir=$(srcdir) --top-builddir=$(top_builddir) $(pg_regress_locale_flags)
 
 ##########################################################################
 #
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index a771ccb..981b50c 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -347,8 +347,11 @@ heapgetpage(HeapScanDesc scan, BlockNumber page)
 	/*
 	 * Prune and repair fragmentation for the whole page, if possible.
 	 */
-	Assert(TransactionIdIsValid(RecentGlobalXmin));
-	heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+	if (IsSystemRelation(scan->rs_rd)
+		|| RelationIsAccessibleInLogicalDecoding(scan->rs_rd))
+		heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+	else
+		heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalDataXmin);
 
 	/*
 	 * We must hold share lock on the buffer content while examining tuple
@@ -1750,10 +1753,22 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
 		 */
 		if (!skip)
 		{
+			/*
+			 * For the benefit of logical decoding, have t_self point at the
+			 * element of the HOT chain we're currently investigating instead
+			 * of the root tuple of the HOT chain. This is important because
+			 * the *Satisfies routine for historical mvcc snapshots needs the
+			 * correct tid to decide about the visibility in some cases.
+			 */
+			ItemPointerSet(&(heapTuple->t_self), BufferGetBlockNumber(buffer), offnum);
+
 			/* If it's visible per the snapshot, we must return it */
 			valid = HeapTupleSatisfiesVisibility(heapTuple, snapshot, buffer);
 			CheckForSerializableConflictOut(valid, relation, heapTuple,
 											buffer, snapshot);
+			/* reset to original, non-redirected, tid */
+			heapTuple->t_self = *tid;
+
 			if (valid)
 			{
 				ItemPointerSetOffsetNumber(tid, offnum);
@@ -8199,6 +8214,9 @@ heap2_redo(XLogRecPtr lsn, XLogRecord *record)
 			 * decoding.
 			 */
 			break;
+		case XLOG_HEAP2_REWRITE:
+			heap_xlog_logical_rewrite(lsn, record);
+			break;
 		default:
 			elog(PANIC, "heap2_redo: unknown op code %u", info);
 	}
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index c34ab98..11ba952 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -102,17 +102,34 @@
  */
 #include "postgres.h"
 
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "miscadmin.h"
+
 #include "access/heapam.h"
 #include "access/heapam_xlog.h"
 #include "access/rewriteheap.h"
 #include "access/transam.h"
 #include "access/tuptoaster.h"
+#include "access/xact.h"
+
+#include "catalog/catalog.h"
+
+#include "lib/ilist.h"
+
+#include "replication/logical.h"
+#include "replication/slot.h"
+
 #include "storage/bufmgr.h"
+#include "storage/fd.h"
 #include "storage/smgr.h"
+
 #include "utils/memutils.h"
 #include "utils/rel.h"
 #include "utils/tqual.h"
 
+#include "storage/procarray.h"
 
 /*
  * State associated with a rewrite operation. This is opaque to the user
@@ -120,21 +137,28 @@
  */
 typedef struct RewriteStateData
 {
+	Relation	rs_old_rel;		/* source heap */
 	Relation	rs_new_rel;		/* destination heap */
 	Page		rs_buffer;		/* page currently being built */
 	BlockNumber rs_blockno;		/* block where page will go */
 	bool		rs_buffer_valid;	/* T if any tuples in buffer */
 	bool		rs_use_wal;		/* must we WAL-log inserts? */
+	bool		rs_logical_rewrite; /* do we need to do logical rewriting */
 	TransactionId rs_oldest_xmin;		/* oldest xmin used by caller to
 										 * determine tuple visibility */
 	TransactionId rs_freeze_xid;/* Xid that will be used as freeze cutoff
 								 * point */
+	TransactionId rs_logical_xmin;	/* Xid that will be used as cutoff
+									 * point for logical rewrites */
 	MultiXactId rs_cutoff_multi;/* MultiXactId that will be used as cutoff
 								 * point for multixacts */
 	MemoryContext rs_cxt;		/* for hash tables and entries and tuples in
 								 * them */
+	XLogRecPtr	rs_begin_lsn;	/* XLogInsertLsn when starting the rewrite */
 	HTAB	   *rs_unresolved_tups;		/* unmatched A tuples */
 	HTAB	   *rs_old_new_tid_map;		/* unmatched B tuples */
+	HTAB	   *rs_logical_mappings;	/* logical remapping files */
+	uint32		rs_num_rewrite_mappings; /* # in memory mappings */
 }	RewriteStateData;
 
 /*
@@ -169,14 +193,45 @@ typedef struct
 
 typedef OldToNewMappingData *OldToNewMapping;
 
+/*
+ * In-Memory data for a xid that might need logical remapping entries
+ * to be logged.
+ */
+typedef struct RewriteMappingFile
+{
+	TransactionId		xid;		/* xid that might need to see the row */
+	int					vfd;		/* fd of mappings file */
+	off_t				off;		/* how far have we written yet */
+	uint32				num_mappings; /* number of in-memory mappings */
+	dlist_head			mappings;	/* list of in-memory mappings */
+	char				path[MAXPGPATH]; /* path, for error messages */
+} RewriteMappingFile;
+
+/*
+ * A single In-Memeory logical rewrite mapping, hanging of
+ * RewriteMappingFile->mappings.
+ */
+typedef struct RewriteMappingDataEntry
+{
+	LogicalRewriteMappingData map;	/* map between old and new location of
+									 * the tuple */
+	dlist_node	node;
+} RewriteMappingDataEntry;
+
 
 /* prototypes for internal functions */
 static void raw_heap_insert(RewriteState state, HeapTuple tup);
 
+/* internal logical remapping prototypes */
+static void logical_begin_heap_rewrite(RewriteState state);
+static void logical_rewrite_heap_tuple(RewriteState state, ItemPointerData old_tid, HeapTuple new_tuple);
+static void logical_end_heap_rewrite(RewriteState state);
+
 
 /*
  * Begin a rewrite of a table
  *
+ * old_heap		old, locked heap relation tuples will be read from
  * new_heap		new, locked heap relation to insert tuples to
  * oldest_xmin	xid used by the caller to determine which tuples are dead
  * freeze_xid	xid before which tuples will be frozen
@@ -187,7 +242,7 @@ static void raw_heap_insert(RewriteState state, HeapTuple tup);
  * to be used in subsequent calls to the other functions.
  */
 RewriteState
-begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin,
+begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xmin,
 				   TransactionId freeze_xid, MultiXactId cutoff_multi,
 				   bool use_wal)
 {
@@ -210,6 +265,7 @@ begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin,
 	/* Create and fill in the state struct */
 	state = palloc0(sizeof(RewriteStateData));
 
+	state->rs_old_rel = old_heap;
 	state->rs_new_rel = new_heap;
 	state->rs_buffer = (Page) palloc(BLCKSZ);
 	/* new_heap needn't be empty, just locked */
@@ -244,6 +300,8 @@ begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin,
 
 	MemoryContextSwitchTo(old_cxt);
 
+	logical_begin_heap_rewrite(state);
+
 	return state;
 }
 
@@ -301,6 +359,8 @@ end_heap_rewrite(RewriteState state)
 	if (RelationNeedsWAL(state->rs_new_rel))
 		heap_sync(state->rs_new_rel);
 
+	logical_end_heap_rewrite(state);
+
 	/* Deleting the context frees everything */
 	MemoryContextDelete(state->rs_cxt);
 }
@@ -429,6 +489,8 @@ rewrite_heap_tuple(RewriteState state,
 		raw_heap_insert(state, new_tuple);
 		new_tid = new_tuple->t_self;
 
+		logical_rewrite_heap_tuple(state, old_tid, new_tuple);
+
 		/*
 		 * If the tuple is the updated version of a row, and the prior version
 		 * wouldn't be DEAD yet, then we need to either resolve the prior
@@ -678,3 +740,539 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
 	if (heaptup != tup)
 		heap_freetuple(heaptup);
 }
+
+/* ------------------------------------------------------------------------
+ * Logical rewrite support
+ *
+ * When doing logical decoding - which relies on using cmin/cmax of catalog
+ * tuples, via xl_heap_new_cid records - heap rewrites have to log enough
+ * information to allow the decoding backend to updates its internal mapping
+ * of (relfilenode,ctid) => (cmin, cmax) to be correct for the rewritten heap.
+ *
+ * For that, every time we find a tuple that's been modified in a catalog
+ * relation within the xmin horizon of any decoding slot, we log a mapping
+ * from the old to the new location.
+ *
+ * To deal with rewrites that abort the filename of a mapping file contains
+ * the xid of the transaction performing the rewrite, which then can be
+ * checked before being read in.
+ *
+ * For efficiency we don't immediately spill every single map mapping for a
+ * row to disk but only do so in batches when we've collected several of them
+ * in memory or when end_heap_rewrite() has been called.
+ *
+ * Crash-Safety: This module diverts from the usual patterns of doing WAL
+ * since it cannot rely on checkpoint flushing out all buffers and thus
+ * waiting for exlusive locks on buffers. Usually the XLogInsert() covering
+ * buffer modifications is performed while the buffer(s) that are being
+ * modified are exlusively locked guaranteeing that both the WAL record and
+ * the modified heap are on either side of the checkpoint. But since the
+ * mapping files we log aren't in shared_buffers that interlock doesn't work.
+ *
+ * Instead we simply write the mapping files out to disk, *before* the
+ * XLogInsert() is performed. That guarantees that either the XLogInsert() is
+ * inserted after the checkpoint's redo pointer or that the checkpoint (via
+ * LogicalRewriteHeapCheckpoint()) has flushed the (partial) mapping file to
+ * disk. That leaves the tail end that has not yet been flushed open to
+ * corruption, which is solved by including the current offset in the
+ * xl_heap_rewrite_mapping records and truncating the mapping file to it
+ * during replay. Every time a rewrite is finished all generated mapping files
+ * are synced to disk.
+ *
+ * Note that if we were only concerned about crash safety we wouldn't have to
+ * deal with WAL logging at all - an fsync() at the end of a rewrite would be
+ * sufficient for crash safety. Any mapping that hasn't been safely flushed to
+ * disk has to be by an aborted (explicitly or via a crash) transaction and is
+ * ignored by virtue of the xid in it's name being subject to a
+ * TransactionDidCommit() check. But we want to support having standbys via
+ * physical replication, both for availability and to to do logical decoding
+ * there.
+ * ------------------------------------------------------------------------
+ */
+
+/*
+ * Do preparations for logging logical mappings during a rewrite if
+ * necessary. If we detect that we don't need to log anything we'll prevent
+ * any further action by the various logical rewrite functions.
+ */
+static void
+logical_begin_heap_rewrite(RewriteState state)
+{
+	HASHCTL		hash_ctl;
+	TransactionId logical_xmin;
+
+	/*
+	 * We only need to persist these mappings if the rewritten table can be
+	 * accessed during logical decoding, if not, we can skip doing any
+	 * additional work.
+	 */
+	state->rs_logical_rewrite =
+		RelationIsAccessibleInLogicalDecoding(state->rs_old_rel);
+
+	if (!state->rs_logical_rewrite)
+		return;
+
+	Assert(ReplicationSlotCtl != NULL);
+
+	ProcArrayGetReplicationSlotXmin(NULL, &logical_xmin);
+
+	/*
+	 * If there are no logical slots in progress we don't need to do anything,
+	 * there cannot be any remappings for relevant rows yet. The relation's
+	 * lock protects us against races.
+	 */
+	if (logical_xmin == InvalidTransactionId)
+	{
+		state->rs_logical_rewrite = false;
+		return;
+	}
+
+	state->rs_logical_xmin = logical_xmin;
+	state->rs_begin_lsn = GetXLogInsertRecPtr();
+	state->rs_num_rewrite_mappings = 0;
+
+	memset(&hash_ctl, 0, sizeof(hash_ctl));
+	hash_ctl.keysize = sizeof(TransactionId);
+	hash_ctl.entrysize = sizeof(RewriteMappingFile);
+	hash_ctl.hcxt = state->rs_cxt;
+	hash_ctl.hash = tag_hash;
+
+	state->rs_logical_mappings =
+		hash_create("Logical rewrite mapping",
+					128,		/* arbitrary initial size */
+					&hash_ctl,
+					HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+}
+
+/*
+ * Flush all logical in-memory mappings to disk, but don't fsync them yet.
+ */
+static void
+logical_heap_rewrite_flush_mappings(RewriteState state)
+{
+	HASH_SEQ_STATUS seq_status;
+	RewriteMappingFile *src;
+	dlist_mutable_iter iter;
+
+	Assert(state->rs_logical_rewrite);
+
+	/* no logical rewrite in progress, no need to iterate over mappings */
+	if (state->rs_num_rewrite_mappings == 0)
+		return;
+
+	elog(DEBUG1, "flushing %u logical rewrite mapping entries",
+		 state->rs_num_rewrite_mappings);
+
+	hash_seq_init(&seq_status, state->rs_logical_mappings);
+	while ((src = (RewriteMappingFile *) hash_seq_search(&seq_status)) != NULL)
+	{
+		XLogRecData		rdata[2];
+		char		   *waldata;
+		char		   *waldata_start;
+		xl_heap_rewrite_mapping xlrec;
+		Oid				dboid;
+		uint32			len;
+		int				written;
+
+		/* this file hasn't got any new mappings */
+		if (src->num_mappings == 0)
+			continue;
+
+		if (state->rs_old_rel->rd_rel->relisshared)
+			dboid = InvalidOid;
+		else
+			dboid = MyDatabaseId;
+
+		xlrec.num_mappings = src->num_mappings;
+		xlrec.mapped_rel = RelationGetRelid(state->rs_old_rel);
+		xlrec.mapped_xid = src->xid;
+		xlrec.mapped_db = dboid;
+		xlrec.offset = src->off;
+		xlrec.start_lsn = state->rs_begin_lsn;
+
+		rdata[0].data = (char *) (&xlrec);
+		rdata[0].len = sizeof(xlrec);
+		rdata[0].buffer = InvalidBuffer;
+		rdata[0].next = &(rdata[1]);
+
+		/* write all mappings consecutively */
+		len = src->num_mappings * sizeof(LogicalRewriteMappingData);
+		waldata = palloc(len);
+		waldata_start = waldata;
+
+		/*
+		 * collect data we need to write out, but don't modify ondisk data yet
+		 */
+		dlist_foreach_modify(iter, &src->mappings)
+		{
+			RewriteMappingDataEntry *pmap;
+
+			pmap = dlist_container(RewriteMappingDataEntry, node, iter.cur);
+
+			memcpy(waldata, &pmap->map, sizeof(pmap->map));
+			waldata += sizeof(pmap->map);
+
+			/* remove from the list and free */
+			dlist_delete(&pmap->node);
+			pfree(pmap);
+
+			/* update bookkeeping */
+			state->rs_num_rewrite_mappings--;
+			src->num_mappings--;
+		}
+
+		/*
+		 * Note that we deviate from the usual WAL coding practices here,
+		 * check the above "Logical rewrite support" comment for reasoning.
+		 */
+		written = FileWrite(src->vfd, waldata_start, len);
+		if (written != len)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not write to file \"%s\", wrote %d of %d: %m", src->path,
+							written, len)));
+		src->off += len;
+
+		Assert(src->num_mappings == 0);
+
+		rdata[1].data = waldata_start;
+		rdata[1].len = len;
+		rdata[1].buffer = InvalidBuffer;
+		rdata[1].next = NULL;
+
+		/* write xlog record */
+		XLogInsert(RM_HEAP2_ID, XLOG_HEAP2_REWRITE, rdata);
+
+	}
+	Assert(state->rs_num_rewrite_mappings == 0);
+}
+
+/*
+ * Logical remapping part of end_heap_rewrite().
+ */
+static void
+logical_end_heap_rewrite(RewriteState state)
+{
+	HASH_SEQ_STATUS seq_status;
+	RewriteMappingFile *src;
+
+	/* done, no logical rewrite in progress */
+	if (!state->rs_logical_rewrite)
+		return;
+
+	/* writeout remaining in-memory entries */
+	if (state->rs_num_rewrite_mappings > 0 )
+		logical_heap_rewrite_flush_mappings(state);
+
+	/* Iterate over all mappings we have written and fsync the files. */
+	hash_seq_init(&seq_status, state->rs_logical_mappings);
+	while ((src = (RewriteMappingFile *) hash_seq_search(&seq_status)) != NULL)
+	{
+		if(FileSync(src->vfd) != 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not fsync file \"%s\": %m", src->path)));
+		FileClose(src->vfd);
+	}
+	/* memory context cleanup will deal with the rest */
+}
+
+/*
+ * Log a single (old->new) mapping for 'xid'.
+ */
+static void
+logical_rewrite_log_mapping(RewriteState state, TransactionId xid,
+							LogicalRewriteMappingData *map)
+{
+	RewriteMappingFile		   *src;
+	RewriteMappingDataEntry	   *pmap;
+	Oid							relid;
+	bool						found;
+
+	relid = RelationGetRelid(state->rs_old_rel);
+
+	/* look for existing mappings for this 'mapped' xid */
+	src = hash_search(state->rs_logical_mappings, &xid,
+					  HASH_ENTER, &found);
+
+	/*
+	 * We haven't yet had the need to map anything for this xid, create
+	 * per-xid data structures.
+	 */
+	if (!found)
+	{
+		char		path[MAXPGPATH];
+		Oid			dboid;
+
+		if (state->rs_old_rel->rd_rel->relisshared)
+			dboid = InvalidOid;
+		else
+			dboid = MyDatabaseId;
+
+		snprintf(path, MAXPGPATH,
+				 "pg_llog/mappings/" LOGICAL_REWRITE_FORMAT,
+				 dboid, relid,
+				 state->rs_begin_lsn,
+				 xid, GetCurrentTransactionId());
+
+		dlist_init(&src->mappings);
+		src->num_mappings = 0;
+		src->off = 0;
+		memcpy(src->path, path, sizeof(path));
+		src->vfd = PathNameOpenFile(path,
+									O_CREAT | O_EXCL | O_WRONLY | PG_BINARY,
+									S_IRUSR | S_IWUSR);
+		if (src->vfd < 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not create file \"%s\": %m",	path)));
+	}
+
+	pmap = MemoryContextAlloc(state->rs_cxt,
+							  sizeof(RewriteMappingDataEntry));
+	memcpy(&pmap->map, map, sizeof(LogicalRewriteMappingData));
+	dlist_push_tail(&src->mappings, &pmap->node);
+	src->num_mappings++;
+	state->rs_num_rewrite_mappings++;
+
+	/*
+	 * Write out buffer every time we've too many in-memory entries across all
+	 * mapping files.
+	 */
+	if (state->rs_num_rewrite_mappings >= 1000 /* arbitrary number */)
+		logical_heap_rewrite_flush_mappings(state);
+}
+
+/*
+ * Perform logical remapping for a tuple that's mapped from old_tid to
+ * new_tuple->t_self by rewrite_heap_tuple() iff necessary for the tuple.
+ */
+static void
+logical_rewrite_heap_tuple(RewriteState state, ItemPointerData old_tid,
+						   HeapTuple new_tuple)
+{
+	ItemPointerData new_tid = new_tuple->t_self;
+	TransactionId	cutoff = state->rs_logical_xmin;
+	TransactionId	xmin;
+	TransactionId	xmax;
+	bool			do_log_xmin = false;
+	bool			do_log_xmax = false;
+	LogicalRewriteMappingData map;
+
+	/* no logical rewrite in progress, we don't need to log anything */
+	if (!state->rs_logical_rewrite)
+		return;
+
+	xmin = HeapTupleHeaderGetXmin(new_tuple->t_data);
+	/* use *GetUpdateXid to correctly deal with multixacts */
+	xmax = HeapTupleHeaderGetUpdateXid(new_tuple->t_data);
+
+	/*
+	 * Log the mapping iff the tuple has been created recently.
+	 */
+	if (TransactionIdIsNormal(xmin) && !TransactionIdPrecedes(xmin, cutoff))
+		do_log_xmin = true;
+
+	if (!TransactionIdIsNormal(xmax))
+	{
+		/*
+		 * no xmax is set, can't have any permanent ones, so this check is
+		 * sufficient
+		 */
+	}
+	else if (HEAP_XMAX_IS_LOCKED_ONLY(new_tuple->t_data->t_infomask))
+	{
+		/* only locked, we don't care */
+	}
+	else if (!TransactionIdPrecedes(xmax, cutoff))
+	{
+		/* tuple has been deleted recently, log */
+		do_log_xmax = true;
+	}
+
+	/* if neither needs to be logged, we're done */
+	if (!do_log_xmin && !do_log_xmax)
+		return;
+
+	/* fill out mapping information */
+	map.old_node = state->rs_old_rel->rd_node;
+	map.old_tid = old_tid;
+	map.new_node = state->rs_new_rel->rd_node;
+	map.new_tid = new_tid;
+
+	/* ---
+	 * Now persist the mapping for the individual xids that are affected. We
+	 * need to log for both xmin and xmax if they aren't the same transaction
+	 * since the mapping files are per "affected" xid.
+	 * We don't muster all that much effort detecting whether xmin and xmax
+	 * are actually the same transaction, we just check whether the xid is the
+	 * same disregarding subtransactions. Logging too much is relatively
+	 * harmless and we could never do the check fully since subtransaction
+	 * data is thrown away during restarts.
+	 * ---
+	 */
+	if (do_log_xmin)
+		logical_rewrite_log_mapping(state, xmin, &map);
+	/* separately log mapping for xmax unless it'd be redundant */
+	if (do_log_xmax && !TransactionIdEquals(xmin, xmax))
+		logical_rewrite_log_mapping(state, xmax, &map);
+}
+
+/*
+ * Replay XLOG_HEAP2_REWRITE records
+ */
+void
+heap_xlog_logical_rewrite(XLogRecPtr lsn, XLogRecord *r)
+{
+	char		path[MAXPGPATH];
+	int			fd;
+	xl_heap_rewrite_mapping *xlrec;
+	uint32		len;
+	char	   *data;
+
+	xlrec = (xl_heap_rewrite_mapping *) XLogRecGetData(r);
+
+	snprintf(path, MAXPGPATH,
+			 "pg_llog/mappings/" LOGICAL_REWRITE_FORMAT,
+			 xlrec->mapped_db, xlrec->mapped_rel, xlrec->start_lsn,
+			 xlrec->mapped_xid, r->xl_xid);
+
+	fd = OpenTransientFile(path,
+						   O_CREAT | O_WRONLY | PG_BINARY,
+						   S_IRUSR | S_IWUSR);
+	if (fd < 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not create file \"%s\": %m",	path)));
+	/*
+	 * Truncate all data that's not guaranteed to have been safely fsynced (by
+	 * previous record or by the last checkpoint).
+	 */
+	if (ftruncate(fd, xlrec->offset) != 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not truncate file \"%s\" to %u: %m",
+						path, (uint32) xlrec->offset)));
+
+	/* now seek to the position we want to write our data to */
+	if (lseek(fd, xlrec->offset, SEEK_SET) != xlrec->offset)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not seek to the end of file \"%s\": %m",
+						path)));
+
+	data = XLogRecGetData(r) + sizeof(*xlrec);
+
+	len = xlrec->num_mappings * sizeof(LogicalRewriteMappingData);
+
+	/* write out tail end of mapping file (again) */
+	if (write(fd, data, len) != len)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not write to file \"%s\": %m", path)));
+	/*
+	 * Now fsync all previously written data. We could improve things and only
+	 * do this for the last write to a file, but the required bookkeeping
+	 * doesn't seem worth the trouble.
+	 */
+	if (pg_fsync(fd) != 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not fsync file \"%s\": %m", path)));
+
+	CloseTransientFile(fd);
+}
+
+/* ---
+ * Perform a checkpoint for logical rewrite mappings
+ *
+ * This serves two tasks:
+ * 1) Remove all mappings not needed anymore based on the logical restart LSN
+ * 2) Flush all remaining mappings to disk, so that replay after a checkpoint
+ *	  only has to deal with the parts of a mapping that have been written out
+ *	  after the checkpoint started.
+ * ---
+ */
+void
+CheckpointLogicalRewriteHeap(void)
+{
+	XLogRecPtr	cutoff;
+	XLogRecPtr	redo;
+	DIR		   *mappings_dir;
+	struct dirent *mapping_de;
+	char		path[MAXPGPATH];
+
+	/*
+	 * We start of with a minimum of the last redo pointer. No new decoding
+	 * slot will start before that, so that's a safe upper bound for removal.
+	 */
+	redo = GetRedoRecPtr();
+
+	/* now check for the restart ptrs from existing slots */
+	cutoff = ComputeLogicalRestartLSN();
+
+	/* don't start earlier than the restart lsn */
+	if (cutoff != InvalidXLogRecPtr && redo < cutoff)
+		cutoff = redo;
+
+	mappings_dir = AllocateDir("pg_llog/mappings");
+	while ((mapping_de = ReadDir(mappings_dir, "pg_llog/mappings")) != NULL)
+	{
+		struct stat	statbuf;
+		Oid			dboid;
+		Oid			relid;
+		XLogRecPtr	lsn;
+		TransactionId rewrite_xid;
+		TransactionId create_xid;
+
+		if (strcmp(mapping_de->d_name, ".") == 0 ||
+			strcmp(mapping_de->d_name, "..") == 0)
+			continue;
+
+		snprintf(path, MAXPGPATH, "pg_llog/mappings/%s", mapping_de->d_name);
+		if (lstat(path, &statbuf) == 0 && !S_ISREG(statbuf.st_mode))
+			continue;
+
+		/* Skip over files that cannot be ours. */
+		if (strncmp(mapping_de->d_name, "map-", 4) != 0)
+			continue;
+
+		if (sscanf(mapping_de->d_name, LOGICAL_REWRITE_FORMAT,
+				   &dboid, &relid, &lsn, &rewrite_xid, &create_xid) != 5)
+			elog(ERROR,"could not parse filename \"%s\"", mapping_de->d_name);
+
+		if (lsn < cutoff || cutoff == InvalidXLogRecPtr)
+		{
+			elog(DEBUG1, "removing logical rewrite file \"%s\"", path);
+			if (unlink(path) < 0)
+				ereport(ERROR,
+						(errcode_for_file_access(),
+						 errmsg("could not unlink file \"%s\": %m", path)));
+		}
+		else
+		{
+			int		fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+
+			/*
+			 * The file cannot vanish due to concurrency since this function
+			 * is the only one removing logical mappings and it's run while
+			 * CheckpointLock is held exclusively.
+			 */
+			if (fd < 0)
+				ereport(ERROR,
+						(errcode_for_file_access(),
+						 errmsg("could not open file \"%s\": %m", path)));
+			/*
+			 * We could try to avoid fsyncing files that either haven't
+			 * changed or have only been created since the checkpoint's start,
+			 * but it's currently not deemed worth the effort.
+			 */
+			else if (pg_fsync(fd) != 0)
+				ereport(ERROR,
+						(errcode_for_file_access(),
+						 errmsg("could not fsync file \"%s\": %m", path)));
+			CloseTransientFile(fd);
+		}
+	}
+	FreeDir(mappings_dir);
+}
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 1aba2f0..559a7c8 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -67,7 +67,10 @@
 
 #include "access/relscan.h"
 #include "access/transam.h"
+#include "access/xlog.h"
+
 #include "catalog/index.h"
+#include "catalog/catalog.h"
 #include "pgstat.h"
 #include "storage/bufmgr.h"
 #include "storage/lmgr.h"
@@ -520,8 +523,15 @@ index_fetch_heap(IndexScanDesc scan)
 		 * Prune page, but only if we weren't already on this page
 		 */
 		if (prev_buf != scan->xs_cbuf)
-			heap_page_prune_opt(scan->heapRelation, scan->xs_cbuf,
-								RecentGlobalXmin);
+		{
+			if (IsSystemRelation(scan->heapRelation)
+				|| RelationIsAccessibleInLogicalDecoding(scan->heapRelation))
+				heap_page_prune_opt(scan->heapRelation, scan->xs_cbuf,
+									RecentGlobalXmin);
+			else
+				heap_page_prune_opt(scan->heapRelation, scan->xs_cbuf,
+									RecentGlobalDataXmin);
+		}
 	}
 
 	/* Obtain share-lock on the buffer so we can examine visibility */
diff --git a/src/backend/access/rmgrdesc/heapdesc.c b/src/backend/access/rmgrdesc/heapdesc.c
index 89ba09a..c8a6166 100644
--- a/src/backend/access/rmgrdesc/heapdesc.c
+++ b/src/backend/access/rmgrdesc/heapdesc.c
@@ -149,6 +149,10 @@ heap2_desc(StringInfo buf, uint8 xl_info, char *rec)
 						 xlrec->node.relNode, xlrec->block,
 						 xlrec->cutoff_xid, xlrec->ntuples);
 	}
+	else if (info == XLOG_HEAP2_REWRITE)
+	{
+		appendStringInfoString(buf, "heap rewrite:");
+	}
 	else if (info == XLOG_HEAP2_CLEANUP_INFO)
 	{
 		xl_heap_cleanup_info *xlrec = (xl_heap_cleanup_info *) rec;
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 7f63185..73681a5 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -23,6 +23,7 @@
 
 #include "access/clog.h"
 #include "access/multixact.h"
+#include "access/rewriteheap.h"
 #include "access/subtrans.h"
 #include "access/timeline.h"
 #include "access/transam.h"
@@ -39,7 +40,9 @@
 #include "pgstat.h"
 #include "postmaster/bgwriter.h"
 #include "postmaster/startup.h"
+#include "replication/logical.h"
 #include "replication/slot.h"
+#include "replication/snapbuild.h"
 #include "replication/walreceiver.h"
 #include "replication/walsender.h"
 #include "storage/barrier.h"
@@ -6551,6 +6554,14 @@ StartupXLOG(void)
 	XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
 	XLogCtl->ckptXid = checkPoint.nextXid;
 
+
+	/*
+	 * Startup logical state, needs to be setup now so we have proper data
+	 * during restore.
+	 */
+	StartupReplicationSlots(checkPoint.redo);
+	StartupReorderBuffer();
+
 	/*
 	 * Initialize replication slots, before there's a chance to remove
 	 * required resources.
@@ -8588,7 +8599,7 @@ CreateCheckPoint(int flags)
 	 * StartupSUBTRANS hasn't been called yet.
 	 */
 	if (!RecoveryInProgress())
-		TruncateSUBTRANS(GetOldestXmin(true, false));
+		TruncateSUBTRANS(GetOldestXmin(true, false, true));
 
 	/* Real work is done, but log and update stats before releasing lock. */
 	LogCheckpointEnd(false);
@@ -8673,6 +8684,8 @@ CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
 	CheckPointPredicate();
 	CheckPointRelationMap();
 	CheckPointReplicationSlots();
+	CheckPointSnapBuild();
+	CheckpointLogicalRewriteHeap();
 	CheckPointBuffers(flags);	/* performs all required fsyncs */
 	/* We deliberately delay 2PC checkpointing as long as possible */
 	CheckPointTwoPhase(checkPointRedo);
@@ -8964,7 +8977,7 @@ CreateRestartPoint(int flags)
 	 * this because StartupSUBTRANS hasn't been called yet.
 	 */
 	if (EnableHotStandby)
-		TruncateSUBTRANS(GetOldestXmin(true, false));
+		TruncateSUBTRANS(GetOldestXmin(true, true, true));
 
 	/* Real work is done, but log and update before releasing lock. */
 	LogCheckpointEnd(true);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 8eae43d..4d3ef66 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2158,9 +2158,19 @@ IndexBuildHeapScan(Relation heapRelation,
 	}
 	else
 	{
+		/*
+		 * We can ignore a) pegged xmins b) shared relations if we don't scan
+		 * something acting as a catalog.
+		 */
+		bool include_systables =
+			IsSystemRelation(heapRelation) ||
+			RelationIsAccessibleInLogicalDecoding(heapRelation);
+
 		snapshot = SnapshotAny;
 		/* okay to ignore lazy VACUUMs here */
-		OldestXmin = GetOldestXmin(heapRelation->rd_rel->relisshared, true);
+		OldestXmin = GetOldestXmin(heapRelation->rd_rel->relisshared,
+								   true,
+								   include_systables);
 	}
 
 	scan = heap_beginscan_strat(heapRelation,	/* relation */
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index f02efec..494fc54 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -616,11 +616,13 @@ CREATE VIEW pg_stat_replication AS
 CREATE VIEW pg_replication_slots AS
     SELECT
             L.slot_name,
+            L.plugin,
             L.slot_type,
             L.datoid,
             D.datname AS database,
             L.active,
             L.xmin,
+            L.catalog_xmin,
             L.restart_lsn
     FROM pg_get_replication_slots() AS L
             LEFT JOIN pg_database D ON (L.datoid = D.oid);
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index e7fcb55..8d70cf7 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -22,6 +22,7 @@
 #include "access/tuptoaster.h"
 #include "access/visibilitymap.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_collation.h"
@@ -1081,7 +1082,9 @@ acquire_sample_rows(Relation onerel, int elevel,
 	totalblocks = RelationGetNumberOfBlocks(onerel);
 
 	/* Need a cutoff xmin for HeapTupleSatisfiesVacuum */
-	OldestXmin = GetOldestXmin(onerel->rd_rel->relisshared, true);
+	OldestXmin = GetOldestXmin(onerel->rd_rel->relisshared, true,
+							   IsSystemRelation(onerel) ||
+							   RelationIsAccessibleInLogicalDecoding(onerel));
 
 	/* Prepare for sampling block numbers */
 	BlockSampler_Init(&bs, totalblocks, targrows);
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 14a5e5a..6a1565e 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -850,9 +850,11 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
 	 * Since we're going to rewrite the whole table anyway, there's no reason
 	 * not to be aggressive about this.
 	 */
-	vacuum_set_xid_limits(0, 0, OldHeap->rd_rel->relisshared,
-						  &OldestXmin, &FreezeXid, NULL, &MultiXactCutoff,
-						  NULL);
+	vacuum_set_xid_limits(0, 0,
+						  OldHeap->rd_rel->relisshared,
+						  IsSystemRelation(OldHeap)
+						  || RelationIsAccessibleInLogicalDecoding(OldHeap),
+						  &OldestXmin, &FreezeXid, NULL, &MultiXactCutoff, NULL);
 
 	/*
 	 * FreezeXid will become the table's new relfrozenxid, and that mustn't go
@@ -869,7 +871,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
 	is_system_catalog = IsSystemRelation(OldHeap);
 
 	/* Initialize the rewrite operation */
-	rwstate = begin_heap_rewrite(NewHeap, OldestXmin, FreezeXid,
+	rwstate = begin_heap_rewrite(OldHeap, NewHeap, OldestXmin, FreezeXid,
 								 MultiXactCutoff, use_wal);
 
 	/*
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 5d540aa..8939df1 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -45,6 +45,7 @@
 #include "miscadmin.h"
 #include "pgstat.h"
 #include "postmaster/bgwriter.h"
+#include "replication/logical.h"
 #include "storage/copydir.h"
 #include "storage/fd.h"
 #include "storage/lmgr.h"
@@ -750,6 +751,7 @@ dropdb(const char *dbname, bool missing_ok)
 	HeapTuple	tup;
 	int			notherbackends;
 	int			npreparedxacts;
+	int			nslots, nslots_active;
 
 	/*
 	 * Look up the target database's OID, and get exclusive lock on it. We
@@ -807,6 +809,20 @@ dropdb(const char *dbname, bool missing_ok)
 				 errmsg("cannot drop the currently open database")));
 
 	/*
+	 * Check whether there are, possibly unconnected, logical
+	 * slots that refer to the to-be-dropped database. The database
+	 * lock we are holding prevents the creation of new slots using
+	 * the database.
+	 */
+	if (LogicalDecodingCountDBSlots(db_id, &nslots, &nslots_active))
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_IN_USE),
+				 errmsg("database \"%s\" is used in a logical decoding slot",
+						dbname),
+				 errdetail("There are %d slot(s), %d of them active",
+						   nslots, nslots_active)));
+
+	/*
 	 * Check for other backends in the target database.  (Because we hold the
 	 * database lock, no new ones can start after this.)
 	 *
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 3455a0b..630a2ac 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -399,6 +399,7 @@ void
 vacuum_set_xid_limits(int freeze_min_age,
 					  int freeze_table_age,
 					  bool sharedRel,
+					  bool catalogRel,
 					  TransactionId *oldestXmin,
 					  TransactionId *freezeLimit,
 					  TransactionId *xidFullScanLimit,
@@ -419,7 +420,7 @@ vacuum_set_xid_limits(int freeze_min_age,
 	 * working on a particular table at any time, and that each vacuum is
 	 * always an independent transaction.
 	 */
-	*oldestXmin = GetOldestXmin(sharedRel, true);
+	*oldestXmin = GetOldestXmin(sharedRel, true, catalogRel);
 
 	Assert(TransactionIdIsNormal(*oldestXmin));
 
@@ -748,7 +749,7 @@ vac_update_datfrozenxid(void)
 	 * committed pg_class entries for new tables; see AddNewRelationTuple().
 	 * So we cannot produce a wrong minimum by starting with this.
 	 */
-	newFrozenXid = GetOldestXmin(true, true);
+	newFrozenXid = GetOldestXmin(true, true, true);
 
 	/*
 	 * Similarly, initialize the MultiXact "min" with the value that would be
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 75e5f15..8534eac 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -44,6 +44,7 @@
 #include "access/multixact.h"
 #include "access/transam.h"
 #include "access/visibilitymap.h"
+#include "catalog/catalog.h"
 #include "catalog/storage.h"
 #include "commands/dbcommands.h"
 #include "commands/vacuum.h"
@@ -206,6 +207,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
 
 	vacuum_set_xid_limits(vacstmt->freeze_min_age, vacstmt->freeze_table_age,
 						  onerel->rd_rel->relisshared,
+						  IsSystemRelation(onerel)
+						  || RelationIsAccessibleInLogicalDecoding(onerel),
 						  &OldestXmin, &FreezeLimit, &xidFullScanLimit,
 						  &MultiXactCutoff, &mxactFullScanLimit);
 
diff --git a/src/backend/replication/Makefile b/src/backend/replication/Makefile
index 7941cb8..6f17b08 100644
--- a/src/backend/replication/Makefile
+++ b/src/backend/replication/Makefile
@@ -17,6 +17,8 @@ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
 OBJS = walsender.o walreceiverfuncs.o walreceiver.o basebackup.o \
 	repl_gram.o slot.o slotfuncs.o syncrep.o
 
+SUBDIRS = logical
+
 include $(top_srcdir)/src/backend/common.mk
 
 # repl_scanner is compiled as part of repl_gram
diff --git a/src/backend/replication/logical/Makefile b/src/backend/replication/logical/Makefile
new file mode 100644
index 0000000..310a45c
--- /dev/null
+++ b/src/backend/replication/logical/Makefile
@@ -0,0 +1,19 @@
+#-------------------------------------------------------------------------
+#
+# Makefile--
+#    Makefile for src/backend/replication/logical
+#
+# IDENTIFICATION
+#    src/backend/replication/logical/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/backend/replication/logical
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
+
+OBJS = decode.o logical.o logicalfuncs.o reorderbuffer.o snapbuild.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
new file mode 100644
index 0000000..3f9fc17
--- /dev/null
+++ b/src/backend/replication/logical/decode.c
@@ -0,0 +1,801 @@
+/* -------------------------------------------------------------------------
+ *
+ * decode.c
+ *		This module decodes WAL records read using xlogreader.h's APIs for the
+ *		purpose of changeset extraction by passing information to the
+ *		reorderbuffer module (containing the actual changes) and to the
+ *		snapbuild module to build a fitting catalog snapshot (to be able to
+ *		properly decode the changes in the reorderbuffer).
+ *
+ * NOTE:
+ *		This basically tries to handle all low level xlog stuff for
+ *      reorderbuffer.c and snapbuild.c. There's some minor leakage where a
+ *      specific record's struct is used to pass data along, but those just
+ *      happen to contain the right amount of data in a convenient
+ *      format. There isn't and shouldn't be much intelligence about the
+ *      contents of records in here xexcept turning them into a more usable
+ *      format.
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  src/backend/replication/logical/decode.c
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "access/heapam_xlog.h"
+#include "access/transam.h"
+#include "access/xact.h"
+#include "access/xlog_internal.h"
+#include "access/xlogreader.h"
+
+#include "catalog/pg_control.h"
+
+#include "replication/decode.h"
+#include "replication/logical.h"
+#include "replication/reorderbuffer.h"
+#include "replication/snapbuild.h"
+
+#include "storage/standby.h"
+
+typedef struct XLogRecordBuffer
+{
+	XLogRecPtr origptr;
+	XLogRecPtr endptr;
+	XLogRecord record;
+	char *record_data;
+} XLogRecordBuffer;
+
+/* RMGR Handlers */
+static void DecodeXLogOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+static void DecodeHeapOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+static void DecodeHeap2Op(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+static void DecodeXactOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+static void DecodeStandbyOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+
+/* individual record(group)'s handlers */
+static void DecodeInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+static void DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+static void DecodeDelete(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+static void DecodeMultiInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+static void DecodeCommit(LogicalDecodingContext *ctx, XLogRecordBuffer *buf,
+						 TransactionId xid, TimestampTz commit_time,
+						 int nsubxacts, TransactionId *sub_xids,
+						 int ninval_msgs, SharedInvalidationMessage *msg);
+static void DecodeAbort(LogicalDecodingContext *ctx, XLogRecPtr lsn,
+			TransactionId xid, TransactionId *sub_xids, int nsubxacts);
+
+/* common function to decode tuples */
+static void DecodeXLogTuple(char *data, Size len, ReorderBufferTupleBuf *tup);
+
+/*
+ * Take every XLogReadRecord()ed record and perform the actions required to
+ * decode it using the output plugin already setup in the logical decoding
+ * context.
+ */
+void
+LogicalDecodingProcessRecord(LogicalDecodingContext *ctx, XLogRecord *record)
+{
+	XLogRecordBuffer buf;
+
+	buf.origptr = ctx->reader->ReadRecPtr;
+	buf.endptr = ctx->reader->EndRecPtr;
+	buf.record = *record;
+	buf.record_data = XLogRecGetData(record);
+
+	/* cast so we get a warning when new rmgrs are added */
+	switch ((RmgrIds) buf.record.xl_rmid)
+	{
+		/*
+		 * Rmgrs we care about for logical decoding. Add new rmgrs in
+		 * rmgrlist.h's order.
+		 */
+		case RM_XLOG_ID:
+			DecodeXLogOp(ctx, &buf);
+			break;
+
+		case RM_XACT_ID:
+			DecodeXactOp(ctx, &buf);
+			break;
+
+		case RM_STANDBY_ID:
+			DecodeStandbyOp(ctx, &buf);
+			break;
+
+		case RM_HEAP2_ID:
+			DecodeHeap2Op(ctx, &buf);
+			break;
+
+		case RM_HEAP_ID:
+			DecodeHeapOp(ctx, &buf);
+			break;
+
+		/*
+		 * Rmgrs irrelevant for changeset extraction, they describe stuff not
+		 * represented in logical decoding. Add new rmgrs in rmgrlist.h's
+		 * order.
+		 */
+		case RM_SMGR_ID:
+		case RM_CLOG_ID:
+		case RM_DBASE_ID:
+		case RM_TBLSPC_ID:
+		case RM_MULTIXACT_ID:
+		case RM_RELMAP_ID:
+		case RM_BTREE_ID:
+		case RM_HASH_ID:
+		case RM_GIN_ID:
+		case RM_GIST_ID:
+		case RM_SEQ_ID:
+		case RM_SPGIST_ID:
+			break;
+		case RM_NEXT_ID:
+			elog(ERROR, "unexpected RM_NEXT_ID rmgr_id: %u", (RmgrIds) buf.record.xl_rmid);
+	}
+}
+
+/*
+ * Handle rmgr XLOG_ID records for DecodeRecordIntoReorderBuffer().
+ */
+static void
+DecodeXLogOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	SnapBuild  *builder = ctx->snapshot_builder;
+	uint8		info = buf->record.xl_info & ~XLR_INFO_MASK;
+
+	switch (info)
+	{
+		/* this is also used in END_OF_RECOVERY checkpoints */
+		case XLOG_CHECKPOINT_SHUTDOWN:
+		case XLOG_END_OF_RECOVERY:
+			SnapBuildSerializationPoint(builder, buf->origptr);
+
+			break;
+		case XLOG_CHECKPOINT_ONLINE:
+			/*
+			 * a RUNNING_XACTS record will have been logged near to this, we
+			 * can restart from there.
+			 */
+			break;
+		case XLOG_NOOP:
+		case XLOG_NEXTOID:
+		case XLOG_SWITCH:
+		case XLOG_BACKUP_END:
+		case XLOG_PARAMETER_CHANGE:
+		case XLOG_RESTORE_POINT:
+		case XLOG_FPW_CHANGE:
+		case XLOG_FPI:
+			break;
+		default:
+			elog(ERROR, "unexpected RM_XLOG_ID record type: %u", info);
+	}
+}
+
+/*
+ * Handle rmgr XACT_ID records for DecodeRecordIntoReorderBuffer().
+ */
+static void
+DecodeXactOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	SnapBuild	   *builder = ctx->snapshot_builder;
+	ReorderBuffer  *reorder = ctx->reorder;
+	XLogRecord	   *r = &buf->record;
+	uint8		info = r->xl_info & ~XLR_INFO_MASK;
+
+	/* no point in doing anything yet, data could not be decoded anyway */
+	if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT)
+		return;
+
+	switch (info)
+	{
+		case XLOG_XACT_COMMIT:
+			{
+				xl_xact_commit *xlrec;
+				TransactionId *subxacts = NULL;
+				SharedInvalidationMessage *invals = NULL;
+
+				xlrec = (xl_xact_commit *) buf->record_data;
+
+				subxacts = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
+				invals = (SharedInvalidationMessage *) &(subxacts[xlrec->nsubxacts]);
+
+				/* FIXME: skip if wrong db? */
+
+				DecodeCommit(ctx, buf, r->xl_xid, xlrec->xact_time,
+							 xlrec->nsubxacts, subxacts,
+							 xlrec->nmsgs, invals);
+
+				break;
+			}
+		case XLOG_XACT_COMMIT_PREPARED:
+			{
+				xl_xact_commit_prepared *prec;
+				xl_xact_commit *xlrec;
+				TransactionId *subxacts;
+				SharedInvalidationMessage *invals = NULL;
+
+				/* Prepared commits contain a normal commit record... */
+				prec = (xl_xact_commit_prepared *) buf->record_data;
+				xlrec = &prec->crec;
+
+				subxacts = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
+				invals = (SharedInvalidationMessage *) &(subxacts[xlrec->nsubxacts]);
+
+				/* FIXME: skip if wrong db? */
+
+				DecodeCommit(ctx, buf, r->xl_xid,
+							 xlrec->xact_time,
+							 xlrec->nsubxacts, subxacts,
+							 xlrec->nmsgs, invals);
+
+				break;
+			}
+		case XLOG_XACT_COMMIT_COMPACT:
+			{
+				xl_xact_commit_compact *xlrec;
+
+				xlrec = (xl_xact_commit_compact *) buf->record_data;
+
+				/* FIXME: skip if wrong db? */
+
+				DecodeCommit(ctx, buf, r->xl_xid, xlrec->xact_time,
+							 xlrec->nsubxacts, xlrec->subxacts,
+							 0, NULL);
+				break;
+			}
+		case XLOG_XACT_ABORT:
+			{
+				xl_xact_abort *xlrec;
+				TransactionId *sub_xids;
+
+				xlrec = (xl_xact_abort *) buf->record_data;
+
+				sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
+
+				DecodeAbort(ctx, buf->origptr, r->xl_xid,
+							sub_xids, xlrec->nsubxacts);
+				break;
+			}
+		case XLOG_XACT_ABORT_PREPARED:
+			{
+				xl_xact_abort_prepared *prec;
+				xl_xact_abort *xlrec;
+				TransactionId *sub_xids;
+
+				/* prepared abort contain a normal commit abort... */
+				prec = (xl_xact_abort_prepared *) buf->record_data;
+				xlrec = &prec->arec;
+
+				sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
+
+				/* r->xl_xid is committed in a separate record */
+				DecodeAbort(ctx, buf->origptr, prec->xid,
+							sub_xids, xlrec->nsubxacts);
+				break;
+			}
+
+		case XLOG_XACT_ASSIGNMENT:
+			{
+				xl_xact_assignment *xlrec;
+				int			i;
+				TransactionId *sub_xid;
+
+				xlrec =	(xl_xact_assignment *) buf->record_data;
+
+				/* FIXME: skip based on database */
+
+				sub_xid = &xlrec->xsub[0];
+
+				for (i = 0; i < xlrec->nsubxacts; i++)
+				{
+					ReorderBufferAssignChild(reorder, xlrec->xtop,
+											 *(sub_xid++), buf->origptr);
+				}
+				break;
+			}
+		case XLOG_XACT_PREPARE:
+			/*
+			 * XXX: As a future feature, we could replay the transaction and
+			 * prepare it as well, allowing for 2PC via logical decoding.
+			 */
+			break;
+		default:
+			elog(ERROR, "unexpected RM_XACT_ID record type: %u", info);
+	}
+}
+
+/*
+ * Handle rmgr STANDBY_ID records for DecodeRecordIntoReorderBuffer().
+ */
+static void
+DecodeStandbyOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	SnapBuild  *builder = ctx->snapshot_builder;
+	XLogRecord *r = &buf->record;
+	uint8		info = r->xl_info & ~XLR_INFO_MASK;
+
+	switch (info)
+	{
+		case XLOG_RUNNING_XACTS:
+			{
+				xl_running_xacts *running = (xl_running_xacts *) buf->record_data;
+				SnapBuildProcessRunningXacts(builder, buf->origptr, running);
+				/*
+				 * Abort all transactions that we keep track of that are older
+				 * than ->oldestRunningXid. This is the most convenient spot
+				 * for doing so since, in contrast to shutdown or end of
+				 * recover checkpoints, we have sufficient knowledge to deal
+				 * with prepared transactions here.
+				 */
+				ReorderBufferAbortOld(ctx->reorder, running->oldestRunningXid);
+			}
+			break;
+		case XLOG_STANDBY_LOCK:
+			break;
+		default:
+			elog(ERROR, "unexpected RM_STANDBY_ID record type: %u", info);
+	}
+}
+
+/*
+ * Handle rmgr HEAP2_ID records for DecodeRecordIntoReorderBuffer().
+ */
+static void
+DecodeHeap2Op(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	uint8		info = buf->record.xl_info & XLOG_HEAP_OPMASK;
+	TransactionId xid = buf->record.xl_xid;
+	SnapBuild  *builder = ctx->snapshot_builder;
+
+	/* no point in doing anything yet */
+	if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT)
+		return;
+
+	switch (info)
+	{
+		case XLOG_HEAP2_MULTI_INSERT:
+			if (SnapBuildProcessChange(builder, xid, buf->origptr))
+				DecodeMultiInsert(ctx, buf);
+			break;
+		case XLOG_HEAP2_NEW_CID:
+			{
+				xl_heap_new_cid *xlrec;
+				xlrec = (xl_heap_new_cid *) buf->record_data;
+				SnapBuildProcessNewCid(builder, xid, buf->origptr, xlrec);
+
+				break;
+			}
+		case XLOG_HEAP2_REWRITE:
+			/* only crash recovery/replication needs to care */
+			break;
+
+		/*
+		 * Everything else here is just low level physical stuff we're
+		 * not interested in.
+		 */
+		case XLOG_HEAP2_FREEZE_PAGE:
+		case XLOG_HEAP2_CLEAN:
+		case XLOG_HEAP2_CLEANUP_INFO:
+		case XLOG_HEAP2_VISIBLE:
+		case XLOG_HEAP2_LOCK_UPDATED:
+			break;
+		default:
+			elog(ERROR, "unexpected RM_HEAP2_ID record type: %u", info);
+	}
+}
+
+/*
+ * Handle rmgr HEAP_ID records for DecodeRecordIntoReorderBuffer().
+ */
+static void
+DecodeHeapOp(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	uint8		info = buf->record.xl_info & XLOG_HEAP_OPMASK;
+	TransactionId xid = buf->record.xl_xid;
+	SnapBuild  *builder = ctx->snapshot_builder;
+
+	/* no point in doing anything yet */
+	if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT)
+		return;
+
+	switch (info)
+	{
+		case XLOG_HEAP_INSERT:
+			if (SnapBuildProcessChange(builder, xid, buf->origptr))
+				DecodeInsert(ctx, buf);
+			break;
+
+			/*
+			 * Treat HOT update as normal updates, there is no useful
+			 * information in the fact that we could make it a HOT update
+			 * locally and the WAL layout is compatible.
+			 */
+		case XLOG_HEAP_HOT_UPDATE:
+		case XLOG_HEAP_UPDATE:
+			if (SnapBuildProcessChange(builder, xid, buf->origptr))
+				DecodeUpdate(ctx, buf);
+			break;
+
+		case XLOG_HEAP_DELETE:
+			if (SnapBuildProcessChange(builder, xid, buf->origptr))
+				DecodeDelete(ctx, buf);
+			break;
+
+		case XLOG_HEAP_NEWPAGE:
+			/*
+			 * XXX: There doesn't seem to be a usecase for decoding
+			 * HEAP_NEWPAGE's. Its only used in various indexam's and CLUSTER,
+			 * neither of which should be relevant for the logical
+			 * changestream.
+			 */
+			break;
+
+		case XLOG_HEAP_INPLACE:
+			/*
+			 * If the record wasn't part of a transaction, it will not have
+			 * caused invalidations and thus isn't important when building
+			 * snapshots. If it was part of a transaction, that transaction
+			 * just performed DDL because those are the only codepaths using
+			 * inplace updates.
+			 */
+			if (!TransactionIdIsValid(xid))
+				break;
+
+			SnapBuildProcessChange(builder, xid, buf->origptr);
+			ReorderBufferXidSetCatalogChanges(ctx->reorder, xid, buf->origptr);
+			break;
+
+			/* we don't care about row level locks for now */
+		case XLOG_HEAP_LOCK:
+			break;
+
+		default:
+			elog(ERROR, "unexpected RM_HEAP_ID record type: %u", info);
+			break;
+	}
+}
+
+/*
+ * Get the data from the various forms of commit records and pass it
+ * on to snapbuild.c and reorderbuffer.c
+ */
+static void
+DecodeCommit(LogicalDecodingContext *ctx, XLogRecordBuffer *buf,
+			 TransactionId xid, TimestampTz commit_time,
+			 int nsubxacts, TransactionId *sub_xids,
+			 int ninval_msgs, SharedInvalidationMessage *msgs)
+{
+	int			i;
+
+	/* always need the invalidation messages */
+	if (ninval_msgs > 0)
+	{
+		ReorderBufferAddInvalidations(ctx->reorder, xid, buf->origptr,
+									  ninval_msgs, msgs);
+		ReorderBufferXidSetCatalogChanges(ctx->reorder, xid, buf->origptr);
+	}
+
+	SnapBuildCommitTxn(ctx->snapshot_builder, buf->origptr, xid,
+					   nsubxacts, sub_xids);
+
+	/*
+	 * We might not be interested in decoding transactions up to this
+	 * LSN. This can happen because we previously decoded it and now just are
+	 * restarting or we haven't assembled a consistent snapshot.
+	 *
+	 * If we're not interested just tell ReorderBuffer it's an abort and make
+	 * it throw away the data.
+	 */
+	if (SnapBuildXactNeedsSkip(ctx->snapshot_builder, buf->origptr))
+	{
+		/*
+		 * XXX: At some point we might want to execute the transaction's
+		 * invalidations here. Currently skips will only happen after we've
+		 * invalidated the entire cache after initially starting logically
+		 * decoding, but that might change at some point when we find it
+		 * necessary to use a more fine-grained mechanism.
+		 */
+		for (i = 0; i < nsubxacts; i++)
+		{
+			ReorderBufferAbort(ctx->reorder, *sub_xids, buf->origptr);
+			sub_xids++;
+		}
+		ReorderBufferAbort(ctx->reorder, xid, buf->origptr);
+
+		return;
+	}
+
+	for (i = 0; i < nsubxacts; i++)
+	{
+		ReorderBufferCommitChild(ctx->reorder, xid, *sub_xids,
+								 buf->origptr, buf->endptr);
+		sub_xids++;
+	}
+
+	/* replay actions of all transaction + subtransactions in order */
+	ReorderBufferCommit(ctx->reorder, xid, buf->origptr, buf->endptr,
+						commit_time);
+}
+
+/*
+ * Get the data from the various forms of abort records and pass it on to
+ * snapbuild.c and reorderbuffer.c
+ */
+static void
+DecodeAbort(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
+			TransactionId *sub_xids, int nsubxacts)
+{
+	int			i;
+
+	SnapBuildAbortTxn(ctx->snapshot_builder, lsn, xid, nsubxacts, sub_xids);
+
+	for (i = 0; i < nsubxacts; i++)
+	{
+		ReorderBufferAbort(ctx->reorder, *sub_xids, lsn);
+		sub_xids++;
+	}
+
+	ReorderBufferAbort(ctx->reorder, xid, lsn);
+}
+
+/*
+ * Parse XLOG_HEAP_INSERT (not MULTI_INSERT!) records into tuplebufs.
+ *
+ * Deletes can contain the new tuple.
+ */
+static void
+DecodeInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	XLogRecord *r = &buf->record;
+	xl_heap_insert *xlrec;
+	ReorderBufferChange *change;
+
+	xlrec = (xl_heap_insert *) buf->record_data;
+
+	/* only interested in our database */
+	if (xlrec->target.node.dbNode != ctx->slot->data.database)
+		return;
+
+	change = ReorderBufferGetChange(ctx->reorder);
+	change->action = REORDER_BUFFER_CHANGE_INSERT;
+	memcpy(&change->tp.relnode, &xlrec->target.node, sizeof(RelFileNode));
+
+	if (xlrec->flags & XLOG_HEAP_CONTAINS_NEW_TUPLE)
+	{
+		Assert(r->xl_len > (SizeOfHeapInsert + SizeOfHeapHeader));
+
+		change->tp.newtuple = ReorderBufferGetTupleBuf(ctx->reorder);
+
+		DecodeXLogTuple((char *) xlrec + SizeOfHeapInsert,
+						r->xl_len - SizeOfHeapInsert,
+						change->tp.newtuple);
+	}
+
+	ReorderBufferQueueChange(ctx->reorder, r->xl_xid, buf->origptr, change);
+}
+
+/*
+ * Parse XLOG_HEAP_UPDATE and XLOG_HEAP_HOT_UPDATE, which have the same layout
+ * in the record, from wal into proper tuplebufs.
+ *
+ * Updates can possibly contain a new tuple and the old primary key.
+ */
+static void
+DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	XLogRecord *r = &buf->record;
+	xl_heap_update *xlrec;
+	xl_heap_header_len *xlhdr;
+	ReorderBufferChange *change;
+	char	   *data;
+
+	xlrec = (xl_heap_update *) buf->record_data;
+	xlhdr = (xl_heap_header_len *) (buf->record_data + SizeOfHeapUpdate);
+
+	/* only interested in our database */
+	if (xlrec->target.node.dbNode != ctx->slot->data.database)
+		return;
+
+	change = ReorderBufferGetChange(ctx->reorder);
+	change->action = REORDER_BUFFER_CHANGE_UPDATE;
+	memcpy(&change->tp.relnode, &xlrec->target.node, sizeof(RelFileNode));
+
+	data = (char *) &xlhdr->header;
+
+	if (xlrec->flags & XLOG_HEAP_CONTAINS_NEW_TUPLE)
+	{
+		Assert(r->xl_len > (SizeOfHeapUpdate + SizeOfHeapHeaderLen));
+
+		change->tp.newtuple = ReorderBufferGetTupleBuf(ctx->reorder);
+
+		DecodeXLogTuple(data,
+						xlhdr->t_len + SizeOfHeapHeader,
+						change->tp.newtuple);
+		/* skip over the rest of the tuple header */
+		data += SizeOfHeapHeader;
+		/* skip over the tuple data */
+		data += xlhdr->t_len;
+	}
+
+	if (xlrec->flags & XLOG_HEAP_CONTAINS_OLD)
+	{
+		xlhdr = (xl_heap_header_len *) data;
+		change->tp.oldtuple = ReorderBufferGetTupleBuf(ctx->reorder);
+		DecodeXLogTuple((char *) &xlhdr->header,
+						xlhdr->t_len + SizeOfHeapHeader,
+						change->tp.oldtuple);
+		data = (char *) &xlhdr->header;
+		data += SizeOfHeapHeader;
+		data += xlhdr->t_len;
+	}
+
+	ReorderBufferQueueChange(ctx->reorder, r->xl_xid, buf->origptr, change);
+}
+
+/*
+ * Parse XLOG_HEAP_DELETE from wal into proper tuplebufs.
+ *
+ * Deletes can possibly contain the old primary key.
+ */
+static void
+DecodeDelete(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	XLogRecord *r = &buf->record;
+	xl_heap_delete *xlrec;
+	ReorderBufferChange *change;
+
+	xlrec = (xl_heap_delete *) buf->record_data;
+
+	/* only interested in our database */
+	if (xlrec->target.node.dbNode != ctx->slot->data.database)
+		return;
+
+	change = ReorderBufferGetChange(ctx->reorder);
+	change->action = REORDER_BUFFER_CHANGE_DELETE;
+
+	memcpy(&change->tp.relnode, &xlrec->target.node, sizeof(RelFileNode));
+
+	/* old primary key stored */
+	if (xlrec->flags & XLOG_HEAP_CONTAINS_OLD)
+	{
+		Assert(r->xl_len > (SizeOfHeapDelete + SizeOfHeapHeader));
+
+		change->tp.oldtuple = ReorderBufferGetTupleBuf(ctx->reorder);
+
+		DecodeXLogTuple((char *) xlrec + SizeOfHeapDelete,
+						r->xl_len - SizeOfHeapDelete,
+						change->tp.oldtuple);
+	}
+	ReorderBufferQueueChange(ctx->reorder, r->xl_xid, buf->origptr, change);
+}
+
+/*
+ * Decode XLOG_HEAP2_MULTI_INSERT_insert record into multiple tuplebufs.
+ *
+ * Currently MULTI_INSERT will always contain the full tuples.
+ */
+static void
+DecodeMultiInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	XLogRecord *r = &buf->record;
+	xl_heap_multi_insert *xlrec;
+	int			i;
+	char	   *data;
+	bool		isinit = (r->xl_info & XLOG_HEAP_INIT_PAGE) != 0;
+
+	xlrec = (xl_heap_multi_insert *) buf->record_data;
+
+	/* only interested in our database */
+	if (xlrec->node.dbNode != ctx->slot->data.database)
+		return;
+
+	data = buf->record_data + SizeOfHeapMultiInsert;
+
+	/*
+	 * OffsetNumbers (which are not of interest to us) are stored when
+	 * XLOG_HEAP_INIT_PAGE is not set -- skip over them.
+	 */
+	if (!isinit)
+		data += sizeof(OffsetNumber) * xlrec->ntuples;
+
+	for (i = 0; i < xlrec->ntuples; i++)
+	{
+		ReorderBufferChange *change;
+		xl_multi_insert_tuple *xlhdr;
+		int			datalen;
+		ReorderBufferTupleBuf *tuple;
+
+		change = ReorderBufferGetChange(ctx->reorder);
+		change->action = REORDER_BUFFER_CHANGE_INSERT;
+		memcpy(&change->tp.relnode, &xlrec->node, sizeof(RelFileNode));
+
+		/*
+		 * CONTAINS_NEW_TUPLE will always be set currently as multi_insert
+		 * isn't used for catalogs, but better be future proof.
+		 *
+		 * We decode the tuple in pretty much the same way as DecodeXLogTuple,
+		 * but since the layout is slightly different, we can't use it here.
+		 */
+		if (xlrec->flags & XLOG_HEAP_CONTAINS_NEW_TUPLE)
+		{
+			change->tp.newtuple = ReorderBufferGetTupleBuf(ctx->reorder);
+
+			tuple = change->tp.newtuple;
+
+			/* not a disk based tuple */
+			ItemPointerSetInvalid(&tuple->tuple.t_self);
+
+			xlhdr = (xl_multi_insert_tuple *) SHORTALIGN(data);
+			data = ((char *) xlhdr) + SizeOfMultiInsertTuple;
+			datalen = xlhdr->datalen;
+
+			/*
+			 * We can only figure this out after reassembling the
+			 * transactions.
+			 */
+			tuple->tuple.t_tableOid = InvalidOid;
+			tuple->tuple.t_data = &tuple->header;
+			tuple->tuple.t_len = datalen
+				+ offsetof(HeapTupleHeaderData, t_bits);
+
+			memset(&tuple->header, 0, sizeof(HeapTupleHeaderData));
+
+			memcpy((char *) &tuple->header
+				   + offsetof(HeapTupleHeaderData, t_bits),
+				   (char *) data,
+				   datalen);
+			data += datalen;
+
+			tuple->header.t_infomask = xlhdr->t_infomask;
+			tuple->header.t_infomask2 = xlhdr->t_infomask2;
+			tuple->header.t_hoff = xlhdr->t_hoff;
+		}
+
+		ReorderBufferQueueChange(ctx->reorder, r->xl_xid,
+								 buf->origptr, change);
+	}
+}
+
+/*
+ * Read a HeapTuple as WAL logged by heap_insert, heap_update and
+ * heap_delete, but not by heap_multi_insert into a tuplebuf.
+ *
+ * The size 'len' and the pointer 'data' in the record need to be
+ * computed outside as they are record specific.
+ */
+static void
+DecodeXLogTuple(char *data, Size len, ReorderBufferTupleBuf *tuple)
+{
+	xl_heap_header xlhdr;
+	int			datalen = len - SizeOfHeapHeader;
+
+	Assert(datalen >= 0);
+	Assert(datalen <= MaxHeapTupleSize);
+
+	tuple->tuple.t_len = datalen + offsetof(HeapTupleHeaderData, t_bits);
+
+	/* not a disk based tuple */
+	ItemPointerSetInvalid(&tuple->tuple.t_self);
+
+	/* we can only figure this out after reassembling the transactions */
+	tuple->tuple.t_tableOid = InvalidOid;
+	tuple->tuple.t_data = &tuple->header;
+
+	/* data is not stored aligned, copy to aligned storage */
+	memcpy((char *) &xlhdr,
+		   data,
+		   SizeOfHeapHeader);
+
+	memset(&tuple->header, 0, sizeof(HeapTupleHeaderData));
+
+	memcpy((char *) &tuple->header + offsetof(HeapTupleHeaderData, t_bits),
+		   data + SizeOfHeapHeader,
+		   datalen);
+
+	tuple->header.t_infomask = xlhdr.t_infomask;
+	tuple->header.t_infomask2 = xlhdr.t_infomask2;
+	tuple->header.t_hoff = xlhdr.t_hoff;
+}
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
new file mode 100644
index 0000000..fd022f0
--- /dev/null
+++ b/src/backend/replication/logical/logical.c
@@ -0,0 +1,809 @@
+/*-------------------------------------------------------------------------
+ * logical.c
+ *	   PostgreSQL changeset extraction coordination
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/backend/replication/logical/logical.c
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "fmgr.h"
+#include "miscadmin.h"
+
+#include "access/transam.h"
+
+#include "replication/decode.h"
+#include "replication/logical.h"
+#include "replication/reorderbuffer.h"
+#include "replication/snapbuild.h"
+
+#include "storage/ipc.h"
+#include "storage/proc.h"
+#include "storage/procarray.h"
+#include "storage/fd.h"
+
+#include "utils/memutils.h"
+#include "utils/syscache.h"
+
+/*
+ * Set the xmin required for decoding snapshots for the specific decoding
+ * slot.
+ */
+void
+IncreaseLogicalXminForSlot(XLogRecPtr lsn, TransactionId xmin)
+{
+	bool	updated_xmin = false;
+
+	Assert(MyReplicationSlot != NULL);
+
+	SpinLockAcquire(&MyReplicationSlot->mutex);
+
+	/*
+	 * don't overwrite if we already have a newer xmin. This can
+	 * happen if we restart decoding in a slot.
+	 */
+	if (TransactionIdPrecedesOrEquals(xmin, MyReplicationSlot->data.catalog_xmin))
+	{
+	}
+	/*
+	 * If the client has already confirmed up to this lsn, we directly
+	 * can mark this as accepted. This can happen if we restart
+	 * decoding in a slot.
+	 */
+	else if (lsn <= MyReplicationSlot->data.confirmed_flush)
+	{
+		MyReplicationSlot->candidate_catalog_xmin = xmin;
+		MyReplicationSlot->candidate_xmin_lsn = lsn;
+
+		/* our candidate can directly be used */
+		updated_xmin = true;
+	}
+	/*
+	 * Only increase if the previous values have been applied, otherwise we
+	 * might never end up updating if the receiver acks too slowly.
+	 */
+	else if (MyReplicationSlot->candidate_xmin_lsn == InvalidXLogRecPtr)
+	{
+		MyReplicationSlot->candidate_catalog_xmin = xmin;
+		MyReplicationSlot->candidate_xmin_lsn = lsn;
+		elog(DEBUG1, "got new xmin %u at %X/%X", xmin,
+			 (uint32) (lsn >> 32), (uint32) lsn);
+	}
+	SpinLockRelease(&MyReplicationSlot->mutex);
+
+	/* candidate already valid with the current flush position, apply */
+	if (updated_xmin)
+		LogicalConfirmReceivedLocation(MyReplicationSlot->data.confirmed_flush);
+}
+
+/*
+ * Mark the minimal LSN (restart_lsn) we need to read to replay all
+ * transactions that have not yet committed at current_lsn. Only takes
+ * effect when the client has confirmed to have received current_lsn.
+ */
+void
+IncreaseRestartDecodingForSlot(XLogRecPtr current_lsn, XLogRecPtr restart_lsn)
+{
+	bool	updated_lsn = false;
+
+	Assert(MyReplicationSlot != NULL);
+	Assert(restart_lsn != InvalidXLogRecPtr);
+	Assert(current_lsn != InvalidXLogRecPtr);
+
+	SpinLockAcquire(&MyReplicationSlot->mutex);
+
+	/* don't overwrite if have a newer restart lsn*/
+	if (restart_lsn <= MyReplicationSlot->data.restart_lsn)
+	{
+	}
+	/*
+	 * We might have already flushed far enough to directly accept this lsn, in
+	 * this case there is no need to check for existing candidate LSNs
+	 */
+	else if (current_lsn <= MyReplicationSlot->data.confirmed_flush)
+	{
+		MyReplicationSlot->candidate_restart_valid = current_lsn;
+		MyReplicationSlot->candidate_restart_lsn = restart_lsn;
+
+		/* our candidate can directly be used */
+		updated_lsn = true;
+	}
+	/*
+	 * Only increase if the previous values have been applied, otherwise we
+	 * might never end up updating if the receiver acks too slowly. A missed
+	 * value here will just cause some extra effort after reconnecting.
+	 */
+	if (MyReplicationSlot->candidate_restart_valid == InvalidXLogRecPtr)
+	{
+		MyReplicationSlot->candidate_restart_valid = current_lsn;
+		MyReplicationSlot->candidate_restart_lsn = restart_lsn;
+
+		elog(DEBUG1, "got new restart lsn %X/%X at %X/%X",
+			 (uint32) (restart_lsn >> 32), (uint32) restart_lsn,
+			 (uint32) (current_lsn >> 32), (uint32) current_lsn);
+	}
+	else
+	{
+		elog(DEBUG1, "failed to increase restart lsn: proposed %X/%X, after %X/%X, current candidate %X/%X, current after %X/%X, flushed up to %X/%X",
+			 (uint32) (restart_lsn >> 32), (uint32) restart_lsn,
+			 (uint32) (current_lsn >> 32), (uint32) current_lsn,
+			 (uint32) (MyReplicationSlot->candidate_restart_lsn >> 32),
+			 (uint32) MyReplicationSlot->candidate_restart_lsn,
+			 (uint32) (MyReplicationSlot->candidate_restart_valid >> 32),
+			 (uint32) MyReplicationSlot->candidate_restart_valid,
+			 (uint32) (MyReplicationSlot->data.confirmed_flush >> 32),
+			 (uint32) MyReplicationSlot->data.confirmed_flush
+			);
+	}
+	SpinLockRelease(&MyReplicationSlot->mutex);
+
+	/* candidates are already valid with the current flush position, apply */
+	if (updated_lsn)
+		LogicalConfirmReceivedLocation(MyReplicationSlot->data.confirmed_flush);
+}
+
+void
+LogicalConfirmReceivedLocation(XLogRecPtr lsn)
+{
+	Assert(lsn != InvalidXLogRecPtr);
+
+	/* Do an unlocked check for candidate_lsn first. */
+	if (MyReplicationSlot->candidate_xmin_lsn != InvalidXLogRecPtr ||
+		MyReplicationSlot->candidate_restart_valid != InvalidXLogRecPtr)
+	{
+		bool		updated_xmin = false;
+		bool		updated_restart = false;
+
+		/* use volatile pointer to prevent code rearrangement */
+		volatile ReplicationSlot *slot = MyReplicationSlot;
+
+		SpinLockAcquire(&slot->mutex);
+
+		slot->data.confirmed_flush = lsn;
+
+		/* if were past the location required for bumping xmin, do so */
+		if (slot->candidate_xmin_lsn != InvalidXLogRecPtr &&
+			slot->candidate_xmin_lsn <= lsn)
+		{
+			/*
+			 * We have to write the changed xmin to disk *before* we change
+			 * the in-memory value, otherwise after a crash we wouldn't know
+			 * that some catalog tuples might have been removed already.
+			 *
+			 * Ensure that by first writing to ->xmin and only update
+			 * ->effective_xmin once the new state is synced to disk. After a
+			 * crash ->effective_xmin is set to ->xmin.
+			 */
+			if (TransactionIdIsValid(slot->candidate_catalog_xmin) &&
+				slot->data.catalog_xmin != slot->candidate_catalog_xmin)
+			{
+				slot->data.catalog_xmin = slot->candidate_catalog_xmin;
+				slot->candidate_catalog_xmin = InvalidTransactionId;
+				slot->candidate_xmin_lsn = InvalidXLogRecPtr;
+				updated_xmin = true;
+			}
+		}
+
+		if (slot->candidate_restart_valid != InvalidXLogRecPtr &&
+			slot->candidate_restart_valid <= lsn)
+		{
+			Assert(slot->candidate_restart_lsn != InvalidXLogRecPtr);
+
+			slot->data.restart_lsn = slot->candidate_restart_lsn;
+			slot->candidate_restart_lsn = InvalidXLogRecPtr;
+			slot->candidate_restart_valid = InvalidXLogRecPtr;
+			updated_restart = true;
+		}
+
+		SpinLockRelease(&slot->mutex);
+
+		/* first write new xmin to disk, so we know whats up after a crash */
+		if (updated_xmin || updated_restart)
+		{
+			/* cast away volatile, thats ok. */
+			ReplicationSlotSave();
+			elog(DEBUG1, "updated xmin: %u restart: %u", updated_xmin, updated_restart);
+		}
+		/*
+		 * Now the new xmin is safely on disk, we can let the global value
+		 * advance. We do not take ProcArrayLock or similar since we only
+		 * advance xmin here and there's not much harm done by a concurrent
+		 * computation missing that.
+		 */
+		if (updated_xmin)
+		{
+			SpinLockAcquire(&slot->mutex);
+			slot->effective_catalog_xmin = slot->data.catalog_xmin;
+			SpinLockRelease(&slot->mutex);
+
+			ReplicationSlotsComputeRequiredXmin(false);
+		}
+	}
+	else
+	{
+		volatile ReplicationSlot *slot = MyReplicationSlot;
+
+		SpinLockAcquire(&slot->mutex);
+		slot->data.confirmed_flush = lsn;
+		SpinLockRelease(&slot->mutex);
+	}
+}
+
+/*
+ * Compute the oldest WAL LSN required by *logical* decoding slots..
+ *
+ * Returns InvalidXLogRecPtr if logical decoding is disabled or no logicals
+ * slots exist.
+ *
+ * NB: this returns a value >= ReplicationSlotsComputeRequiredLSN(), since it
+ * ignores physical replication slots.
+ */
+XLogRecPtr
+ComputeLogicalRestartLSN(void)
+{
+	XLogRecPtr	result = InvalidXLogRecPtr;
+	int			i;
+
+	if (max_replication_slots <= 0)
+		return InvalidXLogRecPtr;
+
+	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
+
+	for (i = 0; i < max_replication_slots; i++)
+	{
+		volatile ReplicationSlot *s;
+		XLogRecPtr		restart_lsn;
+
+		s = &ReplicationSlotCtl->replication_slots[i];
+
+		/* cannot change while ReplicationSlotCtlLock is held */
+		if (!s->in_use)
+			continue;
+
+		/* we're only interested in logical slots */
+		if (s->data.database == InvalidOid)
+			continue;
+
+		/* read once, it's ok if it increases while we're checking */
+		SpinLockAcquire(&s->mutex);
+		restart_lsn = s->data.restart_lsn;
+		SpinLockRelease(&s->mutex);
+
+		if (result == InvalidXLogRecPtr ||
+			restart_lsn < result)
+			result = restart_lsn;
+	}
+
+	LWLockRelease(ReplicationSlotControlLock);
+
+	return result;
+}
+
+/*
+ * Make sure the current settings & environment are capable of doing logical
+ * changeset extraction.
+ */
+void
+CheckLogicalDecodingRequirements(void)
+{
+	CheckSlotRequirements();
+
+	if (wal_level < WAL_LEVEL_LOGICAL)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("changeset extraction requires wal_level >= logical")));
+
+	if (MyDatabaseId == InvalidOid)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("changeset extraction requires to be connected to a database")));
+}
+
+/*
+ * LogicalDecodingCountDBSlots -- count number of slots referring to the given DB
+ *
+ * Returns true if there are any slots referencing the
+ * database. *nslots will be set to the absolute number of slots in
+ * the database, *nactive to ones currently active.
+ */
+bool
+LogicalDecodingCountDBSlots(Oid dboid, int *nslots, int *nactive)
+{
+	int			i;
+
+	*nslots = *nactive = 0;
+
+	if (max_replication_slots <= 0)
+		return false;
+
+	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
+	for (i = 0; i < max_replication_slots; i++)
+	{
+		volatile ReplicationSlot *s;
+
+		s = &ReplicationSlotCtl->replication_slots[i];
+
+		/* cannot change while ReplicationSlotCtlLock is held */
+		if (!s->in_use)
+			continue;
+
+		/* not our database, don't count */
+		if (s->data.database != dboid)
+			continue;
+
+		/* count slots with spinlock held */
+		SpinLockAcquire(&s->mutex);
+		(*nslots)++;
+		if (s->active)
+			(*nactive)++;
+		SpinLockRelease(&s->mutex);
+	}
+	LWLockRelease(ReplicationSlotControlLock);
+
+	if (*nslots > 0)
+		return true;
+	return false;
+}
+
+static void
+LoadOutputPlugin(OutputPluginCallbacks *callbacks, char *plugin)
+{
+	LogicalOutputPluginInit plugin_init;
+
+	plugin_init = (LogicalOutputPluginInit)
+		load_external_function(plugin, "_PG_output_plugin_init", false, NULL);
+
+	if (plugin_init == NULL)
+		elog(ERROR, "output plugins have to declare the _PG_output_plugin_init symbol");
+
+	plugin_init(callbacks);
+
+	if (callbacks->begin_cb == NULL)
+		elog(ERROR, "output plugins have to register a begin callback");
+	if (callbacks->change_cb == NULL)
+		elog(ERROR, "output plugins have to register a change callback");
+	if (callbacks->commit_cb == NULL)
+		elog(ERROR, "output plugins have to register a commit callback");
+}
+
+/*
+ * Context management functions to coordinate between the different logical
+ * decoding pieces.
+ */
+
+typedef struct LogicalErrorCallbackState
+{
+	LogicalDecodingContext *ctx;
+	const char *callback;
+} LogicalErrorCallbackState;
+
+static void
+output_plugin_error_callback(void *arg)
+{
+	LogicalErrorCallbackState *state = (LogicalErrorCallbackState *) arg;
+	/* XXX: Add the current LSN? */
+	errcontext("slot \"%s\", output plugin \"%s\" during the %s callback",
+			   NameStr(state->ctx->slot->data.name),
+			   NameStr(state->ctx->slot->data.plugin),
+			   state->callback);
+}
+
+static void
+startup_slot_wrapper(LogicalDecodingContext *ctx, bool is_init)
+{
+	LogicalErrorCallbackState state;
+	ErrorContextCallback errcallback;
+
+	/* Push callback + info on the error context stack */
+	state.ctx = ctx;
+	state.callback = "pg_decode_startup";
+	errcallback.callback = output_plugin_error_callback;
+	errcallback.arg = (void *) &state;
+	errcallback.previous = error_context_stack;
+	error_context_stack = &errcallback;
+
+	/* set output state */
+	ctx->accept_writes = false;
+
+	/* do the actual work: call callback */
+	ctx->callbacks.startup_cb(ctx, is_init);
+
+	/* Pop the error context stack */
+	error_context_stack = errcallback.previous;
+}
+
+static void
+shutdown_slot_wrapper(LogicalDecodingContext *ctx)
+{
+	LogicalErrorCallbackState state;
+	ErrorContextCallback errcallback;
+
+	/* Push callback + info on the error context stack */
+	state.ctx = ctx;
+	state.callback = "pg_decode_shutdown";
+	errcallback.callback = output_plugin_error_callback;
+	errcallback.arg = (void *) &state;
+	errcallback.previous = error_context_stack;
+	error_context_stack = &errcallback;
+
+	/* set output state */
+	ctx->accept_writes = false;
+
+	/* do the actual work: call callback */
+	ctx->callbacks.shutdown_cb(ctx);
+
+	/* Pop the error context stack */
+	error_context_stack = errcallback.previous;
+}
+
+
+/*
+ * Callbacks for ReorderBuffer which add in some more information and then call
+ * output_plugin.h plugins.
+ */
+static void
+begin_txn_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn)
+{
+	LogicalDecodingContext *ctx = cache->private_data;
+	LogicalErrorCallbackState state;
+	ErrorContextCallback errcallback;
+
+	/* Push callback + info on the error context stack */
+	state.ctx = ctx;
+	state.callback = "pg_decode_begin_txn";
+	errcallback.callback = output_plugin_error_callback;
+	errcallback.arg = (void *) &state;
+	errcallback.previous = error_context_stack;
+	error_context_stack = &errcallback;
+
+	/* set output state */
+	ctx->accept_writes = true;
+	ctx->write_xid = txn->xid;
+	ctx->write_location = txn->first_lsn;
+
+	/* do the actual work: call callback */
+	ctx->callbacks.begin_cb(ctx, txn);
+
+	/* Pop the error context stack */
+	error_context_stack = errcallback.previous;
+}
+
+static void
+commit_txn_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn, XLogRecPtr commit_lsn)
+{
+	LogicalDecodingContext *ctx = cache->private_data;
+	LogicalErrorCallbackState state;
+	ErrorContextCallback errcallback;
+
+	/* Push callback + info on the error context stack */
+	state.ctx = ctx;
+	state.callback = "pg_decode_commit_txn";
+	errcallback.callback = output_plugin_error_callback;
+	errcallback.arg = (void *) &state;
+	errcallback.previous = error_context_stack;
+	error_context_stack = &errcallback;
+
+	/* set output state */
+	ctx->accept_writes = true;
+	ctx->write_xid = txn->xid;
+	ctx->write_location = txn->end_lsn;
+
+	/* do the actual work: call callback */
+	ctx->callbacks.commit_cb(ctx, txn, commit_lsn);
+
+	/* Pop the error context stack */
+	error_context_stack = errcallback.previous;
+}
+
+static void
+change_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
+			   Relation relation, ReorderBufferChange *change)
+{
+	LogicalDecodingContext *ctx = cache->private_data;
+	LogicalErrorCallbackState state;
+	ErrorContextCallback errcallback;
+
+	/* Push callback + info on the error context stack */
+	state.ctx = ctx;
+	state.callback = "pg_decode_change";
+	errcallback.callback = output_plugin_error_callback;
+	errcallback.arg = (void *) &state;
+	errcallback.previous = error_context_stack;
+	error_context_stack = &errcallback;
+
+	/* set output state */
+	ctx->accept_writes = true;
+	ctx->write_xid = txn->xid;
+	ctx->write_location = txn->end_lsn;
+
+	ctx->callbacks.change_cb(ctx, txn, relation, change);
+
+	/* Pop the error context stack */
+	error_context_stack = errcallback.previous;
+}
+
+/*
+ * Prepare a write using the context's output routine.
+ */
+void
+OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
+{
+	if (!ctx->accept_writes)
+		elog(ERROR, "writes are only accepted in commit, begin and change callbacks");
+
+	ctx->prepare_write(ctx, ctx->write_location, ctx->write_xid, last_write);
+	ctx->prepared_write = true;
+}
+
+/*
+ * Perform a write using the context's output routine.
+ */
+void
+OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
+{
+	if (!ctx->prepared_write)
+		elog(ERROR, "OutputPluginPrepareWrite needs to be called before OutputPluginWrite");
+
+	ctx->write(ctx, ctx->write_location, ctx->write_xid, last_write);
+	ctx->prepared_write = false;
+}
+
+/*
+ * Allocate a new decoding context.
+ *
+ * is_init denotes whether the slot is newly initialized
+ * plugin sets the output plugin used when initializing the slot
+ * output_plugin_options contains options passed to the output plugin
+ * read_page, prepare_write, do_write are callbacks that have to be filled to
+ *		perform the use-case dependent, actual, work.
+ *
+ * Returns a usable output plugin after calling the output plugins startup
+ * function.
+ */
+LogicalDecodingContext *
+CreateDecodingContext(bool is_init,
+					  char *plugin,
+					  XLogRecPtr start_lsn,
+					  List *output_plugin_options,
+					  XLogPageReadCB read_page,
+					  LogicalOutputPluginWriterPrepareWrite prepare_write,
+					  LogicalOutputPluginWriterWrite do_write)
+{
+	MemoryContext context;
+	MemoryContext old_context;
+	TransactionId xmin_horizon;
+	LogicalDecodingContext *ctx;
+	ReplicationSlot *slot;
+
+	if (MyReplicationSlot == NULL)
+		elog(ERROR, "need a current slot");
+
+	if (is_init && start_lsn != InvalidXLogRecPtr)
+		elog(ERROR, "Cannot INIT_LOGICAL_REPLICATION at a specified LSN");
+
+	if (is_init && plugin == NULL)
+		elog(ERROR, "Cannot INIT_LOGICAL_REPLICATION without a specified plugin");
+
+	if (MyReplicationSlot->data.database == InvalidOid)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 (errmsg("cannot use a replication slot created for streaming replication for changeset extraction"))));
+
+	if (MyReplicationSlot->data.database != MyDatabaseId)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 (errmsg("START_REPLICATION needs to be run in the same database as CREATE_REPLICATION_SLOT"))));
+
+	/* shorter lines... */
+	slot = MyReplicationSlot;
+
+	context = AllocSetContextCreate(CurrentMemoryContext,
+									"Changeset Extraction Context",
+									ALLOCSET_DEFAULT_MINSIZE,
+									ALLOCSET_DEFAULT_INITSIZE,
+									ALLOCSET_DEFAULT_MAXSIZE);
+	old_context = MemoryContextSwitchTo(context);
+	ctx = palloc0(sizeof(LogicalDecodingContext));
+
+	ctx->context = context;
+
+	/* If we're initializing a new slot, there's a bit more to do */
+	if (is_init)
+	{
+		/* register output plugin name with slot */
+		strncpy(NameStr(MyReplicationSlot->data.plugin), plugin,
+				NAMEDATALEN);
+		NameStr(MyReplicationSlot->data.plugin)[NAMEDATALEN - 1] = '\0';
+
+		/*
+		 * Lets start with enough information if we can, so log a standby
+		 * snapshot and start decoding at exactl that position.
+		 */
+		if (!RecoveryInProgress())
+		{
+			XLogRecPtr flushptr;
+
+			/* start at current insert position*/
+			slot->data.restart_lsn = GetXLogInsertRecPtr();
+
+			/* make sure we have enough information to start */
+			flushptr = LogStandbySnapshot();
+
+			/* and make sure it's fsynced to disk */
+			XLogFlush(flushptr);
+		}
+		else
+			slot->data.restart_lsn = GetRedoRecPtr();
+
+		/*
+		 * Acquire the current global xmin value and directly set the logical
+		 * xmin before releasing the lock if necessary. We do this so wal
+		 * decoding is guaranteed to have all catalog rows produced by xacts
+		 * with an xid > walsnd->xmin available.
+		 *
+		 * We can't let ReplicationSlotsComputeRequiredXmin() lock the
+		 * procarray as that acquires ProcArrayLock separately which would
+		 * open a short window for the global xmin to advance above our xmin.
+		 */
+		LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+		slot->effective_catalog_xmin = GetOldestSafeDecodingTransactionId();
+		slot->data.catalog_xmin = slot->effective_catalog_xmin;
+
+		ReplicationSlotsComputeRequiredXmin(true);
+
+		LWLockRelease(ProcArrayLock);
+
+		xmin_horizon = slot->data.catalog_xmin;
+	}
+	else
+	{
+		xmin_horizon = InvalidTransactionId;
+
+		if (start_lsn == InvalidXLogRecPtr)
+		{
+			/* continue from last position */
+			start_lsn = slot->data.confirmed_flush;
+		}
+		else if (start_lsn < MyReplicationSlot->data.confirmed_flush)
+		{
+			/*
+			 * It might seem like we should error out in this case, but it's
+			 * pretty common for a client to acknowledge a LSN it doesn't have
+			 * to do anything for, and thus didn't store persistently, because
+			 * the xlog records didn't result in anyting relevant for
+			 * changeset extraction.
+			 */
+			start_lsn = MyReplicationSlot->data.confirmed_flush;
+			elog(LOG, "cannot stream from %X/%X, minimum is %X/%X, forwarding",
+				 (uint32)(start_lsn >> 32), (uint32)start_lsn,
+				 (uint32)(slot->data.confirmed_flush >> 32), (uint32)slot->data.confirmed_flush);
+		}
+	}
+
+	/* load output plugins, so we detect a wrong output plugin now. */
+	LoadOutputPlugin(&ctx->callbacks, NameStr(slot->data.plugin));
+
+	/*
+	 * Now that the slot's xmin has been set, we can announce ourselves as a
+	 * logical decoding backend which doesn't need to be checked when
+	 * computing the xmin horizon.
+	 */
+	LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+	MyPgXact->vacuumFlags |= PROC_IN_LOGICAL_DECODING;
+	LWLockRelease(ProcArrayLock);
+
+	ctx->slot = slot;
+
+	ctx->reader = XLogReaderAllocate(read_page, ctx);
+	ctx->reader->private_data = ctx;
+
+	ctx->reorder = ReorderBufferAllocate();
+	ctx->snapshot_builder =
+		AllocateSnapshotBuilder(ctx->reorder, xmin_horizon, start_lsn);
+
+	ctx->reorder->private_data = ctx;
+
+	/* wrap output plugin callbacks, so we can add error context information */
+	ctx->reorder->begin = begin_txn_wrapper;
+	ctx->reorder->apply_change = change_wrapper;
+	ctx->reorder->commit = commit_txn_wrapper;
+
+	ctx->out = makeStringInfo();
+	ctx->prepare_write = prepare_write;
+	ctx->write = do_write;
+
+	ctx->output_plugin_options = output_plugin_options;
+
+	/* call output plugin initialization callback */
+	if (ctx->callbacks.startup_cb != NULL)
+		startup_slot_wrapper(ctx, is_init);
+
+	MemoryContextSwitchTo(old_context);
+
+	ereport(LOG,
+			(errmsg("changeset extraction started, extracting changes after %X/%X, reading from %X/%X",
+					(uint32)(slot->data.confirmed_flush >> 32),
+					(uint32)slot->data.confirmed_flush,
+					(uint32)(slot->data.restart_lsn >> 32),
+					(uint32)slot->data.restart_lsn)));
+
+	return ctx;
+}
+
+/*
+ * Read from the decoding slot
+ */
+void
+DecodingContextFindStartpoint(LogicalDecodingContext *ctx)
+{
+	XLogRecPtr	startptr;
+
+	/* Initialize from where to start reading WAL. */
+	startptr = ctx->slot->data.restart_lsn;
+
+	elog(DEBUG1, "searching for intial changeset extraction starting point, starting at %X/%X",
+		 (uint32)(ctx->slot->data.restart_lsn >> 32),
+		 (uint32)ctx->slot->data.restart_lsn);
+
+	/* Wait for a consistent starting point */
+	for (;;)
+	{
+		XLogRecord *record;
+		char	   *err = NULL;
+
+		/*
+		 * If the caller requires that interrupts be checked, the read_page
+		 * callback should do so, as those will often wait.
+		 */
+
+		/* the read_page callback waits for new WAL */
+		record = XLogReadRecord(ctx->reader, startptr, &err);
+		if (err)
+			elog(ERROR, "%s", err);
+
+		Assert(record);
+
+		startptr = InvalidXLogRecPtr;
+
+		LogicalDecodingProcessRecord(ctx, record);
+
+		/* only continue till we found a consistent spot */
+		if (DecodingContextReady(ctx))
+			break;
+	}
+
+	ctx->slot->data.confirmed_flush = ctx->reader->EndRecPtr;
+}
+
+/*
+ * Free a previously allocated decoding context, invoking the shutdown
+ * callback if necessary.
+ */
+void
+FreeDecodingContext(LogicalDecodingContext *ctx)
+{
+	if (ctx->callbacks.shutdown_cb != NULL)
+		shutdown_slot_wrapper(ctx);
+
+	ReorderBufferFree(ctx->reorder);
+	FreeSnapshotBuilder(ctx->snapshot_builder);
+	XLogReaderFree(ctx->reader);
+	MemoryContextDelete(ctx->context);
+}
+
+
+/*
+ * Returns true if an consistent initial decoding snapshot has been built.
+ */
+bool
+DecodingContextReady(LogicalDecodingContext *ctx)
+{
+	return SnapBuildCurrentState(ctx->snapshot_builder) == SNAPBUILD_CONSISTENT;
+}
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
new file mode 100644
index 0000000..6579041
--- /dev/null
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -0,0 +1,550 @@
+/*-------------------------------------------------------------------------
+ *
+ * logicalfuncs.c
+ *
+ *	   Support functions for using changeset extraction and managing
+ *	   logical replication slots via SQL.
+ *
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/backend/replication/logicalfuncs.c
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include <unistd.h>
+
+#include "fmgr.h"
+#include "funcapi.h"
+#include "miscadmin.h"
+
+#include "catalog/pg_type.h"
+
+#include "nodes/makefuncs.h"
+
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/inval.h"
+#include "utils/memutils.h"
+#include "utils/resowner.h"
+
+#include "replication/decode.h"
+#include "replication/logical.h"
+#include "replication/logicalfuncs.h"
+
+#include "storage/fd.h"
+
+/* private date for writing out data */
+typedef struct DecodingOutputState {
+	Tuplestorestate *tupstore;
+	TupleDesc tupdesc;
+} DecodingOutputState;
+
+/*
+ * Prepare for a output plugin write.
+ */
+static void
+LogicalOutputPrepareWrite(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
+						  bool last_write)
+{
+	resetStringInfo(ctx->out);
+}
+
+/*
+ * Performoutput plugin write into tuplestore.
+ */
+static void
+LogicalOutputWrite(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
+				   bool last_write)
+{
+	Datum		values[3];
+	bool		nulls[3];
+	char		buf[60];
+	DecodingOutputState *p;
+
+	/* SQL Datums can only be of a limited length... */
+	if (ctx->out->len > MaxAllocSize - VARHDRSZ)
+		elog(ERROR, "too much output for sql interface");
+
+	p = (DecodingOutputState *) ctx->output_writer_private;
+
+	sprintf(buf, "%X/%X", (uint32) (lsn >> 32), (uint32) lsn);
+
+	memset(nulls, 0, sizeof(nulls));
+	values[0] = CStringGetTextDatum(buf);
+	values[1] = TransactionIdGetDatum(xid);
+	/*
+	 * XXX: maybe we ought to assert ctx->out is in database encoding when
+	 * we're writing textual output.
+	 */
+	/* ick, but cstring_to_text_with_len works for bytea perfectly fine */
+	values[2] = PointerGetDatum(
+		cstring_to_text_with_len(ctx->out->data, ctx->out->len));
+
+	tuplestore_putvalues(p->tupstore, p->tupdesc, values, nulls);
+}
+
+/* FIXME: duplicate code with pg_xlogdump, similar to walsender.c */
+static void
+XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
+{
+	char	   *p;
+	XLogRecPtr	recptr;
+	Size		nbytes;
+
+	static int	sendFile = -1;
+	static XLogSegNo sendSegNo = 0;
+	static uint32 sendOff = 0;
+
+	p = buf;
+	recptr = startptr;
+	nbytes = count;
+
+	while (nbytes > 0)
+	{
+		uint32		startoff;
+		int			segbytes;
+		int			readbytes;
+
+		startoff = recptr % XLogSegSize;
+
+		if (sendFile < 0 || !XLByteInSeg(recptr, sendSegNo))
+		{
+			char		path[MAXPGPATH];
+
+			/* Switch to another logfile segment */
+			if (sendFile >= 0)
+				close(sendFile);
+
+			XLByteToSeg(recptr, sendSegNo);
+
+			XLogFilePath(path, tli, sendSegNo);
+
+			sendFile = BasicOpenFile(path, O_RDONLY | PG_BINARY, 0);
+
+			if (sendFile < 0)
+			{
+				if (errno == ENOENT)
+					ereport(ERROR,
+							(errcode_for_file_access(),
+							 errmsg("requested WAL segment %s has already been removed",
+									path)));
+				else
+					ereport(ERROR,
+							(errcode_for_file_access(),
+							 errmsg("could not open file \"%s\": %m",
+									path)));
+			}
+			sendOff = 0;
+		}
+
+		/* Need to seek in the file? */
+		if (sendOff != startoff)
+		{
+			if (lseek(sendFile, (off_t) startoff, SEEK_SET) < 0)
+			{
+				char		path[MAXPGPATH];
+
+				XLogFilePath(path, tli, sendSegNo);
+
+				ereport(ERROR,
+						(errcode_for_file_access(),
+				  errmsg("could not seek in log segment %s to offset %u: %m",
+						 path, startoff)));
+			}
+			sendOff = startoff;
+		}
+
+		/* How many bytes are within this segment? */
+		if (nbytes > (XLogSegSize - startoff))
+			segbytes = XLogSegSize - startoff;
+		else
+			segbytes = nbytes;
+
+		readbytes = read(sendFile, p, segbytes);
+		if (readbytes <= 0)
+		{
+			char		path[MAXPGPATH];
+
+			XLogFilePath(path, tli, sendSegNo);
+
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not read from log segment %s, offset %u, length %lu: %m",
+							path, sendOff, (unsigned long) segbytes)));
+		}
+
+		/* Update state for read */
+		recptr += readbytes;
+
+		sendOff += readbytes;
+		nbytes -= readbytes;
+		p += readbytes;
+	}
+}
+
+static void
+check_permissions(void)
+{
+	if (!superuser() && !has_rolreplication(GetUserId()))
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 (errmsg("must be superuser or replication role to use changeset extraction"))));
+}
+
+/*
+ * read_page callback for logical decoding contexts.
+ *
+ * Public because it would likely be very helpful for someone writing another
+ * output method outside walsender, e.g. in a bgwriter.
+ */
+int
+logical_read_local_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr,
+	int reqLen, XLogRecPtr targetRecPtr, char *cur_page, TimeLineID *pageTLI)
+{
+	XLogRecPtr	flushptr,
+				loc;
+	int			count;
+
+	loc = targetPagePtr + reqLen;
+	while (1)
+	{
+		/*
+		 * FIXME: we're going to have to do something more intelligent about
+		 * timelines on standby's. Use readTimeLineHistory() and
+		 * tliOfPointInHistory() to get the proper LSN?
+		 */
+		if (!RecoveryInProgress())
+		{
+			*pageTLI = ThisTimeLineID;
+			flushptr = GetFlushRecPtr();
+		}
+		else
+			flushptr = GetXLogReplayRecPtr(pageTLI);
+
+		if (loc <= flushptr)
+			break;
+
+		/*
+		 * XXX: It'd be way nicer to be able to use the walsender waiting logic
+		 * here, but that's not available in all environments.
+		 */
+		CHECK_FOR_INTERRUPTS();
+		pg_usleep(1000L);
+	}
+
+	/* more than one block available */
+	if (targetPagePtr + XLOG_BLCKSZ <= flushptr)
+		count = XLOG_BLCKSZ;
+	/* not enough data there */
+	else if (targetPagePtr + reqLen > flushptr)
+		return -1;
+	/* part of the page available */
+	else
+		count = flushptr - targetPagePtr;
+
+	/* XXX: more sensible/efficient implementation */
+	XLogRead(cur_page, *pageTLI, targetPagePtr, XLOG_BLCKSZ);
+
+	return count;
+}
+
+/*
+ * SQL function for creating a new changeset extraction replication slot.
+ */
+Datum
+pg_create_decoding_replication_slot(PG_FUNCTION_ARGS)
+{
+	Name		name = PG_GETARG_NAME(0);
+	Name		plugin = PG_GETARG_NAME(1);
+
+	char		xpos[MAXFNAMELEN];
+
+	TupleDesc	tupdesc;
+	HeapTuple	tuple;
+	Datum		result;
+	Datum		values[2];
+	bool		nulls[2];
+
+	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
+
+	check_permissions();
+
+	CheckLogicalDecodingRequirements();
+
+	Assert(!MyReplicationSlot);
+
+	/*
+	 * Acquire a logical decoding slot, this will check for conflicting
+	 * names.
+	 */
+	ReplicationSlotCreate(NameStr(*name), true);
+
+	/* make sure we don't end up with an unreleased slot */
+	PG_TRY();
+	{
+		LogicalDecodingContext *ctx = NULL;
+
+		/*
+		 * Create logical decoding context, to build the initial snapshot.
+		 */
+		ctx = CreateDecodingContext(
+			true, NameStr(*plugin), InvalidXLogRecPtr, NIL,
+			logical_read_local_xlog_page, NULL, NULL);
+
+		/* build initial snapshot, might take a while */
+		DecodingContextFindStartpoint(ctx);
+
+		/* Extract the values we want */
+		snprintf(xpos, sizeof(xpos), "%X/%X",
+				 (uint32) (MyReplicationSlot->data.confirmed_flush >> 32),
+				 (uint32) MyReplicationSlot->data.confirmed_flush);
+
+		/* don't need the decoding context anymore */
+		FreeDecodingContext(ctx);
+	}
+	PG_CATCH();
+	{
+		ReplicationSlotRelease();
+		ReplicationSlotDrop(NameStr(*name));
+		PG_RE_THROW();
+	}
+	PG_END_TRY();
+
+	values[0] = CStringGetTextDatum(NameStr(MyReplicationSlot->data.name));
+	values[1] = CStringGetTextDatum(xpos);
+
+	memset(nulls, 0, sizeof(nulls));
+
+	tuple = heap_form_tuple(tupdesc, values, nulls);
+	result = HeapTupleGetDatum(tuple);
+
+	ReplicationSlotRelease();
+
+	PG_RETURN_DATUM(result);
+}
+
+/*
+ * Helper function for the various SQL callable changeset extraction function
+ * that output changes.
+ */
+static Datum
+pg_decoding_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm)
+{
+	Name		name = PG_GETARG_NAME(0);
+
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+	MemoryContext per_query_ctx;
+	MemoryContext oldcontext;
+
+	XLogRecPtr	now;
+	XLogRecPtr	startptr;
+
+	LogicalDecodingContext *ctx;
+
+	ResourceOwner old_resowner = CurrentResourceOwner;
+	ArrayType  *arr;
+	Size		ndim;
+	List	   *options = NIL;
+	DecodingOutputState *p;
+
+	/* check to see if caller supports us returning a tuplestore */
+	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("set-valued function called in context that cannot accept a set")));
+	if (!(rsinfo->allowedModes & SFRM_Materialize))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("materialize mode required, but it is not allowed in this context")));
+
+	/* state to write output to */
+	p = palloc(sizeof(DecodingOutputState));
+
+	/* Build a tuple descriptor for our result type */
+	if (get_call_result_type(fcinfo, NULL, &p->tupdesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
+
+	check_permissions();
+
+	CheckLogicalDecodingRequirements();
+
+	arr = PG_GETARG_ARRAYTYPE_P(2);
+	ndim = ARR_NDIM(arr);
+
+	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
+	oldcontext = MemoryContextSwitchTo(per_query_ctx);
+
+	if (ndim > 1)
+	{
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("start_logical_replication only accept one dimension of arguments")));
+	}
+	else if (array_contains_nulls(arr))
+	{
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			  errmsg("start_logical_replication expects NOT NULL options")));
+	}
+	else if (ndim == 1)
+	{
+		int			nelems;
+		Datum	   *datum_opts;
+		int			i;
+
+		Assert(ARR_ELEMTYPE(arr) == TEXTOID);
+
+		deconstruct_array(arr, TEXTOID, -1, false, 'i',
+						  &datum_opts, NULL, &nelems);
+
+		if (nelems % 2 != 0)
+		{
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("options need to be specified pairwise")));
+		}
+
+		for (i = 0; i < nelems; i += 2)
+		{
+			char	   *name = TextDatumGetCString(datum_opts[i]);
+			char	   *opt = TextDatumGetCString(datum_opts[i + 1]);
+
+			options = lappend(options, makeDefElem(name, (Node *) makeString(opt)));
+		}
+	}
+
+	p->tupstore = tuplestore_begin_heap(true, false, work_mem);
+	rsinfo->returnMode = SFRM_Materialize;
+	rsinfo->setResult = p->tupstore;
+	rsinfo->setDesc = p->tupdesc;
+
+	/*
+	 * XXX: It's impolite to ignore our argument and keep decoding until the
+	 * current position.
+	 */
+	if (!RecoveryInProgress())
+		now = GetFlushRecPtr();
+	else
+		now = GetXLogReplayRecPtr(NULL);
+
+	CheckLogicalDecodingRequirements();
+	ReplicationSlotAcquire(NameStr(*name));
+
+	PG_TRY();
+	{
+		ctx = CreateDecodingContext(false,
+									NULL,
+									MyReplicationSlot->data.confirmed_flush,
+									options,
+									logical_read_local_xlog_page,
+									LogicalOutputPrepareWrite,
+									LogicalOutputWrite);
+
+		MemoryContextSwitchTo(oldcontext);
+
+		ctx->output_writer_private = p;
+
+		startptr = MyReplicationSlot->data.restart_lsn;
+
+		CurrentResourceOwner = ResourceOwnerCreate(CurrentResourceOwner, "logical decoding");
+
+		/* invalidate non-timetravel entries */
+		InvalidateSystemCaches();
+
+		while ((startptr != InvalidXLogRecPtr && startptr < now) ||
+			   (ctx->reader->EndRecPtr && ctx->reader->EndRecPtr < now))
+		{
+			XLogRecord *record;
+			char	   *errm = NULL;
+
+			record = XLogReadRecord(ctx->reader, startptr, &errm);
+			if (errm)
+				elog(ERROR, "%s", errm);
+
+			startptr = InvalidXLogRecPtr;
+
+			/*
+			 * The {begin_txn,change,commit_txn}_wrapper callbacks above will
+			 * store the description into our tuplestore.
+			 */
+			if (record != NULL)
+				LogicalDecodingProcessRecord(ctx, record);
+		}
+	}
+	PG_CATCH();
+	{
+		ReplicationSlotRelease();
+
+		/*
+		 * clear timetravel entries: XXX allowed in aborted TXN?
+		 */
+		InvalidateSystemCaches();
+
+		PG_RE_THROW();
+	}
+	PG_END_TRY();
+
+	tuplestore_donestoring(tupstore);
+
+	CurrentResourceOwner = old_resowner;
+
+	/*
+	 * Next time, start where we left off. (Hunting things, the family
+	 * business..)
+	 */
+	if (ctx->reader->EndRecPtr != InvalidXLogRecPtr && confirm)
+		LogicalConfirmReceivedLocation(ctx->reader->EndRecPtr);
+
+	/* free context, call shutdown callback */
+	FreeDecodingContext(ctx);
+
+	ReplicationSlotRelease();
+	InvalidateSystemCaches();
+
+	return (Datum) 0;
+}
+
+/*
+ * SQL function returning the changestream as text, consuming the data.
+ */
+Datum
+pg_decoding_slot_get_changes(PG_FUNCTION_ARGS)
+{
+	Datum ret = pg_decoding_slot_get_changes_guts(fcinfo, true);
+	return ret;
+}
+
+/*
+ * SQL function returning the changestream as text, only peeking ahead.
+ */
+Datum
+pg_decoding_slot_peek_changes(PG_FUNCTION_ARGS)
+{
+	Datum ret = pg_decoding_slot_get_changes_guts(fcinfo, false);
+	return ret;
+}
+
+/*
+ * SQL function returning the changestream in binary, consuming the data.
+ */
+Datum
+pg_decoding_slot_get_binary_changes(PG_FUNCTION_ARGS)
+{
+	Datum ret = pg_decoding_slot_get_changes_guts(fcinfo, true);
+	return ret;
+}
+
+/*
+ * SQL function returning the changestream in binary, only peeking ahead.
+ */
+Datum
+pg_decoding_slot_peek_binary_changes(PG_FUNCTION_ARGS)
+{
+	Datum ret = pg_decoding_slot_get_changes_guts(fcinfo, false);
+	return ret;
+}
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
new file mode 100644
index 0000000..3743a2a
--- /dev/null
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -0,0 +1,2923 @@
+/*-------------------------------------------------------------------------
+ *
+ * reorderbuffer.c
+ *	  PostgreSQL logical replay/reorder buffer management
+ *
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/replication/reorderbuffer.c
+ *
+ * NOTES
+ *	  This module gets handed individual pieces of transactions in the order
+ *	  they are written to the WAL and is responsible to reassemble them into
+ *	  toplevel transaction sized pieces. When a transaction is completely
+ *	  reassembled - signalled by reading the transaction commit record - it
+ *	  will then call the output plugin (c.f. ReorderBufferCommit()) with the
+ *	  individual changes. The output plugins rely on snapshots built by
+ *	  snapbuild.c which hands them to us.
+ *
+ *	  Transactions and subtransactions/savepoints in postgres are not
+ *	  immediately linked to each other from outside the performing
+ *	  backend. Only at commit/abort (or special xact_assignment records) they
+ *	  are linked together. Which means that we will have to splice together a
+ *	  toplevel transaction from its subtransactions. To do that efficiently we
+ *	  build a binary heap indexed by the smallest current lsn of the individual
+ *	  subtransactions' changestreams. As the individual streams are inherently
+ *	  ordered by LSN - since that is where we build them from - the transaction
+ *	  can easily be reassembled by always using the subtransaction with the
+ *	  smallest current LSN from the heap.
+ *
+ *	  In order to cope with large transactions - which can be several times as
+ *	  big as the available memory - this module supports spooling the contents
+ *	  of a large transactions to disk. When the transaction is replayed the
+ *	  contents of individual (sub-)transactions will be read from disk in
+ *	  chunks.
+ *
+ *	  This module also has to deal with reassembling toast records from the
+ *	  individual chunks stored in WAL. When a new (or initial) version of a
+ *	  tuple is stored in WAL it will always be preceded by the toast chunks
+ *	  emitted for the columns stored out of line. Within a single toplevel
+ *	  transaction there will be no other data carrying records between a row's
+ *	  toast chunks and the row data itself. See ReorderBufferToast* for
+ *	  details.
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "miscadmin.h"
+
+#include "access/transam.h"
+#include "access/xact.h"
+#include "access/rewriteheap.h"
+
+#include "catalog/catalog.h"
+
+#include "common/relpath.h"
+
+#include "lib/binaryheap.h"
+
+#include "replication/logical.h"
+#include "replication/reorderbuffer.h"
+#include "replication/slot.h"
+#include "replication/snapbuild.h" /* just for SnapBuildSnapDecRefcount */
+
+#include "storage/bufmgr.h"
+#include "storage/fd.h"
+#include "storage/sinval.h"
+
+#include "utils/builtins.h"
+#include "utils/combocid.h"
+#include "utils/memdebug.h"
+#include "utils/memutils.h"
+#include "utils/relcache.h"
+#include "utils/relfilenodemap.h"
+#include "utils/resowner.h"
+#include "utils/tqual.h"
+
+/*
+ * For efficiency and simplicity reasons we want to keep Snapshots, CommandIds
+ * and ComboCids in the same list with the user visible INSERT/UPDATE/DELETE
+ * changes. We don't want to leak those internal values to external users
+ * though (they would just use switch()...default:) because that would make it
+ * harder to add to new user visible values.
+ *
+ * This needs to be synchronized with ReorderBufferChangeType! Adjust the
+ * StaticAssertExpr's in ReorderBufferAllocate if you add anything!
+ */
+typedef enum
+{
+	REORDER_BUFFER_CHANGE_INTERNAL_INSERT,
+	REORDER_BUFFER_CHANGE_INTERNAL_UPDATE,
+	REORDER_BUFFER_CHANGE_INTERNAL_DELETE,
+	REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT,
+	REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID,
+	REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID
+} ReorderBufferChangeTypeInternal;
+
+/* entry for a hash table we use to map from xid to our transaction state */
+typedef struct ReorderBufferTXNByIdEnt
+{
+	TransactionId xid;
+	ReorderBufferTXN *txn;
+} ReorderBufferTXNByIdEnt;
+
+/* data structures for (relfilenode, ctid) => (cmin, cmax) mapping */
+typedef struct ReorderBufferTupleCidKey
+{
+	RelFileNode relnode;
+	ItemPointerData tid;
+} ReorderBufferTupleCidKey;
+
+typedef struct ReorderBufferTupleCidEnt
+{
+	ReorderBufferTupleCidKey key;
+	CommandId	cmin;
+	CommandId	cmax;
+	CommandId	combocid;		/* just for debugging */
+} ReorderBufferTupleCidEnt;
+
+/* k-way in-order change iteration support structures */
+typedef struct ReorderBufferIterTXNEntry
+{
+	XLogRecPtr	lsn;
+	ReorderBufferChange *change;
+	ReorderBufferTXN *txn;
+	int			fd;
+	XLogSegNo	segno;
+} ReorderBufferIterTXNEntry;
+
+typedef struct ReorderBufferIterTXNState
+{
+	binaryheap *heap;
+	Size		nr_txns;
+	dlist_head	old_change;
+	ReorderBufferIterTXNEntry entries[FLEXIBLE_ARRAY_MEMBER];
+} ReorderBufferIterTXNState;
+
+/* toast datastructures */
+typedef struct ReorderBufferToastEnt
+{
+	Oid			chunk_id;		/* toast_table.chunk_id */
+	int32		last_chunk_seq; /* toast_table.chunk_seq of the last chunk we
+								 * have seen */
+	Size		num_chunks;		/* number of chunks we've already seen */
+	Size		size;			/* combined size of chunks seen */
+	dlist_head	chunks;			/* linked list of chunks */
+	struct varlena *reconstructed;		/* reconstructed varlena now pointed
+										 * to in main tup */
+} ReorderBufferToastEnt;
+
+
+/* number of changes kept in memory, per transaction */
+const Size	max_memtries = 4096;
+
+/* Size of the slab caches used for frequently allocated objects */
+const Size	max_cached_changes = 4096 * 2;
+const Size	max_cached_tuplebufs = 4096 * 2;		/* ~8MB */
+const Size	max_cached_transactions = 512;
+
+
+/* ---------------------------------------
+ * primary reorderbuffer support routines
+ * ---------------------------------------
+ */
+static ReorderBufferTXN *ReorderBufferGetTXN(ReorderBuffer *rb);
+static void ReorderBufferReturnTXN(ReorderBuffer *rb, ReorderBufferTXN *txn);
+static ReorderBufferTXN *ReorderBufferTXNByXid(ReorderBuffer *rb,
+					  TransactionId xid, bool create, bool *is_new,
+					  XLogRecPtr lsn, bool create_as_top);
+
+static void AssertTXNLsnOrder(ReorderBuffer *rb);
+
+/* ---------------------------------------
+ * support functions for lsn-order iterating over the ->changes of a
+ * transaction and its subtransactions
+ *
+ * used for iteration over the k-way heap merge of a transaction and its
+ * subtransactions
+ * ---------------------------------------
+ */
+static ReorderBufferIterTXNState *ReorderBufferIterTXNInit(ReorderBuffer *rb, ReorderBufferTXN *txn);
+static ReorderBufferChange *
+			ReorderBufferIterTXNNext(ReorderBuffer *rb, ReorderBufferIterTXNState *state);
+static void ReorderBufferIterTXNFinish(ReorderBuffer *rb,
+						   ReorderBufferIterTXNState *state);
+static void ReorderBufferExecuteInvalidations(ReorderBuffer *rb, ReorderBufferTXN *txn);
+
+/*
+ * ---------------------------------------
+ * Disk serialization support functions
+ * ---------------------------------------
+ */
+static void ReorderBufferCheckSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn);
+static void ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn);
+static void ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
+							 int fd, ReorderBufferChange *change);
+static Size ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn,
+							int *fd, XLogSegNo *segno);
+static void ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
+						   char *change);
+static void ReorderBufferRestoreCleanup(ReorderBuffer *rb, ReorderBufferTXN *txn);
+
+static void ReorderBufferFreeSnap(ReorderBuffer *rb, Snapshot snap);
+static Snapshot ReorderBufferCopySnap(ReorderBuffer *rb, Snapshot orig_snap,
+					  ReorderBufferTXN *txn, CommandId cid);
+
+/* ---------------------------------------
+ * toast reassembly support
+ * ---------------------------------------
+ */
+/* Size of an EXTERNAL datum that contains a standard TOAST pointer */
+#define TOAST_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(struct varatt_external))
+
+/* Size of an indirect datum that contains a standard TOAST pointer */
+#define INDIRECT_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(struct varatt_indirect))
+
+static void ReorderBufferToastInitHash(ReorderBuffer *rb, ReorderBufferTXN *txn);
+static void ReorderBufferToastReset(ReorderBuffer *rb, ReorderBufferTXN *txn);
+static void ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
+						  Relation relation, ReorderBufferChange *change);
+static void ReorderBufferToastAppendChunk(ReorderBuffer *rb, ReorderBufferTXN *txn,
+							  Relation relation, ReorderBufferChange *change);
+
+
+/*
+ * Allocate a new ReorderBuffer
+ */
+ReorderBuffer *
+ReorderBufferAllocate(void)
+{
+	ReorderBuffer *buffer;
+	HASHCTL		hash_ctl;
+	MemoryContext new_ctx;
+
+	StaticAssertExpr((int) REORDER_BUFFER_CHANGE_INTERNAL_INSERT == (int) REORDER_BUFFER_CHANGE_INSERT, "out of sync enums");
+	StaticAssertExpr((int) REORDER_BUFFER_CHANGE_INTERNAL_UPDATE == (int) REORDER_BUFFER_CHANGE_UPDATE, "out of sync enums");
+	StaticAssertExpr((int) REORDER_BUFFER_CHANGE_INTERNAL_DELETE == (int) REORDER_BUFFER_CHANGE_DELETE, "out of sync enums");
+
+	/* allocate memory in own context, to have better accountability */
+	new_ctx = AllocSetContextCreate(CurrentMemoryContext,
+									"ReorderBuffer",
+									ALLOCSET_DEFAULT_MINSIZE,
+									ALLOCSET_DEFAULT_INITSIZE,
+									ALLOCSET_DEFAULT_MAXSIZE);
+
+	buffer =
+		(ReorderBuffer *) MemoryContextAlloc(new_ctx, sizeof(ReorderBuffer));
+
+	memset(&hash_ctl, 0, sizeof(hash_ctl));
+
+	buffer->context = new_ctx;
+
+	hash_ctl.keysize = sizeof(TransactionId);
+	hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt);
+	hash_ctl.hash = tag_hash;
+	hash_ctl.hcxt = buffer->context;
+
+	buffer->by_txn = hash_create("ReorderBufferByXid", 1000, &hash_ctl,
+								 HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+
+	buffer->by_txn_last_xid = InvalidTransactionId;
+	buffer->by_txn_last_txn = NULL;
+
+	buffer->nr_cached_transactions = 0;
+	buffer->nr_cached_changes = 0;
+	buffer->nr_cached_tuplebufs = 0;
+
+	buffer->outbuf = NULL;
+	buffer->outbufsize = 0;
+
+	buffer->current_restart_decoding_lsn = InvalidXLogRecPtr;
+
+	dlist_init(&buffer->toplevel_by_lsn);
+	dlist_init(&buffer->cached_transactions);
+	dlist_init(&buffer->cached_changes);
+	slist_init(&buffer->cached_tuplebufs);
+
+	return buffer;
+}
+
+/*
+ * Free a ReorderBuffer
+ */
+void
+ReorderBufferFree(ReorderBuffer *rb)
+{
+	MemoryContext context = rb->context;
+
+	/*
+	 * We free separately allocated data by entirely scrapping reorderbuffer's
+	 * memory context.
+	 */
+	MemoryContextDelete(context);
+}
+
+/*
+ * Get a unused, possibly preallocated, ReorderBufferTXN.
+ */
+static ReorderBufferTXN *
+ReorderBufferGetTXN(ReorderBuffer *rb)
+{
+	ReorderBufferTXN *txn;
+
+	if (rb->nr_cached_transactions > 0)
+	{
+		rb->nr_cached_transactions--;
+		txn = (ReorderBufferTXN *)
+			dlist_container(ReorderBufferTXN, node,
+							dlist_pop_head_node(&rb->cached_transactions));
+	}
+	else
+	{
+		txn = (ReorderBufferTXN *)
+			MemoryContextAlloc(rb->context, sizeof(ReorderBufferTXN));
+	}
+
+	memset(txn, 0, sizeof(ReorderBufferTXN));
+
+	dlist_init(&txn->changes);
+	dlist_init(&txn->tuplecids);
+	dlist_init(&txn->subtxns);
+
+	return txn;
+}
+
+/*
+ * Free an ReorderBufferTXN. Deallocation might be delayed for efficiency
+ * purposes.
+ */
+void
+ReorderBufferReturnTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	/* clean the lookup cache if we were cached (quite likely) */
+	if (rb->by_txn_last_xid == txn->xid)
+	{
+		rb->by_txn_last_xid = InvalidTransactionId;
+		rb->by_txn_last_txn = NULL;
+	}
+
+	if (txn->tuplecid_hash != NULL)
+	{
+		hash_destroy(txn->tuplecid_hash);
+		txn->tuplecid_hash = NULL;
+	}
+
+	if (txn->invalidations)
+	{
+		pfree(txn->invalidations);
+		txn->invalidations = NULL;
+	}
+
+	if (rb->nr_cached_transactions < max_cached_transactions)
+	{
+		rb->nr_cached_transactions++;
+		dlist_push_head(&rb->cached_transactions, &txn->node);
+		VALGRIND_MAKE_MEM_UNDEFINED(txn, sizeof(ReorderBufferTXN));
+		VALGRIND_MAKE_MEM_DEFINED(&txn->node, sizeof(txn->node));
+	}
+	else
+	{
+		pfree(txn);
+	}
+}
+
+/*
+ * Get a unused, possibly preallocated, ReorderBufferChange.
+ */
+ReorderBufferChange *
+ReorderBufferGetChange(ReorderBuffer *rb)
+{
+	ReorderBufferChange *change;
+
+	if (rb->nr_cached_changes)
+	{
+		rb->nr_cached_changes--;
+		change = (ReorderBufferChange *)
+			dlist_container(ReorderBufferChange, node,
+							dlist_pop_head_node(&rb->cached_changes));
+	}
+	else
+	{
+		change = (ReorderBufferChange *)
+			MemoryContextAlloc(rb->context, sizeof(ReorderBufferChange));
+	}
+
+	memset(change, 0, sizeof(ReorderBufferChange));
+	return change;
+}
+
+/*
+ * Free an ReorderBufferChange. Deallocation might be delayed for efficiency
+ * purposes.
+ */
+void
+ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change)
+{
+	switch ((ReorderBufferChangeTypeInternal) change->action_internal)
+	{
+		case REORDER_BUFFER_CHANGE_INTERNAL_INSERT:
+		case REORDER_BUFFER_CHANGE_INTERNAL_UPDATE:
+		case REORDER_BUFFER_CHANGE_INTERNAL_DELETE:
+			if (change->tp.newtuple)
+			{
+				ReorderBufferReturnTupleBuf(rb, change->tp.newtuple);
+				change->tp.newtuple = NULL;
+			}
+
+			if (change->tp.oldtuple)
+			{
+				ReorderBufferReturnTupleBuf(rb, change->tp.oldtuple);
+				change->tp.oldtuple = NULL;
+			}
+			break;
+		case REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT:
+			if (change->snapshot)
+			{
+				ReorderBufferFreeSnap(rb, change->snapshot);
+				change->snapshot = NULL;
+			}
+			break;
+		case REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
+			break;
+		case REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID:
+			break;
+	}
+
+	if (rb->nr_cached_changes < max_cached_changes)
+	{
+		rb->nr_cached_changes++;
+		dlist_push_head(&rb->cached_changes, &change->node);
+		VALGRIND_MAKE_MEM_UNDEFINED(change, sizeof(ReorderBufferChange));
+		VALGRIND_MAKE_MEM_DEFINED(&change->node, sizeof(change->node));
+	}
+	else
+	{
+		pfree(change);
+	}
+}
+
+
+/*
+ * Get a unused, possibly preallocated, ReorderBufferTupleBuf
+ */
+ReorderBufferTupleBuf *
+ReorderBufferGetTupleBuf(ReorderBuffer *rb)
+{
+	ReorderBufferTupleBuf *tuple;
+
+	if (rb->nr_cached_tuplebufs)
+	{
+		rb->nr_cached_tuplebufs--;
+		tuple = slist_container(ReorderBufferTupleBuf, node,
+								slist_pop_head_node(&rb->cached_tuplebufs));
+#ifdef USE_ASSERT_CHECKING
+		memset(tuple, 0xdeadbeef, sizeof(ReorderBufferTupleBuf));
+#endif
+	}
+	else
+	{
+		tuple = (ReorderBufferTupleBuf *)
+			MemoryContextAlloc(rb->context, sizeof(ReorderBufferTupleBuf));
+	}
+
+	return tuple;
+}
+
+/*
+ * Free an ReorderBufferTupleBuf. Deallocation might be delayed for efficiency
+ * purposes.
+ */
+void
+ReorderBufferReturnTupleBuf(ReorderBuffer *rb, ReorderBufferTupleBuf *tuple)
+{
+	if (rb->nr_cached_tuplebufs < max_cached_tuplebufs)
+	{
+		rb->nr_cached_tuplebufs++;
+		slist_push_head(&rb->cached_tuplebufs, &tuple->node);
+		VALGRIND_MAKE_MEM_UNDEFINED(tuple, sizeof(ReorderBufferTupleBuf));
+		VALGRIND_MAKE_MEM_DEFINED(&tuple->node, sizeof(tuple->node));
+	}
+	else
+	{
+		pfree(tuple);
+	}
+}
+
+/*
+ * Return the ReorderBufferTXN from the given buffer, specified by Xid.
+ * If create is true, and a transaction doesn't already exist, create it
+ * (with the given LSN, and as top transaction if that's specified);
+ * when this happens, is_new is set to true.
+ */
+static ReorderBufferTXN *
+ReorderBufferTXNByXid(ReorderBuffer *rb, TransactionId xid, bool create,
+					  bool *is_new, XLogRecPtr lsn, bool create_as_top)
+{
+	ReorderBufferTXN *txn;
+	ReorderBufferTXNByIdEnt *ent;
+	bool		found;
+
+	Assert(TransactionIdIsValid(xid));
+	Assert(!create || lsn != InvalidXLogRecPtr);
+
+	/*
+	 * Check the one-entry lookup cache first
+	 */
+	if (TransactionIdIsValid(rb->by_txn_last_xid) &&
+		rb->by_txn_last_xid == xid)
+	{
+		txn = rb->by_txn_last_txn;
+
+		if (txn != NULL)
+		{
+			/* found it, and it's valid */
+			if (is_new)
+				*is_new = false;
+			return txn;
+		}
+
+		/*
+		 * cached as non-existant, and asked not to create? Then nothing else
+		 * to do.
+		 */
+		if (!create)
+			return NULL;
+		/* otherwise fall through to create it */
+	}
+
+	/*
+	 * If the cache wasn't hit or it yielded an "does-not-exist" and we want
+	 * to create an entry.
+	 */
+
+	/* search the lookup table */
+	ent = (ReorderBufferTXNByIdEnt *)
+		hash_search(rb->by_txn,
+					(void *) &xid,
+					create ? HASH_ENTER : HASH_FIND,
+					&found);
+	if (found)
+		txn = ent->txn;
+	else if (create)
+	{
+		/* initialize the new entry, if creation was requested */
+		Assert(ent != NULL);
+
+		ent->txn = ReorderBufferGetTXN(rb);
+		ent->txn->xid = xid;
+		txn = ent->txn;
+		txn->first_lsn = lsn;
+		txn->restart_decoding_lsn = rb->current_restart_decoding_lsn;
+
+		if (create_as_top)
+		{
+			dlist_push_tail(&rb->toplevel_by_lsn, &txn->node);
+			AssertTXNLsnOrder(rb);
+		}
+	}
+	else
+		txn = NULL;				/* not found and not asked to create */
+
+	/* update cache */
+	rb->by_txn_last_xid = xid;
+	rb->by_txn_last_txn = txn;
+
+	if (is_new)
+		*is_new = !found;
+
+	Assert(!create || !!txn);
+	return txn;
+}
+
+/*
+ * Queue a change into a transaction so it can be replayed upon commit.
+ */
+void
+ReorderBufferQueueChange(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn,
+					   ReorderBufferChange *change)
+{
+	ReorderBufferTXN *txn;
+
+	txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
+
+	change->lsn = lsn;
+	Assert(InvalidXLogRecPtr != lsn);
+	dlist_push_tail(&txn->changes, &change->node);
+	txn->nentries++;
+	txn->nentries_mem++;
+
+	ReorderBufferCheckSerializeTXN(rb, txn);
+}
+
+static void
+AssertTXNLsnOrder(ReorderBuffer *rb)
+{
+#ifdef USE_ASSERT_CHECKING
+	dlist_iter	iter;
+	XLogRecPtr	prev_first_lsn = InvalidXLogRecPtr;
+
+	dlist_foreach(iter, &rb->toplevel_by_lsn)
+	{
+		ReorderBufferTXN *cur_txn;
+
+		cur_txn = dlist_container(ReorderBufferTXN, node, iter.cur);
+		Assert(cur_txn->first_lsn != InvalidXLogRecPtr);
+
+		if (cur_txn->end_lsn != InvalidXLogRecPtr)
+			Assert(cur_txn->first_lsn <= cur_txn->end_lsn);
+
+		if (prev_first_lsn != InvalidXLogRecPtr)
+			Assert(prev_first_lsn < cur_txn->first_lsn);
+
+		Assert(!cur_txn->is_known_as_subxact);
+		prev_first_lsn = cur_txn->first_lsn;
+	}
+#endif
+}
+
+ReorderBufferTXN *
+ReorderBufferGetOldestTXN(ReorderBuffer *rb)
+{
+	ReorderBufferTXN *txn;
+
+	if (dlist_is_empty(&rb->toplevel_by_lsn))
+		return NULL;
+
+	AssertTXNLsnOrder(rb);
+
+	txn = dlist_head_element(ReorderBufferTXN, node, &rb->toplevel_by_lsn);
+
+	Assert(!txn->is_known_as_subxact);
+	Assert(txn->first_lsn != InvalidXLogRecPtr);
+	return txn;
+}
+
+void
+ReorderBufferSetRestartPoint(ReorderBuffer *rb, XLogRecPtr ptr)
+{
+	rb->current_restart_decoding_lsn = ptr;
+}
+
+void
+ReorderBufferAssignChild(ReorderBuffer *rb, TransactionId xid,
+						 TransactionId subxid, XLogRecPtr lsn)
+{
+	ReorderBufferTXN *txn;
+	ReorderBufferTXN *subtxn;
+	bool		new_top;
+	bool		new_sub;
+
+	txn = ReorderBufferTXNByXid(rb, xid, true, &new_top, lsn, true);
+	subtxn = ReorderBufferTXNByXid(rb, subxid, true, &new_sub, lsn, false);
+
+	if (new_sub)
+	{
+		/*
+		 * we assign subtransactions to top level transaction even if we don't
+		 * have data for it yet, assignment records frequently reference xids
+		 * that have not yet produced any records. Knowing those aren't top
+		 * level xids allows us to make processing cheaper in some places.
+		 */
+		dlist_push_tail(&txn->subtxns, &subtxn->node);
+		txn->nsubtxns++;
+	}
+	else if (!subtxn->is_known_as_subxact)
+	{
+		subtxn->is_known_as_subxact = true;
+		Assert(subtxn->nsubtxns == 0);
+
+		/* remove from lsn order list of top-level transactions */
+		dlist_delete(&subtxn->node);
+
+		/* add to toplevel transaction */
+		dlist_push_tail(&txn->subtxns, &subtxn->node);
+		txn->nsubtxns++;
+	}
+	else if (new_top)
+	{
+		elog(ERROR, "existing subxact assigned to unknown toplevel xact");
+	}
+}
+
+/*
+ * Associate a subtransaction with its toplevel transaction at commit
+ * time. There may be no further changes added after this.
+ */
+void
+ReorderBufferCommitChild(ReorderBuffer *rb, TransactionId xid,
+						 TransactionId subxid, XLogRecPtr commit_lsn,
+						 XLogRecPtr end_lsn)
+{
+	ReorderBufferTXN *txn;
+	ReorderBufferTXN *subtxn;
+
+	subtxn = ReorderBufferTXNByXid(rb, subxid, false, NULL,
+								   InvalidXLogRecPtr, false);
+
+	/*
+	 * No need to do anything if that subtxn didn't contain any changes
+	 */
+	if (!subtxn)
+		return;
+
+	txn = ReorderBufferTXNByXid(rb, xid, false, NULL, commit_lsn, true);
+
+	if (txn == NULL)
+		elog(ERROR, "subxact logged without previous toplevel record");
+
+	subtxn->final_lsn = commit_lsn;
+	subtxn->end_lsn = end_lsn;
+
+	if (!subtxn->is_known_as_subxact)
+	{
+		subtxn->is_known_as_subxact = true;
+		Assert(subtxn->nsubtxns == 0);
+
+		/* remove from lsn order list of top-level transactions */
+		dlist_delete(&subtxn->node);
+
+		/* add to subtransaction list */
+		dlist_push_tail(&txn->subtxns, &subtxn->node);
+		txn->nsubtxns++;
+	}
+}
+
+
+/*
+ * Support for efficiently iterating over a transaction's and its
+ * subtransactions' changes.
+ *
+ * We do by doing a k-way merge between transactions/subtransactions. For that
+ * we model the current heads of the different transactions as a binary heap
+ * so we easily know which (sub-)transaction has the change with the smallest
+ * lsn next.
+ *
+ * We assume the changes in individual transactions are already sorted by LSN.
+ */
+
+/*
+ * Binary heap comparison function.
+ */
+static int
+ReorderBufferIterCompare(Datum a, Datum b, void *arg)
+{
+	ReorderBufferIterTXNState *state = (ReorderBufferIterTXNState *) arg;
+	XLogRecPtr	pos_a = state->entries[DatumGetInt32(a)].lsn;
+	XLogRecPtr	pos_b = state->entries[DatumGetInt32(b)].lsn;
+
+	if (pos_a < pos_b)
+		return 1;
+	else if (pos_a == pos_b)
+		return 0;
+	return -1;
+}
+
+/*
+ * Allocate & initialize an iterator which iterates in lsn order over a
+ * transaction and all its subtransactions.
+ */
+static ReorderBufferIterTXNState *
+ReorderBufferIterTXNInit(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	Size		nr_txns = 0;
+	ReorderBufferIterTXNState *state;
+	dlist_iter	cur_txn_i;
+	int32		off;
+
+	/*
+	 * Calculate the size of our heap: one element for every transaction that
+	 * contains changes.  (Besides the transactions already in the reorder
+	 * buffer, we count the one we were directly passed.)
+	 */
+	if (txn->nentries > 0)
+		nr_txns++;
+
+	dlist_foreach(cur_txn_i, &txn->subtxns)
+	{
+		ReorderBufferTXN *cur_txn;
+
+		cur_txn = dlist_container(ReorderBufferTXN, node, cur_txn_i.cur);
+
+		if (cur_txn->nentries > 0)
+			nr_txns++;
+	}
+
+	/*
+	 * XXX: Add fastpath for the rather common nr_txns=1 case, no need to
+	 * allocate/build a heap in that case.
+	 */
+
+	/* allocate iteration state */
+	state = (ReorderBufferIterTXNState *)
+		MemoryContextAllocZero(rb->context,
+							   sizeof(ReorderBufferIterTXNState) +
+							   sizeof(ReorderBufferIterTXNEntry) * nr_txns);
+
+	state->nr_txns = nr_txns;
+	dlist_init(&state->old_change);
+
+	for (off = 0; off < state->nr_txns; off++)
+	{
+		state->entries[off].fd = -1;
+		state->entries[off].segno = 0;
+	}
+
+	/* allocate heap */
+	state->heap = binaryheap_allocate(state->nr_txns,
+									  ReorderBufferIterCompare,
+									  state);
+
+	/*
+	 * Now insert items into the binary heap, unordered.  (We will run a heap
+	 * assembly step at the end; this is more efficient.)
+	 */
+
+	off = 0;
+
+	/* add toplevel transaction if it contains changes */
+	if (txn->nentries > 0)
+	{
+		ReorderBufferChange *cur_change;
+
+		if (txn->nentries != txn->nentries_mem)
+			ReorderBufferRestoreChanges(rb, txn, &state->entries[off].fd,
+										&state->entries[off].segno);
+
+		cur_change = dlist_head_element(ReorderBufferChange, node,
+										&txn->changes);
+
+		state->entries[off].lsn = cur_change->lsn;
+		state->entries[off].change = cur_change;
+		state->entries[off].txn = txn;
+
+		binaryheap_add_unordered(state->heap, Int32GetDatum(off++));
+	}
+
+	/* add subtransactions if they contain changes */
+	dlist_foreach(cur_txn_i, &txn->subtxns)
+	{
+		ReorderBufferTXN *cur_txn;
+
+		cur_txn = dlist_container(ReorderBufferTXN, node, cur_txn_i.cur);
+
+		if (cur_txn->nentries > 0)
+		{
+			ReorderBufferChange *cur_change;
+
+			if (txn->nentries != txn->nentries_mem)
+				ReorderBufferRestoreChanges(rb, cur_txn,
+											&state->entries[off].fd,
+											&state->entries[off].segno);
+
+			cur_change = dlist_head_element(ReorderBufferChange, node,
+											&cur_txn->changes);
+
+			state->entries[off].lsn = cur_change->lsn;
+			state->entries[off].change = cur_change;
+			state->entries[off].txn = cur_txn;
+
+			binaryheap_add_unordered(state->heap, Int32GetDatum(off++));
+		}
+	}
+
+	/* assemble a valid binary heap */
+	binaryheap_build(state->heap);
+
+	return state;
+}
+
+/*
+ * FIXME: better comment and/or name
+ */
+static void
+ReorderBufferRestoreCleanup(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	XLogSegNo	first;
+	XLogSegNo	cur;
+	XLogSegNo	last;
+
+	Assert(txn->first_lsn != InvalidXLogRecPtr);
+	Assert(txn->final_lsn != InvalidXLogRecPtr);
+
+	XLByteToSeg(txn->first_lsn, first);
+	XLByteToSeg(txn->final_lsn, last);
+
+	/* iterate over all possible filenames, and delete them */
+	for (cur = first; cur <= last; cur++)
+	{
+		char		path[MAXPGPATH];
+		XLogRecPtr	recptr;
+
+		XLogSegNoOffsetToRecPtr(cur, 0, recptr);
+
+		sprintf(path, "pg_replslot/%s/xid-%u-lsn-%X-%X.snap",
+				NameStr(MyReplicationSlot->data.name), txn->xid,
+				(uint32) (recptr >> 32), (uint32) recptr);
+		if (unlink(path) != 0 && errno != ENOENT)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not unlink file \"%s\": %m", path)));
+	}
+}
+
+/*
+ * Return the next change when iterating over a transaction and its
+ * subtransaction.
+ *
+ * Returns NULL when no further changes exist.
+ */
+static ReorderBufferChange *
+ReorderBufferIterTXNNext(ReorderBuffer *rb, ReorderBufferIterTXNState *state)
+{
+	ReorderBufferChange *change;
+	ReorderBufferIterTXNEntry *entry;
+	int32		off;
+
+	/* nothing there anymore */
+	if (state->heap->bh_size == 0)
+		return NULL;
+
+	off = DatumGetInt32(binaryheap_first(state->heap));
+	entry = &state->entries[off];
+
+	/* free memory we might have "leaked" in the previous *Next call */
+	if (!dlist_is_empty(&state->old_change))
+	{
+		change = dlist_container(ReorderBufferChange, node,
+								 dlist_pop_head_node(&state->old_change));
+		ReorderBufferReturnChange(rb, change);
+		Assert(dlist_is_empty(&state->old_change));
+	}
+
+	change = entry->change;
+
+	/*
+	 * update heap with information about which transaction has the next
+	 * relevant change in LSN order
+	 */
+
+	/* there are in-memory changes */
+	if (dlist_has_next(&entry->txn->changes, &entry->change->node))
+	{
+		dlist_node *next = dlist_next_node(&entry->txn->changes, &change->node);
+		ReorderBufferChange *next_change =
+		dlist_container(ReorderBufferChange, node, next);
+
+		/* txn stays the same */
+		state->entries[off].lsn = next_change->lsn;
+		state->entries[off].change = next_change;
+
+		binaryheap_replace_first(state->heap, Int32GetDatum(off));
+		return change;
+	}
+
+	/* try to load changes from disk */
+	if (entry->txn->nentries != entry->txn->nentries_mem)
+	{
+		/*
+		 * Ugly: restoring changes will reuse *Change records, thus delete the
+		 * current one from the per-tx list and only free in the next call.
+		 */
+		dlist_delete(&change->node);
+		dlist_push_tail(&state->old_change, &change->node);
+
+		if (ReorderBufferRestoreChanges(rb, entry->txn, &entry->fd,
+										&state->entries[off].segno))
+		{
+			/* successfully restored changes from disk */
+			ReorderBufferChange *next_change =
+			dlist_head_element(ReorderBufferChange, node,
+							   &entry->txn->changes);
+
+			elog(DEBUG2, "restored %u/%u changes from disk",
+				 (uint32) entry->txn->nentries_mem,
+				 (uint32) entry->txn->nentries);
+
+			Assert(entry->txn->nentries_mem);
+			/* txn stays the same */
+			state->entries[off].lsn = next_change->lsn;
+			state->entries[off].change = next_change;
+			binaryheap_replace_first(state->heap, Int32GetDatum(off));
+
+			return change;
+		}
+	}
+
+	/* ok, no changes there anymore, remove */
+	binaryheap_remove_first(state->heap);
+
+	return change;
+}
+
+/*
+ * Deallocate the iterator
+ */
+static void
+ReorderBufferIterTXNFinish(ReorderBuffer *rb,
+						   ReorderBufferIterTXNState *state)
+{
+	int32		off;
+
+	for (off = 0; off < state->nr_txns; off++)
+	{
+		if (state->entries[off].fd != -1)
+			CloseTransientFile(state->entries[off].fd);
+	}
+
+	/* free memory we might have "leaked" in the last *Next call */
+	if (!dlist_is_empty(&state->old_change))
+	{
+		ReorderBufferChange *change;
+
+		change = dlist_container(ReorderBufferChange, node,
+								 dlist_pop_head_node(&state->old_change));
+		ReorderBufferReturnChange(rb, change);
+		Assert(dlist_is_empty(&state->old_change));
+	}
+
+	binaryheap_free(state->heap);
+	pfree(state);
+}
+
+/*
+ * Cleanup the contents of a transaction, usually after the transaction
+ * committed or aborted.
+ */
+static void
+ReorderBufferCleanupTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	bool		found;
+	dlist_mutable_iter iter;
+
+	/* cleanup subtransactions & their changes */
+	dlist_foreach_modify(iter, &txn->subtxns)
+	{
+		ReorderBufferTXN *subtxn;
+
+		subtxn = dlist_container(ReorderBufferTXN, node, iter.cur);
+
+		/*
+		 * Subtransactions are always associated to the toplevel TXN, even if
+		 * they originally were happening inside another subtxn, so we won't
+		 * ever recurse more than one level deep here.
+		 */
+		Assert(subtxn->is_known_as_subxact);
+		Assert(subtxn->nsubtxns == 0);
+
+		ReorderBufferCleanupTXN(rb, subtxn);
+	}
+
+	/* cleanup changes in the toplevel txn */
+	dlist_foreach_modify(iter, &txn->changes)
+	{
+		ReorderBufferChange *change;
+
+		change = dlist_container(ReorderBufferChange, node, iter.cur);
+
+		ReorderBufferReturnChange(rb, change);
+	}
+
+	/*
+	 * Cleanup the tuplecids we stored for decoding catalog snapshot
+	 * access. They are always stored in the toplevel transaction.
+	 */
+	dlist_foreach_modify(iter, &txn->tuplecids)
+	{
+		ReorderBufferChange *change;
+
+		change = dlist_container(ReorderBufferChange, node, iter.cur);
+		Assert(change->action_internal == REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID);
+		ReorderBufferReturnChange(rb, change);
+	}
+
+	if (txn->base_snapshot != NULL)
+	{
+		SnapBuildSnapDecRefcount(txn->base_snapshot);
+		txn->base_snapshot = NULL;
+	}
+
+	/* delete from list of known subxacts */
+	if (txn->is_known_as_subxact)
+	{
+		/* FIXME: adjust nsubxacts count of parent */
+		dlist_delete(&txn->node);
+	}
+	/* delete from LSN ordered list of toplevel TXNs */
+	else
+	{
+		dlist_delete(&txn->node);
+	}
+
+	/* now remove reference from buffer */
+	hash_search(rb->by_txn,
+				(void *) &txn->xid,
+				HASH_REMOVE,
+				&found);
+	Assert(found);
+
+	/* remove entries spilled to disk */
+	if (txn->nentries != txn->nentries_mem)
+		ReorderBufferRestoreCleanup(rb, txn);
+
+	/* deallocate */
+	ReorderBufferReturnTXN(rb, txn);
+}
+
+/*
+ * Build a hash with a (relfilenode, ctid) -> (cmin, cmax) mapping for use by
+ * tqual.c's HeapTupleSatisfiesMVCCDuringDecoding.
+ */
+static void
+ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	dlist_iter	iter;
+	HASHCTL		hash_ctl;
+
+	if (!txn->has_catalog_changes || dlist_is_empty(&txn->tuplecids))
+		return;
+
+	memset(&hash_ctl, 0, sizeof(hash_ctl));
+
+	hash_ctl.keysize = sizeof(ReorderBufferTupleCidKey);
+	hash_ctl.entrysize = sizeof(ReorderBufferTupleCidEnt);
+	hash_ctl.hash = tag_hash;
+	hash_ctl.hcxt = rb->context;
+
+	/*
+	 * create the hash with the exact number of to-be-stored tuplecids from
+	 * the start
+	 */
+	txn->tuplecid_hash =
+		hash_create("ReorderBufferTupleCid", txn->ntuplecids, &hash_ctl,
+					HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+
+	dlist_foreach(iter, &txn->tuplecids)
+	{
+		ReorderBufferTupleCidKey key;
+		ReorderBufferTupleCidEnt *ent;
+		bool		found;
+		ReorderBufferChange *change;
+
+		change = dlist_container(ReorderBufferChange, node, iter.cur);
+
+		Assert(change->action_internal == REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID);
+
+		/* be careful about padding */
+		memset(&key, 0, sizeof(ReorderBufferTupleCidKey));
+
+		key.relnode = change->tuplecid.node;
+
+		ItemPointerCopy(&change->tuplecid.tid,
+						&key.tid);
+
+		ent = (ReorderBufferTupleCidEnt *)
+			hash_search(txn->tuplecid_hash,
+						(void *) &key,
+						HASH_ENTER | HASH_FIND,
+						&found);
+		if (!found)
+		{
+			ent->cmin = change->tuplecid.cmin;
+			ent->cmax = change->tuplecid.cmax;
+			ent->combocid = change->tuplecid.combocid;
+		}
+		else
+		{
+			Assert(ent->cmin == change->tuplecid.cmin);
+			Assert(ent->cmax == InvalidCommandId ||
+				   ent->cmax == change->tuplecid.cmax);
+
+			/*
+			 * if the tuple got valid in this transaction and now got deleted
+			 * we already have a valid cmin stored. The cmax will be
+			 * InvalidCommandId though.
+			 */
+			ent->cmax = change->tuplecid.cmax;
+		}
+	}
+}
+
+/*
+ * Copy a provided snapshot so we can modify it privately. This is needed so
+ * that catalog modifying transactions can look into intermediate catalog
+ * states.
+ */
+static Snapshot
+ReorderBufferCopySnap(ReorderBuffer *rb, Snapshot orig_snap,
+					  ReorderBufferTXN *txn, CommandId cid)
+{
+	Snapshot	snap;
+	dlist_iter	iter;
+	int			i = 0;
+	Size		size;
+
+	size = sizeof(SnapshotData) +
+		sizeof(TransactionId) * orig_snap->xcnt +
+		sizeof(TransactionId) * (txn->nsubtxns + 1);
+
+	snap = MemoryContextAllocZero(rb->context, size);
+	memcpy(snap, orig_snap, sizeof(SnapshotData));
+
+	snap->copied = true;
+	snap->active_count = 0;
+	snap->regd_count = 0;
+	snap->xip = (TransactionId *) (snap + 1);
+
+	memcpy(snap->xip, orig_snap->xip, sizeof(TransactionId) * snap->xcnt);
+
+	/*
+	 * ->subxip contains all txids that belong to our transaction which we
+	 * need to check via cmin/cmax. Thats why we store the toplevel
+	 * transaction in there as well.
+	 */
+	snap->subxip = snap->xip + snap->xcnt;
+	snap->subxip[i++] = txn->xid;
+
+	/*
+	 * XXX: ->nsubxcnt can be out of date when subtransactions abort, count
+	 * manually.
+	 */
+	snap->subxcnt = 1;
+
+	dlist_foreach(iter, &txn->subtxns)
+	{
+		ReorderBufferTXN *sub_txn;
+
+		sub_txn = dlist_container(ReorderBufferTXN, node, iter.cur);
+		snap->subxip[i++] = sub_txn->xid;
+		snap->subxcnt++;
+	}
+
+	/* sort so we can bsearch() later */
+	qsort(snap->subxip, snap->subxcnt, sizeof(TransactionId), xidComparator);
+
+	/* store the specified current CommandId */
+	snap->curcid = cid;
+
+	return snap;
+}
+
+/*
+ * Free a previously ReorderBufferCopySnap'ed snapshot
+ */
+static void
+ReorderBufferFreeSnap(ReorderBuffer *rb, Snapshot snap)
+{
+	if (snap->copied)
+		pfree(snap);
+	else
+		SnapBuildSnapDecRefcount(snap);
+}
+
+/*
+ * Commit a transaction and replay all actions that previously have been
+ * ReorderBufferQueueChange'd in the toplevel TX or any of the subtransactions
+ * assigned via ReorderBufferCommitChild.
+ */
+void
+ReorderBufferCommit(ReorderBuffer *rb, TransactionId xid,
+					XLogRecPtr commit_lsn, XLogRecPtr end_lsn,
+					TimestampTz commit_time)
+{
+	ReorderBufferTXN *txn;
+	ReorderBufferIterTXNState *iterstate = NULL;
+	ReorderBufferChange *change;
+
+	volatile CommandId	command_id = FirstCommandId;
+	volatile Snapshot	snapshot_now;
+	volatile bool		tx_started = false;
+	volatile bool		subtx_started = false;
+
+	txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr,
+								false);
+
+	/* empty transaction */
+	if (txn == NULL)
+		return;
+
+	txn->final_lsn = commit_lsn;
+	txn->end_lsn = end_lsn;
+	txn->commit_time = commit_time;
+
+	/* serialize the last bunch of changes if we need start earlier anyway */
+	if (txn->nentries_mem != txn->nentries)
+		ReorderBufferSerializeTXN(rb, txn);
+
+	/*
+	 * If this transaction didn't have any real changes in our database, it's
+	 * OK not to have a snapshot.
+	 */
+	if (txn->base_snapshot == NULL)
+	{
+		Assert(txn->ninvalidations == 0);
+		ReorderBufferCleanupTXN(rb, txn);
+		return;
+	}
+
+	snapshot_now = txn->base_snapshot;
+
+	ReorderBufferBuildTupleCidHash(rb, txn);
+
+	/* setup initial snapshot */
+	SetupDecodingSnapshots(snapshot_now, txn->tuplecid_hash);
+
+	PG_TRY();
+	{
+		tx_started = false;
+
+		/*
+		 * Decoding needs access to syscaches et al., which in turn use
+		 * heavyweight locks and such. Thus we need to have enough state around
+		 * to keep track of those. The easiest way is to simply use a
+		 * transaction internally. That also allows us to easily enforce that
+		 * nothing writes to the database by checking for xid assignments.
+		 *
+		 * When we're called via the SQL SRF there's already a transaction
+		 * started, so start an explicit subtransaction there.
+		 */
+		if (IsTransactionOrTransactionBlock())
+		{
+			BeginInternalSubTransaction("replay");
+			subtx_started = true;
+
+			if (GetTopTransactionIdIfAny() != InvalidTransactionId)
+				elog(ERROR, "cannot replay using sub, already allocated xid %u",
+					 GetTopTransactionIdIfAny());
+		}
+		else
+		{
+			StartTransactionCommand();
+			tx_started = true;
+
+			if (GetTopTransactionIdIfAny() != InvalidTransactionId)
+				elog(ERROR, "cannot replay using top, already allocated xid %u",
+					 GetTopTransactionIdIfAny());
+
+		}
+
+		rb->begin(rb, txn);
+
+		iterstate = ReorderBufferIterTXNInit(rb, txn);
+		while ((change = ReorderBufferIterTXNNext(rb, iterstate)))
+		{
+			Relation	relation = NULL;
+			Oid			reloid;
+
+			switch ((ReorderBufferChangeTypeInternal) change->action_internal)
+			{
+				case REORDER_BUFFER_CHANGE_INTERNAL_INSERT:
+				case REORDER_BUFFER_CHANGE_INTERNAL_UPDATE:
+				case REORDER_BUFFER_CHANGE_INTERNAL_DELETE:
+					Assert(snapshot_now);
+
+					reloid = RelidByRelfilenode(change->tp.relnode.spcNode,
+												change->tp.relnode.relNode);
+
+					/*
+					 * catalog tuple without data, while catalog has been
+					 * rewritten
+					 */
+					if (reloid == InvalidOid &&
+						change->tp.newtuple == NULL &&
+						change->tp.oldtuple == NULL)
+						continue;
+					else if (reloid == InvalidOid)
+						elog(ERROR, "could not lookup relation %s",
+							 relpathperm(change->tp.relnode, MAIN_FORKNUM));
+
+					relation = RelationIdGetRelation(reloid);
+
+					if (relation == NULL)
+						elog(ERROR, "could open relation descriptor %s",
+							 relpathperm(change->tp.relnode, MAIN_FORKNUM));
+
+					if (RelationIsLogicallyLogged(relation))
+					{
+						/* user-triggered change */
+						if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
+						{
+						}
+						else if (!IsToastRelation(relation))
+						{
+							ReorderBufferToastReplace(rb, txn, relation, change);
+							rb->apply_change(rb, txn, relation, change);
+							ReorderBufferToastReset(rb, txn);
+						}
+						/* we're not interested in toast deletions */
+						else if (change->action == REORDER_BUFFER_CHANGE_INSERT)
+						{
+							/*
+							 * need to reassemble change in memory, ensure it
+							 * doesn't get reused till we're done.
+							 */
+							dlist_delete(&change->node);
+							ReorderBufferToastAppendChunk(rb, txn, relation,
+														  change);
+						}
+
+					}
+					RelationClose(relation);
+					break;
+				case REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT:
+					/* XXX: we could skip snapshots in non toplevel txns */
+
+					/* get rid of the old */
+					RevertFromDecodingSnapshots(false);
+
+					if (snapshot_now->copied)
+					{
+						ReorderBufferFreeSnap(rb, snapshot_now);
+						snapshot_now =
+							ReorderBufferCopySnap(rb, change->snapshot,
+												  txn, command_id);
+					}
+
+					/*
+					 * restored from disk, we need to be careful not to double
+					 * free. We could introduce refcounting for that, but for
+					 * now this seems infrequent enough not to care.
+					 */
+					else if (change->snapshot->copied)
+					{
+						snapshot_now =
+							ReorderBufferCopySnap(rb, change->snapshot,
+												  txn, command_id);
+					}
+					else
+					{
+						snapshot_now = change->snapshot;
+					}
+
+
+					/* and start with the new one */
+					SetupDecodingSnapshots(snapshot_now, txn->tuplecid_hash);
+					break;
+
+				case REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
+					Assert(change->command_id != InvalidCommandId);
+
+					if (command_id < change->command_id)
+					{
+						command_id = change->command_id;
+
+						if (!snapshot_now->copied)
+						{
+							/* we don't use the global one anymore */
+							snapshot_now = ReorderBufferCopySnap(rb, snapshot_now,
+																 txn, command_id);
+						}
+
+						snapshot_now->curcid = command_id;
+
+						RevertFromDecodingSnapshots(false);
+						SetupDecodingSnapshots(snapshot_now, txn->tuplecid_hash);
+
+						/*
+						 * Every time the CommandId is incremented, we could
+						 * see new catalog contents, so execute all
+						 * invalidations.
+						 */
+						ReorderBufferExecuteInvalidations(rb, txn);
+					}
+
+					break;
+
+				case REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID:
+					elog(ERROR, "tuplecid value in normal queue");
+					break;
+			}
+		}
+
+		ReorderBufferIterTXNFinish(rb, iterstate);
+
+		/* call commit callback */
+		rb->commit(rb, txn, commit_lsn);
+
+		/* make sure nothing has written anything */
+		if (GetTopTransactionIdIfAny() != InvalidTransactionId)
+			elog(ERROR, "cannot write during replay, allocated xid %u",
+				 GetTopTransactionIdIfAny());
+
+		/* make sure there's no cache pollution */
+		ReorderBufferExecuteInvalidations(rb, txn);
+
+		/* cleanup */
+		RevertFromDecodingSnapshots(false);
+
+		/*
+		 * Abort subtransaction or aborting transaction as a whole has the
+		 * right semantics. We want all locks acquired in here to be released,
+		 * not reassinged to the parent and we do not want any database access
+		 * have persistent effects.
+		 */
+		if (subtx_started)
+			RollbackAndReleaseCurrentSubTransaction();
+		else if (tx_started)
+			AbortCurrentTransaction();
+
+		if (snapshot_now->copied)
+			ReorderBufferFreeSnap(rb, snapshot_now);
+
+		ReorderBufferCleanupTXN(rb, txn);
+	}
+	PG_CATCH();
+	{
+		/* TODO: Encapsulate cleanup from the PG_TRY and PG_CATCH blocks */
+		if (iterstate)
+			ReorderBufferIterTXNFinish(rb, iterstate);
+
+		RevertFromDecodingSnapshots(true);
+
+		if (snapshot_now->copied)
+			ReorderBufferFreeSnap(rb, snapshot_now);
+
+		if (subtx_started)
+			RollbackAndReleaseCurrentSubTransaction();
+		else if (tx_started)
+			AbortCurrentTransaction();
+
+		/*
+		 * Invalidations in an aborted transactions aren't allowed to do
+		 * catalog access, so we don't need to still have the snapshot setup.
+		 */
+		ReorderBufferExecuteInvalidations(rb, txn);
+
+		/*
+		 * don't do a ReorderBufferCleanupTXN here, with the vague idea of
+		 * allowing to retry decoding.
+		 */
+		PG_RE_THROW();
+	}
+	PG_END_TRY();
+}
+
+/*
+ * Abort a transaction that possibly has previous changes. Needs to be done
+ * independently for toplevel and subtransactions.
+ */
+void
+ReorderBufferAbort(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn)
+{
+	ReorderBufferTXN *txn;
+
+	txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr,
+								false);
+
+	/* no changes in this commit */
+	if (txn == NULL)
+		return;
+
+	txn->final_lsn = lsn;
+
+	ReorderBufferCleanupTXN(rb, txn);
+}
+
+/*
+ * Abort all transactions that aren't actually running anymore because the
+ * server restarted.
+ */
+void
+ReorderBufferAbortOld(ReorderBuffer *rb, TransactionId oldestRunningXid)
+{
+	dlist_mutable_iter it;
+
+	dlist_foreach_modify(it, &rb->toplevel_by_lsn)
+	{
+		ReorderBufferTXN * txn;
+
+		txn = dlist_container(ReorderBufferTXN, node, it.cur);
+
+		/*
+		 * Iterate through all (potential) toplevel TXNs and abort all that
+		 * are older than what possibly can be running. Once we've found the
+		 * first that is alive we stop, there might be some that acquired an
+		 * xid earlier but started writing later, but it's unlikely and they
+		 * will cleaned up in a later call to ReorderBufferAbortOld().
+		 */
+		if (TransactionIdPrecedes(txn->xid, oldestRunningXid))
+		{
+			elog(DEBUG1, "aborting old transaction %u", txn->xid);
+			ReorderBufferCleanupTXN(rb, txn);
+		}
+		else
+			return;
+	}
+}
+
+/*
+ * Check whether a transaction is already known in this module
+ */
+bool
+ReorderBufferIsXidKnown(ReorderBuffer *rb, TransactionId xid)
+{
+	ReorderBufferTXN *txn;
+
+	txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr,
+								false);
+	return txn != NULL;
+}
+
+/*
+ * Add a new snapshot to this transaction that is only used after lsn 'lsn'.
+ */
+void
+ReorderBufferAddSnapshot(ReorderBuffer *rb, TransactionId xid,
+						 XLogRecPtr lsn, Snapshot snap)
+{
+	ReorderBufferChange *change = ReorderBufferGetChange(rb);
+
+	change->snapshot = snap;
+	change->action_internal = REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT;
+
+	ReorderBufferQueueChange(rb, xid, lsn, change);
+}
+
+/*
+ * Setup the base snapshot of a transaction. That is the snapshot that is used
+ * to decode all changes until either this transaction modifies the catalog or
+ * another catalog modifying transaction commits.
+ */
+void
+ReorderBufferSetBaseSnapshot(ReorderBuffer *rb, TransactionId xid,
+							 XLogRecPtr lsn, Snapshot snap)
+{
+	ReorderBufferTXN *txn;
+	bool		is_new;
+
+	txn = ReorderBufferTXNByXid(rb, xid, true, &is_new, lsn, true);
+	Assert(txn->base_snapshot == NULL);
+
+	txn->base_snapshot = snap;
+}
+
+/*
+ * Access the catalog with this CommandId at this point in the changestream.
+ *
+ * May only be called for command ids > 1
+ */
+void
+ReorderBufferAddNewCommandId(ReorderBuffer *rb, TransactionId xid,
+							 XLogRecPtr lsn, CommandId cid)
+{
+	ReorderBufferChange *change = ReorderBufferGetChange(rb);
+
+	change->command_id = cid;
+	change->action_internal = REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID;
+
+	ReorderBufferQueueChange(rb, xid, lsn, change);
+}
+
+
+/*
+ * Add new (relfilenode, tid) -> (cmin, cmax) mappings.
+ */
+void
+ReorderBufferAddNewTupleCids(ReorderBuffer *rb, TransactionId xid,
+							 XLogRecPtr lsn, RelFileNode node,
+							 ItemPointerData tid, CommandId cmin,
+							 CommandId cmax, CommandId combocid)
+{
+	ReorderBufferChange *change = ReorderBufferGetChange(rb);
+	ReorderBufferTXN *txn;
+
+	txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
+
+	change->tuplecid.node = node;
+	change->tuplecid.tid = tid;
+	change->tuplecid.cmin = cmin;
+	change->tuplecid.cmax = cmax;
+	change->tuplecid.combocid = combocid;
+	change->lsn = lsn;
+	change->action_internal = REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID;
+
+	dlist_push_tail(&txn->tuplecids, &change->node);
+	txn->ntuplecids++;
+}
+
+/*
+ * Setup the invalidation of the toplevel transaction.
+ *
+ * This needs to be done before ReorderBufferCommit is called!
+ */
+void
+ReorderBufferAddInvalidations(ReorderBuffer *rb, TransactionId xid,
+							  XLogRecPtr lsn, Size nmsgs,
+							  SharedInvalidationMessage *msgs)
+{
+	ReorderBufferTXN *txn;
+
+	txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
+
+	if (txn->ninvalidations != 0)
+		elog(ERROR, "only ever add one set of invalidations");
+
+	Assert(nmsgs > 0);
+
+	txn->ninvalidations = nmsgs;
+	txn->invalidations = (SharedInvalidationMessage *)
+		MemoryContextAlloc(rb->context,
+						   sizeof(SharedInvalidationMessage) * nmsgs);
+	memcpy(txn->invalidations, msgs,
+		   sizeof(SharedInvalidationMessage) * nmsgs);
+}
+
+/*
+ * Apply all invalidations we know. Possibly we only need parts at this point
+ * in the changestream but we don't know which those are.
+ */
+static void
+ReorderBufferExecuteInvalidations(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	int			i;
+
+	for (i = 0; i < txn->ninvalidations; i++)
+		LocalExecuteInvalidationMessage(&txn->invalidations[i]);
+}
+
+/*
+ * Mark a transaction as containing catalog changes
+ */
+void
+ReorderBufferXidSetCatalogChanges(ReorderBuffer *rb, TransactionId xid,
+								  XLogRecPtr lsn)
+{
+	ReorderBufferTXN *txn;
+
+	txn = ReorderBufferTXNByXid(rb, xid, true, NULL, lsn, true);
+
+	txn->has_catalog_changes = true;
+}
+
+/*
+ * Query whether a transaction is already *known* to contain catalog
+ * changes. This can be wrong until directly before the commit!
+ */
+bool
+ReorderBufferXidHasCatalogChanges(ReorderBuffer *rb, TransactionId xid)
+{
+	ReorderBufferTXN *txn;
+
+	txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr,
+								false);
+	if (txn == NULL)
+		return false;
+
+	return txn->has_catalog_changes;
+}
+
+/*
+ * Have we already added the first snapshot?
+ */
+bool
+ReorderBufferXidHasBaseSnapshot(ReorderBuffer *rb, TransactionId xid)
+{
+	ReorderBufferTXN *txn;
+
+	txn = ReorderBufferTXNByXid(rb, xid, false, NULL, InvalidXLogRecPtr,
+								false);
+
+	/* transaction isn't known yet, ergo no snapshot */
+	if (txn == NULL)
+		return false;
+
+	return txn->base_snapshot != NULL;
+}
+
+static void
+ReorderBufferSerializeReserve(ReorderBuffer *rb, Size sz)
+{
+	if (!rb->outbufsize)
+	{
+		rb->outbuf = MemoryContextAlloc(rb->context, sz);
+		rb->outbufsize = sz;
+	}
+	else if (rb->outbufsize < sz)
+	{
+		rb->outbuf = repalloc(rb->outbuf, sz);
+		rb->outbufsize = sz;
+	}
+}
+
+typedef struct ReorderBufferDiskChange
+{
+	Size		size;
+	ReorderBufferChange change;
+	/* data follows */
+} ReorderBufferDiskChange;
+
+/*
+ * Persistency support
+ */
+static void
+ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
+							 int fd, ReorderBufferChange *change)
+{
+	ReorderBufferDiskChange *ondisk;
+	Size		sz = sizeof(ReorderBufferDiskChange);
+
+	ReorderBufferSerializeReserve(rb, sz);
+
+	ondisk = (ReorderBufferDiskChange *) rb->outbuf;
+	memcpy(&ondisk->change, change, sizeof(ReorderBufferChange));
+
+	switch ((ReorderBufferChangeTypeInternal) change->action_internal)
+	{
+		case REORDER_BUFFER_CHANGE_INTERNAL_INSERT:
+			/* fall through */
+		case REORDER_BUFFER_CHANGE_INTERNAL_UPDATE:
+			/* fall through */
+		case REORDER_BUFFER_CHANGE_INTERNAL_DELETE:
+			{
+				char	   *data;
+				Size		oldlen = 0;
+				Size		newlen = 0;
+
+				if (change->tp.oldtuple)
+					oldlen = offsetof(ReorderBufferTupleBuf, data)
+						+ change->tp.oldtuple->tuple.t_len
+						- offsetof(HeapTupleHeaderData, t_bits);
+
+				if (change->tp.newtuple)
+					newlen = offsetof(ReorderBufferTupleBuf, data)
+						+ change->tp.newtuple->tuple.t_len
+						- offsetof(HeapTupleHeaderData, t_bits);
+
+				sz += oldlen;
+				sz += newlen;
+
+				/* make sure we have enough space */
+				ReorderBufferSerializeReserve(rb, sz);
+
+				data = ((char *) rb->outbuf) + sizeof(ReorderBufferDiskChange);
+				/* might have been reallocated above */
+				ondisk = (ReorderBufferDiskChange *) rb->outbuf;
+
+				if (oldlen)
+				{
+					memcpy(data, change->tp.oldtuple, oldlen);
+					data += oldlen;
+					Assert(&change->tp.oldtuple->header == change->tp.oldtuple->tuple.t_data);
+				}
+
+				if (newlen)
+				{
+					memcpy(data, change->tp.newtuple, newlen);
+					data += newlen;
+					Assert(&change->tp.newtuple->header == change->tp.newtuple->tuple.t_data);
+				}
+				break;
+			}
+		case REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT:
+			{
+				char	   *data;
+
+				sz += sizeof(SnapshotData) +
+					sizeof(TransactionId) * change->snapshot->xcnt +
+					sizeof(TransactionId) * change->snapshot->subxcnt
+					;
+
+				/* make sure we have enough space */
+				ReorderBufferSerializeReserve(rb, sz);
+				data = ((char *) rb->outbuf) + sizeof(ReorderBufferDiskChange);
+				/* might have been reallocated above */
+				ondisk = (ReorderBufferDiskChange *) rb->outbuf;
+
+				memcpy(data, change->snapshot, sizeof(SnapshotData));
+				data += sizeof(SnapshotData);
+
+				if (change->snapshot->xcnt)
+				{
+					memcpy(data, change->snapshot->xip,
+						   sizeof(TransactionId) + change->snapshot->xcnt);
+					data += sizeof(TransactionId) + change->snapshot->xcnt;
+				}
+
+				if (change->snapshot->subxcnt)
+				{
+					memcpy(data, change->snapshot->subxip,
+						   sizeof(TransactionId) + change->snapshot->subxcnt);
+					data += sizeof(TransactionId) + change->snapshot->subxcnt;
+				}
+				break;
+			}
+		case REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
+			/* ReorderBufferChange contains everything important */
+			break;
+		case REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID:
+			/* ReorderBufferChange contains everything important */
+			break;
+	}
+
+	ondisk->size = sz;
+
+	if (write(fd, rb->outbuf, ondisk->size) != ondisk->size)
+	{
+		CloseTransientFile(fd);
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not write to xid %u's data file: %m",
+						txn->xid)));
+	}
+
+	Assert(ondisk->change.action_internal == change->action_internal);
+}
+
+/*
+ * Check whether we should spill data to disk.
+ */
+static void
+ReorderBufferCheckSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	/* FIXME subtxn handling? */
+	if (txn->nentries_mem >= max_memtries)
+	{
+		ReorderBufferSerializeTXN(rb, txn);
+		Assert(txn->nentries_mem == 0);
+	}
+}
+
+/*
+ * Spill data of a large transaction (and its subtransactions) to disk.
+ */
+static void
+ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	dlist_iter	subtxn_i;
+	dlist_mutable_iter change_i;
+	int			fd = -1;
+	XLogSegNo	curOpenSegNo = 0;
+	Size		spilled = 0;
+	char		path[MAXPGPATH];
+
+	elog(DEBUG2, "spill %u changes in tx %u to disk",
+		 (uint32) txn->nentries_mem, txn->xid);
+
+	/* do the same to all child TXs */
+	dlist_foreach(subtxn_i, &txn->subtxns)
+	{
+		ReorderBufferTXN *subtxn;
+
+		subtxn = dlist_container(ReorderBufferTXN, node, subtxn_i.cur);
+		ReorderBufferSerializeTXN(rb, subtxn);
+	}
+
+	/* serialize changestream */
+	dlist_foreach_modify(change_i, &txn->changes)
+	{
+		ReorderBufferChange *change;
+
+		change = dlist_container(ReorderBufferChange, node, change_i.cur);
+
+		/*
+		 * store in segment in which it belongs by start lsn, don't split over
+		 * multiple segments tho
+		 */
+		if (fd == -1 || XLByteInSeg(change->lsn, curOpenSegNo))
+		{
+			XLogRecPtr	recptr;
+
+			if (fd != -1)
+				CloseTransientFile(fd);
+
+			XLByteToSeg(change->lsn, curOpenSegNo);
+			XLogSegNoOffsetToRecPtr(curOpenSegNo, 0, recptr);
+
+			/*
+			 * No need to care about TLIs here, only used during a single run,
+			 * so each LSN only maps to a specific WAL record.
+			 */
+			sprintf(path, "pg_replslot/%s/xid-%u-lsn-%X-%X.snap",
+					NameStr(MyReplicationSlot->data.name), txn->xid,
+					(uint32) (recptr >> 32), (uint32) recptr);
+
+			/* open segment, create it if necessary */
+			fd = OpenTransientFile(path,
+								   O_CREAT | O_WRONLY | O_APPEND | PG_BINARY,
+								   S_IRUSR | S_IWUSR);
+
+			if (fd < 0)
+				ereport(ERROR,
+						(errcode_for_file_access(),
+						 errmsg("could not open file \"%s\": %m",
+								path)));
+		}
+
+		ReorderBufferSerializeChange(rb, txn, fd, change);
+		dlist_delete(&change->node);
+		ReorderBufferReturnChange(rb, change);
+
+		spilled++;
+	}
+
+	Assert(spilled == txn->nentries_mem);
+	Assert(dlist_is_empty(&txn->changes));
+	txn->nentries_mem = 0;
+
+	if (fd != -1)
+		CloseTransientFile(fd);
+
+	/* issue write barrier */
+	/* serialize main transaction state */
+}
+
+/*
+ * Restore a number of changes spilled to disk back into memory.
+ */
+static Size
+ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn,
+							int *fd, XLogSegNo *segno)
+{
+	Size		restored = 0;
+	XLogSegNo	last_segno;
+	dlist_mutable_iter cleanup_iter;
+
+	Assert(txn->first_lsn != InvalidXLogRecPtr);
+	Assert(txn->final_lsn != InvalidXLogRecPtr);
+
+	/* free current entries, so we have memory for more */
+	dlist_foreach_modify(cleanup_iter, &txn->changes)
+	{
+		ReorderBufferChange *cleanup =
+		dlist_container(ReorderBufferChange, node, cleanup_iter.cur);
+
+		dlist_delete(&cleanup->node);
+		ReorderBufferReturnChange(rb, cleanup);
+	}
+	txn->nentries_mem = 0;
+	Assert(dlist_is_empty(&txn->changes));
+
+	XLByteToSeg(txn->final_lsn, last_segno);
+
+	while (restored < max_memtries && *segno <= last_segno)
+	{
+		int			readBytes;
+		ReorderBufferDiskChange *ondisk;
+
+		if (*fd == -1)
+		{
+			XLogRecPtr	recptr;
+			char		path[MAXPGPATH];
+
+			/* first time in */
+			if (*segno == 0)
+			{
+				XLByteToSeg(txn->first_lsn, *segno);
+			}
+
+			Assert(*segno != 0 || dlist_is_empty(&txn->changes));
+			XLogSegNoOffsetToRecPtr(*segno, 0, recptr);
+
+			/*
+			 * No need to care about TLIs here, only used during a single run,
+			 * so each LSN only maps to a specific WAL record.
+			 */
+			sprintf(path, "pg_replslot/%s/xid-%u-lsn-%X-%X.snap",
+					NameStr(MyReplicationSlot->data.name), txn->xid,
+					(uint32) (recptr >> 32), (uint32) recptr);
+
+			*fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+			if (*fd < 0 && errno == ENOENT)
+			{
+				*fd = -1;
+				(*segno)++;
+				continue;
+			}
+			else if (*fd < 0)
+				ereport(ERROR,
+						(errcode_for_file_access(),
+						 errmsg("could not open file \"%s\": %m",
+								path)));
+
+		}
+
+		ReorderBufferSerializeReserve(rb, sizeof(ReorderBufferDiskChange));
+
+
+		/*
+		 * Read the statically sized part of a change which has information
+		 * about the total size. If we couldn't read a record, we're at the
+		 * end of this file.
+		 */
+
+		readBytes = read(*fd, rb->outbuf, sizeof(ReorderBufferDiskChange));
+
+		/* eof */
+		if (readBytes == 0)
+		{
+			CloseTransientFile(*fd);
+			*fd = -1;
+			(*segno)++;
+			continue;
+		}
+		else if (readBytes < 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not read from reorderbuffer spill file: %m")));
+		else if (readBytes != sizeof(ReorderBufferDiskChange))
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("incomplete read from reorderbuffer spill file: read %d instead of %u",
+							readBytes,
+							(uint32) sizeof(ReorderBufferDiskChange))));
+
+		ondisk = (ReorderBufferDiskChange *) rb->outbuf;
+
+		ReorderBufferSerializeReserve(rb,
+									  sizeof(ReorderBufferDiskChange) + ondisk->size);
+		ondisk = (ReorderBufferDiskChange *) rb->outbuf;
+
+		readBytes = read(*fd, rb->outbuf + sizeof(ReorderBufferDiskChange),
+						 ondisk->size - sizeof(ReorderBufferDiskChange));
+
+		if (readBytes < 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not read from reorderbuffer spill file: %m")));
+		else if (readBytes != ondisk->size - sizeof(ReorderBufferDiskChange))
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not read from reorderbuffer spill file: read %d instead of %u",
+							readBytes,
+							(uint32) (ondisk->size - sizeof(ReorderBufferDiskChange)))));
+
+		/*
+		 * ok, read a full change from disk, now restore it into proper
+		 * in-memory format
+		 */
+		ReorderBufferRestoreChange(rb, txn, rb->outbuf);
+		restored++;
+	}
+
+	return restored;
+}
+
+/*
+ * Convert change from its on-disk format to in-memory format and queue it onto
+ * the TXN's ->changes list.
+ */
+static void
+ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
+						   char *data)
+{
+	ReorderBufferDiskChange *ondisk;
+	ReorderBufferChange *change;
+
+	ondisk = (ReorderBufferDiskChange *) data;
+
+	change = ReorderBufferGetChange(rb);
+
+	/* copy static part */
+	memcpy(change, &ondisk->change, sizeof(ReorderBufferChange));
+
+	data += sizeof(ReorderBufferDiskChange);
+
+	/* restore individual stuff */
+	switch ((ReorderBufferChangeTypeInternal) change->action_internal)
+	{
+		case REORDER_BUFFER_CHANGE_INTERNAL_INSERT:
+			/* fall through */
+		case REORDER_BUFFER_CHANGE_INTERNAL_UPDATE:
+			/* fall through */
+		case REORDER_BUFFER_CHANGE_INTERNAL_DELETE:
+			if (change->tp.newtuple)
+			{
+				Size		len = offsetof(ReorderBufferTupleBuf, data)
+				+((ReorderBufferTupleBuf *) data)->tuple.t_len
+				- offsetof(HeapTupleHeaderData, t_bits);
+
+				change->tp.newtuple = ReorderBufferGetTupleBuf(rb);
+				memcpy(change->tp.newtuple, data, len);
+				change->tp.newtuple->tuple.t_data = &change->tp.newtuple->header;
+
+				data += len;
+			}
+
+			if (change->tp.oldtuple)
+			{
+				Size		len = offsetof(ReorderBufferTupleBuf, data)
+				+((ReorderBufferTupleBuf *) data)->tuple.t_len
+				- offsetof(HeapTupleHeaderData, t_bits);
+
+				change->tp.oldtuple = ReorderBufferGetTupleBuf(rb);
+				memcpy(change->tp.oldtuple, data, len);
+				change->tp.oldtuple->tuple.t_data = &change->tp.oldtuple->header;
+				data += len;
+			}
+			break;
+		case REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT:
+			{
+				Snapshot	oldsnap = (Snapshot) data;
+				Size		size = sizeof(SnapshotData) +
+				sizeof(TransactionId) * oldsnap->xcnt +
+				sizeof(TransactionId) * (oldsnap->subxcnt + 0)
+						   ;
+
+				Assert(change->snapshot != NULL);
+
+				change->snapshot = MemoryContextAllocZero(rb->context, size);
+
+				memcpy(change->snapshot, data, size);
+				change->snapshot->xip = (TransactionId *)
+					(((char *) change->snapshot) + sizeof(SnapshotData));
+				change->snapshot->subxip =
+					change->snapshot->xip + change->snapshot->xcnt + 0;
+				change->snapshot->copied = true;
+				break;
+			}
+			/* nothing needs to be done */
+		case REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID:
+		case REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID:
+			break;
+	}
+
+	dlist_push_tail(&txn->changes, &change->node);
+	txn->nentries_mem++;
+}
+
+/*
+ * Delete all data spilled to disk after we've restarted/crashed. It will be
+ * recreated when the respective slots are reused.
+ */
+void
+StartupReorderBuffer(void)
+{
+	DIR		   *logical_dir;
+	struct dirent *logical_de;
+
+	DIR		   *spill_dir;
+	struct dirent *spill_de;
+
+	logical_dir = AllocateDir("pg_replslot");
+	while ((logical_de = ReadDir(logical_dir, "pg_replslot")) != NULL)
+	{
+		struct stat	statbuf;
+		char		path[MAXPGPATH];
+
+		if (strcmp(logical_de->d_name, ".") == 0 ||
+			strcmp(logical_de->d_name, "..") == 0)
+			continue;
+
+		/* if it cannot be a slot, skip the directory */
+		if (!ReplicationSlotValidateName(logical_de->d_name, DEBUG2))
+			continue;
+
+		/*
+		 * ok, has to be a surviving logical slot, iterate and delete
+		 * everythign starting with xid-*
+		 */
+		sprintf(path, "pg_replslot/%s", logical_de->d_name);
+
+		/* we're only creating directories here, skip if it's not our's */
+		if (lstat(path, &statbuf) == 0 && !S_ISDIR(statbuf.st_mode))
+			continue;
+
+		spill_dir = AllocateDir(path);
+		while ((spill_de = ReadDir(spill_dir, path)) != NULL)
+		{
+			if (strcmp(spill_de->d_name, ".") == 0 ||
+				strcmp(spill_de->d_name, "..") == 0)
+				continue;
+
+			/* only look at names that can be ours */
+			if (strncmp(spill_de->d_name, "xid", 3) == 0)
+			{
+				sprintf(path, "pg_replslot/%s/%s", logical_de->d_name,
+						spill_de->d_name);
+
+				if (unlink(path) != 0)
+					ereport(PANIC,
+							(errcode_for_file_access(),
+							 errmsg("could not unlink file \"%s\": %m",
+									path)));
+			}
+		}
+		FreeDir(spill_dir);
+	}
+	FreeDir(logical_dir);
+}
+
+/*
+ * toast support
+ */
+
+/*
+ * copied stuff from tuptoaster.c. Perhaps there should be toast_internal.h?
+ */
+#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr)	\
+do { \
+	varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \
+	Assert(VARATT_IS_EXTERNAL(attre)); \
+	Assert(VARSIZE_EXTERNAL(attre) == sizeof(toast_pointer) + VARHDRSZ_EXTERNAL); \
+	memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \
+} while (0)
+
+#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) \
+	((toast_pointer).va_extsize < (toast_pointer).va_rawsize - VARHDRSZ)
+
+/*
+ * Initialize per tuple toast reconstruction support.
+ */
+static void
+ReorderBufferToastInitHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	HASHCTL		hash_ctl;
+
+	Assert(txn->toast_hash == NULL);
+
+	memset(&hash_ctl, 0, sizeof(hash_ctl));
+	hash_ctl.keysize = sizeof(Oid);
+	hash_ctl.entrysize = sizeof(ReorderBufferToastEnt);
+	hash_ctl.hash = tag_hash;
+	hash_ctl.hcxt = rb->context;
+	txn->toast_hash = hash_create("ReorderBufferToastHash", 5, &hash_ctl,
+								  HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+}
+
+/*
+ * Per toast-chunk handling for toast reconstruction
+ *
+ * Appends a toast chunk so we can reconstruct it when the tuple "owning" the
+ * toasted Datum comes along.
+ */
+static void
+ReorderBufferToastAppendChunk(ReorderBuffer *rb, ReorderBufferTXN *txn,
+							  Relation relation, ReorderBufferChange *change)
+{
+	ReorderBufferToastEnt *ent;
+	bool		found;
+	int32		chunksize;
+	bool		isnull;
+	Pointer		chunk;
+	TupleDesc	desc = RelationGetDescr(relation);
+	Oid			chunk_id;
+	Oid			chunk_seq;
+
+	if (txn->toast_hash == NULL)
+		ReorderBufferToastInitHash(rb, txn);
+
+	Assert(IsToastRelation(relation));
+
+	chunk_id = DatumGetObjectId(fastgetattr(&change->tp.newtuple->tuple, 1, desc, &isnull));
+	Assert(!isnull);
+	chunk_seq = DatumGetInt32(fastgetattr(&change->tp.newtuple->tuple, 2, desc, &isnull));
+	Assert(!isnull);
+
+	ent = (ReorderBufferToastEnt *)
+		hash_search(txn->toast_hash,
+					(void *) &chunk_id,
+					HASH_ENTER,
+					&found);
+
+	if (!found)
+	{
+		Assert(ent->chunk_id == chunk_id);
+		ent->num_chunks = 0;
+		ent->last_chunk_seq = 0;
+		ent->size = 0;
+		ent->reconstructed = NULL;
+		dlist_init(&ent->chunks);
+
+		if (chunk_seq != 0)
+			elog(ERROR, "got sequence entry %d for toast chunk %u instead of seq 0",
+				 chunk_seq, chunk_id);
+	}
+	else if (found && chunk_seq != ent->last_chunk_seq + 1)
+		elog(ERROR, "got sequence entry %d for toast chunk %u instead of seq %d",
+			 chunk_seq, chunk_id, ent->last_chunk_seq + 1);
+
+	chunk = DatumGetPointer(fastgetattr(&change->tp.newtuple->tuple, 3, desc, &isnull));
+	Assert(!isnull);
+
+	/* calculate size so we can allocate the right size at once later */
+	if (!VARATT_IS_EXTENDED(chunk))
+		chunksize = VARSIZE(chunk) - VARHDRSZ;
+	else if (VARATT_IS_SHORT(chunk))
+		/* could happen due to heap_form_tuple doing its thing */
+		chunksize = VARSIZE_SHORT(chunk) - VARHDRSZ_SHORT;
+	else
+		elog(ERROR, "unexpected type of toast chunk");
+
+	ent->size += chunksize;
+	ent->last_chunk_seq = chunk_seq;
+	ent->num_chunks++;
+	dlist_push_tail(&ent->chunks, &change->node);
+}
+
+/*
+ * Rejigger change->newtuple to point to in-memory toast tuples instead to
+ * on-disk toast tuples that may not longer exist (think DROP TABLE or VACUUM).
+ *
+ * We cannot replace unchanged toast tuples though, so those will still point
+ * to on-disk toast data.
+ */
+static void
+ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
+						  Relation relation, ReorderBufferChange *change)
+{
+	TupleDesc	desc;
+	int			natt;
+	Datum	   *attrs;
+	bool	   *isnull;
+	bool	   *free;
+	HeapTuple	newtup;
+	Relation	toast_rel;
+	TupleDesc	toast_desc;
+	MemoryContext oldcontext;
+
+	/* no toast tuples changed */
+	if (txn->toast_hash == NULL)
+		return;
+
+	oldcontext = MemoryContextSwitchTo(rb->context);
+
+	/* we should only have toast tuples in an INSERT or UPDATE */
+	Assert(change->tp.newtuple);
+
+	desc = RelationGetDescr(relation);
+
+	toast_rel = RelationIdGetRelation(relation->rd_rel->reltoastrelid);
+	toast_desc = RelationGetDescr(toast_rel);
+
+	/* should we allocate from stack instead? */
+	attrs = palloc0(sizeof(Datum) * desc->natts);
+	isnull = palloc0(sizeof(bool) * desc->natts);
+	free = palloc0(sizeof(bool) * desc->natts);
+
+	heap_deform_tuple(&change->tp.newtuple->tuple, desc,
+					  attrs, isnull);
+
+	for (natt = 0; natt < desc->natts; natt++)
+	{
+		Form_pg_attribute attr = desc->attrs[natt];
+		ReorderBufferToastEnt *ent;
+		struct varlena *varlena;
+
+		/* va_rawsize is the size of the original datum -- including header */
+		struct varatt_external toast_pointer;
+		struct varatt_indirect redirect_pointer;
+		struct varlena *new_datum = NULL;
+		struct varlena *reconstructed;
+		dlist_iter	it;
+		Size		data_done = 0;
+
+		/* system columns aren't toasted */
+		if (attr->attnum < 0)
+			continue;
+
+		if (attr->attisdropped)
+			continue;
+
+		/* not a varlena datatype */
+		if (attr->attlen != -1)
+			continue;
+
+		/* no data */
+		if (isnull[natt])
+			continue;
+
+		/* ok, we know we have a toast datum */
+		varlena = (struct varlena *) DatumGetPointer(attrs[natt]);
+
+		/* no need to do anything if the tuple isn't external */
+		if (!VARATT_IS_EXTERNAL(varlena))
+			continue;
+
+		VARATT_EXTERNAL_GET_POINTER(toast_pointer, varlena);
+
+		/*
+		 * Check whether the toast tuple changed, replace if so.
+		 */
+		ent = (ReorderBufferToastEnt *)
+			hash_search(txn->toast_hash,
+						(void *) &toast_pointer.va_valueid,
+						HASH_FIND,
+						NULL);
+		if (ent == NULL)
+			continue;
+
+		new_datum =
+			(struct varlena *) palloc0(INDIRECT_POINTER_SIZE);
+
+		free[natt] = true;
+
+		reconstructed = palloc0(toast_pointer.va_rawsize);
+
+		ent->reconstructed = reconstructed;
+
+		/* stitch toast tuple back together from its parts */
+		dlist_foreach(it, &ent->chunks)
+		{
+			bool		isnull;
+			ReorderBufferTupleBuf *tup =
+			dlist_container(ReorderBufferChange, node, it.cur)->tp.newtuple;
+			Pointer		chunk =
+			DatumGetPointer(fastgetattr(&tup->tuple, 3, toast_desc, &isnull));
+
+			Assert(!isnull);
+			Assert(!VARATT_IS_EXTERNAL(chunk));
+			Assert(!VARATT_IS_SHORT(chunk));
+
+			memcpy(VARDATA(reconstructed) + data_done,
+				   VARDATA(chunk),
+				   VARSIZE(chunk) - VARHDRSZ);
+			data_done += VARSIZE(chunk) - VARHDRSZ;
+		}
+		Assert(data_done == toast_pointer.va_extsize);
+
+		/* make sure its marked as compressed or not */
+		if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
+			SET_VARSIZE_COMPRESSED(reconstructed, data_done + VARHDRSZ);
+		else
+			SET_VARSIZE(reconstructed, data_done + VARHDRSZ);
+
+		memset(&redirect_pointer, 0, sizeof(redirect_pointer));
+		redirect_pointer.pointer = reconstructed;
+
+		SET_VARTAG_EXTERNAL(new_datum, VARTAG_INDIRECT);
+		memcpy(VARDATA_EXTERNAL(new_datum), &redirect_pointer,
+			   sizeof(redirect_pointer));
+
+		attrs[natt] = PointerGetDatum(new_datum);
+	}
+
+	/*
+	 * Build tuple in separate memory & copy tuple back into the tuplebuf
+	 * passed to the output plugin. We can't directly heap_fill_tuple() into
+	 * the tuplebuf because attrs[] will point back into the current content.
+	 */
+	newtup = heap_form_tuple(desc, attrs, isnull);
+	Assert(change->tp.newtuple->tuple.t_len <= MaxHeapTupleSize);
+	Assert(&change->tp.newtuple->header == change->tp.newtuple->tuple.t_data);
+
+	memcpy(change->tp.newtuple->tuple.t_data,
+		   newtup->t_data,
+		   newtup->t_len);
+	change->tp.newtuple->tuple.t_len = newtup->t_len;
+
+	/*
+	 * free resources we won't further need, more persistent stuff will be
+	 * free'd in ReorderBufferToastReset().
+	 */
+	RelationClose(toast_rel);
+	pfree(newtup);
+	for (natt = 0; natt < desc->natts; natt++)
+	{
+		if (free[natt])
+			pfree(DatumGetPointer(attrs[natt]));
+	}
+	pfree(attrs);
+	pfree(free);
+	pfree(isnull);
+
+	MemoryContextSwitchTo(oldcontext);
+}
+
+/*
+ * Free all resources allocated for toast reconstruction.
+ */
+static void
+ReorderBufferToastReset(ReorderBuffer *rb, ReorderBufferTXN *txn)
+{
+	HASH_SEQ_STATUS hstat;
+	ReorderBufferToastEnt *ent;
+
+	if (txn->toast_hash == NULL)
+		return;
+
+	/* sequentially walk over the hash and free everything */
+	hash_seq_init(&hstat, txn->toast_hash);
+	while ((ent = (ReorderBufferToastEnt *) hash_seq_search(&hstat)) != NULL)
+	{
+		dlist_mutable_iter it;
+
+		if (ent->reconstructed != NULL)
+			pfree(ent->reconstructed);
+
+		dlist_foreach_modify(it, &ent->chunks)
+		{
+			ReorderBufferChange *change =
+			dlist_container(ReorderBufferChange, node, it.cur);
+
+			dlist_delete(&change->node);
+			ReorderBufferReturnChange(rb, change);
+		}
+	}
+
+	hash_destroy(txn->toast_hash);
+	txn->toast_hash = NULL;
+}
+
+
+/*
+ * Visibility support routines
+ */
+
+/*-------------------------------------------------------------------------
+ * Lookup actual cmin/cmax values when using decoding snapshot. We can't
+ * always rely on stored cmin/cmax values because of two scenarios:
+ *
+ * * A tuple got changed multiple times during a single transaction and thus
+ *	 has got a combocid. Combocid's are only valid for the duration of a
+ *	 single transaction.
+ * * A tuple with a cmin but no cmax (and thus no combocid) got
+ *	 deleted/updated in another transaction than the one which created it
+ *	 which we are looking at right now. As only one of cmin, cmax or combocid
+ *	 is actually stored in the heap we don't have access to the the value we
+ *	 need anymore.
+ *
+ * To resolve those problems we have a per-transaction hash of (cmin,
+ * cmax) tuples keyed by (relfilenode, ctid) which contains the actual
+ * (cmin, cmax) values. That also takes care of combocids by simply
+ * not caring about them at all. As we have the real cmin/cmax values
+ * combocids aren't interesting.
+ *
+ * As we only care about catalog tuples here the overhead of this
+ * hashtable should be acceptable.
+ *
+ * Heap rewrites complicate this a bit, check rewriteheap.c for
+ * details.
+ * -------------------------------------------------------------------------
+ */
+
+/* struct for qsort()ing mapping files by lsn somewhat efficiently */
+typedef struct RewriteMappingFile
+{
+	XLogRecPtr	lsn;
+	char		fname[MAXPGPATH];
+} RewriteMappingFile;
+
+#if NOT_USED
+static void
+DisplayMapping(HTAB *tuplecid_data)
+{
+	HASH_SEQ_STATUS hstat;
+	ReorderBufferTupleCidEnt *ent;
+
+	hash_seq_init(&hstat, tuplecid_data);
+	while ((ent = (ReorderBufferTupleCidEnt *) hash_seq_search(&hstat)) != NULL)
+	{
+		elog(DEBUG3, "mapping: node: %u/%u/%u tid: %u/%u cmin: %u, cmax: %u",
+			 ent->key.relnode.dbNode,
+			 ent->key.relnode.spcNode,
+			 ent->key.relnode.relNode,
+			 BlockIdGetBlockNumber(&ent->key.tid.ip_blkid),
+			 ent->key.tid.ip_posid,
+			 ent->cmin,
+			 ent->cmax
+			);
+	}
+}
+#endif
+
+/*
+ * Apply a single mapping file to tuplecid_data.
+ *
+ * The mapping file has to have been verified to be a) committed b) for our
+ * transaction c) applied in LSN order.
+ */
+static void
+ApplyLogicalMappingFile(HTAB *tuplecid_data, Oid relid, const char *fname)
+{
+	char		path[MAXPGPATH];
+	int			fd;
+	int			readBytes;
+	LogicalRewriteMappingData map;
+
+	sprintf(path, "pg_llog/mappings/%s", fname);
+	fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+	if (fd < 0)
+		ereport(ERROR,
+				(errmsg("could not open file \"%s\": %m", path)));
+
+	while (true)
+	{
+		ReorderBufferTupleCidKey key;
+		ReorderBufferTupleCidEnt *ent;
+		ReorderBufferTupleCidEnt *new_ent;
+		bool found;
+
+		/* be careful about padding */
+		memset(&key, 0, sizeof(ReorderBufferTupleCidKey));
+
+		/* read all mappings till the end of the file */
+		readBytes = read(fd, &map, sizeof(LogicalRewriteMappingData));
+
+		if (readBytes < 0)
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not read file \"%s\": %m",
+							path)));
+		else if (readBytes == 0) /* EOF */
+			break;
+		else if (readBytes != sizeof(LogicalRewriteMappingData))
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not read file \"%s\", read %d instead of %d",
+							path, readBytes,
+							(int32) sizeof(LogicalRewriteMappingData))));
+
+		key.relnode = map.old_node;
+		ItemPointerCopy(&map.old_tid,
+						&key.tid);
+
+
+		ent = (ReorderBufferTupleCidEnt *)
+			hash_search(tuplecid_data,
+						(void *) &key,
+						HASH_FIND,
+						NULL);
+
+		/* no existing mapping, no need to update */
+		if (!ent)
+			continue;
+
+		key.relnode = map.new_node;
+		ItemPointerCopy(&map.new_tid,
+						&key.tid);
+
+		new_ent = (ReorderBufferTupleCidEnt *)
+			hash_search(tuplecid_data,
+						(void *) &key,
+						HASH_ENTER,
+						&found);
+
+		if (found)
+		{
+			/*
+			 * Make sure the existing mapping makes sense. We sometime update
+			 * old records that did not yet have a cmax (e.g. pg_class' own
+			 * entry while rewriting it) during rewrites, so allow that.
+			 */
+			Assert(ent->cmin == InvalidCommandId || ent->cmin == new_ent->cmin);
+			Assert(ent->cmax == InvalidCommandId || ent->cmax == new_ent->cmax);
+		}
+		else
+		{
+			/* update mapping */
+			new_ent->cmin = ent->cmin;
+			new_ent->cmax = ent->cmax;
+			new_ent->combocid = ent->combocid;
+		}
+	}
+}
+
+
+/*
+ * Check whether the TransactionOId 'xid' is in the pre-sorted array 'xip'.
+ */
+static bool
+TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
+{
+	return bsearch(&xid, xip, num,
+				   sizeof(TransactionId), xidComparator) != NULL;
+}
+
+/*
+ * qsort() comparator for sorting RewriteMappingFiles in LSN order.
+ */
+static int
+file_sort_by_lsn(const void *a_p, const void *b_p)
+{
+	RewriteMappingFile *a = *(RewriteMappingFile **)a_p;
+	RewriteMappingFile *b = *(RewriteMappingFile **)b_p;
+
+	if (a->lsn < b->lsn)
+		return -1;
+	else if (a->lsn > b->lsn)
+		return 1;
+	return 0;
+}
+
+/*
+ * Apply any existing logical remapping files if there are any targeted at our
+ * transaction for relid.
+ */
+static void
+UpdateLogicalMappings(HTAB *tuplecid_data, Oid relid, Snapshot snapshot)
+{
+	DIR		   *mapping_dir;
+	struct dirent *mapping_de;
+	List	   *files = NIL;
+	ListCell   *file;
+	RewriteMappingFile **files_a;
+	size_t		off;
+	Oid			dboid = IsSharedRelation(relid) ? InvalidOid : MyDatabaseId;
+
+	mapping_dir = AllocateDir("pg_llog/mappings");
+	while ((mapping_de = ReadDir(mapping_dir, "pg_llog/mappings")) != NULL)
+	{
+		Oid				f_dboid;
+		Oid				f_relid;
+		TransactionId	f_mapped_xid;
+		TransactionId	f_create_xid;
+		XLogRecPtr		f_lsn;
+		RewriteMappingFile *f;
+
+		if (strcmp(mapping_de->d_name, ".") == 0 ||
+			strcmp(mapping_de->d_name, "..") == 0)
+			continue;
+
+		/* XXX: should we warn about such files? */
+		if (strncmp(mapping_de->d_name, "map-", 4) != 0)
+			continue;
+
+		if (sscanf(mapping_de->d_name, LOGICAL_REWRITE_FORMAT,
+				   &f_dboid, &f_relid, &f_lsn,
+				   &f_mapped_xid, &f_create_xid) != 5)
+			elog(ERROR, "could not parse fname %s", mapping_de->d_name);
+
+		/* mapping for another database */
+		if (f_dboid != dboid)
+			continue;
+
+		/* mapping for another relation */
+		if (f_relid != relid)
+			continue;
+
+		/* did the creating transaction abort? */
+		if (!TransactionIdDidCommit(f_create_xid))
+			continue;
+
+		/* not for our transaction */
+		if (!TransactionIdInArray(f_mapped_xid, snapshot->subxip, snapshot->subxcnt))
+			continue;
+
+		/* ok, relevant, queue for apply */
+		f = palloc(sizeof(RewriteMappingFile));
+		f->lsn = f_lsn;
+		strcpy(f->fname, mapping_de->d_name);
+		files = lappend(files, f);
+	}
+	FreeDir(mapping_dir);
+
+	/* build array we can easily sort */
+	files_a = palloc(list_length(files) * sizeof(RewriteMappingFile *));
+	off = 0;
+	foreach(file, files)
+	{
+		files_a[off++] = lfirst(file);
+	}
+
+	/* sort files so we apply them in LSN order */
+	qsort(files_a, list_length(files), sizeof(RewriteMappingFile *),
+		  file_sort_by_lsn);
+
+	for(off = 0; off < list_length(files); off++)
+	{
+		RewriteMappingFile *f = files_a[off];
+		elog(DEBUG1, "applying mapping: %s in %u", f->fname,
+			snapshot->subxip[0]);
+		ApplyLogicalMappingFile(tuplecid_data, relid, f->fname);
+		pfree(f);
+	}
+}
+
+/*
+ * Lookup cmin/cmax of a tuple, during logical decoding where we can't rely on
+ * combocids.
+ */
+bool
+ResolveCminCmaxDuringDecoding(HTAB *tuplecid_data,
+							  Snapshot snapshot,
+							  HeapTuple htup, Buffer buffer,
+							  CommandId *cmin, CommandId *cmax)
+{
+	ReorderBufferTupleCidKey key;
+	ReorderBufferTupleCidEnt *ent;
+	ForkNumber	forkno;
+	BlockNumber blockno;
+	bool updated_mapping = false;
+
+	/* be careful about padding */
+	memset(&key, 0, sizeof(key));
+
+	Assert(!BufferIsLocal(buffer));
+
+	/*
+	 * get relfilenode from the buffer, no convenient way to access it other
+	 * than that.
+	 */
+	BufferGetTag(buffer, &key.relnode, &forkno, &blockno);
+
+	/* tuples can only be in the main fork */
+	Assert(forkno == MAIN_FORKNUM);
+	Assert(blockno == ItemPointerGetBlockNumber(&htup->t_self));
+
+	ItemPointerCopy(&htup->t_self,
+					&key.tid);
+
+restart:
+	ent = (ReorderBufferTupleCidEnt *)
+		hash_search(tuplecid_data,
+					(void *) &key,
+					HASH_FIND,
+					NULL);
+
+	/*
+	 * failed to find a mapping, check whether the table was rewritten and
+	 * apply mapping if so, but only do that once - there can be no new
+	 * mappings while we are in here since we have to hold a lock on the
+	 * relation.
+	 */
+	if (ent == NULL && !updated_mapping)
+	{
+		UpdateLogicalMappings(tuplecid_data, htup->t_tableOid, snapshot);
+		/* now check but don't update for a mapping again */
+		updated_mapping = true;
+		goto restart;
+	}
+	else if (ent == NULL)
+		return false;
+
+	if (cmin)
+		*cmin = ent->cmin;
+	if (cmax)
+		*cmax = ent->cmax;
+	return true;
+}
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
new file mode 100644
index 0000000..42875c9
--- /dev/null
+++ b/src/backend/replication/logical/snapbuild.c
@@ -0,0 +1,1874 @@
+/*-------------------------------------------------------------------------
+ *
+ * snapbuild.c
+ *
+ *	  Infrastructure for building historic catalog snapshots based on contents
+ *	  of the WAL, for the purpose of decoding heapam.c style values in the
+ *	  WAL.
+ *
+ * NOTES:
+ *
+ * We build snapshots which can *only* be used to read catalog contents and we
+ * do so by reading and interpreting the WAL stream. The aim is to build a
+ * snapshot that behaves the same as a freshly taken MVCC snapshot would have
+ * at the time the XLogRecord was generated.
+ *
+ * To build the snapshots we reuse the infrastructure built for Hot
+ * Standby. The in-memory snapshots we build look different than HS' because
+ * we have different needs. To successfully decode data from the WAL we only
+ * need to access catalog tables and (sys|rel|cat)cache, not the actual user
+ * tables since the data we decode is wholly contained in the WAL
+ * records. Also, our snapshots need to be different in comparison to normal
+ * MVCC ones because in contrast to those we cannot fully rely on the clog and
+ * pg_subtrans for information about committed transactions because they might
+ * commit in the future from the POV of the WAL entry we're currently
+ * decoding.
+ *
+ * As the percentage of transactions modifying the catalog normally is fairly
+ * small in comparisons to ones only manipulating user data, we keep track of
+ * the committed catalog modifying ones inside (xmin, xmax) instead of keeping
+ * track of all running transactions like its done in a normal snapshot. Note
+ * that we're generally only looking at transactions that have acquired an
+ * xid. That is we keep a list of transactions between snapshot->(xmin, xmax)
+ * that we consider committed, everything else is considered aborted/in
+ * progress. That also allows us not to care about subtransactions before they
+ * have committed which means this modules, in contrast to HS, doesn't have to
+ * care about suboverflowed subtransactions and similar.
+ *
+ * One complexity of doing this is that to e.g. handle mixed DDL/DML
+ * transactions we need Snapshots that see intermediate versions of the
+ * catalog in a transaction. During normal operation this is achieved by using
+ * CommandIds/cmin/cmax. The problem with that however is that for space
+ * efficiency reasons only one value of that is stored
+ * (c.f. combocid.c). Since ComboCids are only available in memory we log
+ * additional information which allows us to get the original (cmin, cmax)
+ * pair during visibility checks. Check the reorderbuffer.c's comment above
+ * ResolveCminCmaxDuringDecoding() for details.
+ *
+ * To facilitate all this we need our own visibility routine, as the normal
+ * ones are optimized for different usecases. To make sure no unexpected
+ * database access bypassing our special snapshot is possible - which would
+ * possibly load invalid data into caches - we temporarily overload the
+ * .satisfies methods of the usual snapshots while changeset extraction.
+ *
+ * To replace the normal catalog snapshots with decoding ones use the
+ * SetupDecodingSnapshots and RevertFromDecodingSnapshots functions.
+ *
+ *
+ *
+ * The snapbuild machinery is starting up in in several stages, as illustrated
+ * by the following graph:
+ *         +-------------------------+
+ *    +----|SNAPBUILD_START          |-------------+
+ *    |    +-------------------------+             |
+ *    |                 |                          |
+ *    |                 |                          |
+ *    |     running_xacts with running xacts       |
+ *    |                 |                          |
+ *    |                 |                          |
+ *    |                 v                          |
+ *    |    +-------------------------+             v
+ *    |    |SNAPBUILD_FULL_SNAPSHOT  |------------>|
+ *    |    +-------------------------+             |
+ * running_xacts        |                      saved snapshot
+ * with zero xacts      |                 at running_xacts's lsn
+ *    |                 |                          |
+ *    |     all running toplevel TXNs finished     |
+ *    |                 |                          |
+ *    |                 v                          |
+ *    |    +-------------------------+             |
+ *    +--->|SNAPBUILD_CONSISTENT     |<------------+
+ *         +-------------------------+
+ *
+ * Initially the machinery is in the START stage. When a xl_running_xacts
+ * record is read that is sufficiently new (above the safe xmin horizon),
+ * there's a state transation. If there were no running xacts when the
+ * runnign_xacts record was generated, we'll directly go into CONSISTENT
+ * state, otherwise we'll switch to the FULL_SNAPSHOT state. Having a full
+ * snapshot means that all transactions that start henceforth can be decoded
+ * in their entirety, but transactions that started previously can't. In
+ * FULL_SNAPSHOT we'll switch into CONSISTENT once all those previously
+ * running transactions have committed or aborted.
+ *
+ * Only transactions that commit after CONSISTENT state has been reached will
+ * be replayed, even though they might have started while still in
+ * FULL_SNAPSHOT. That ensures that we'll reach a point where no previous
+ * changes has been exported, but all the following ones will be. That point
+ * is a convenient point to initialize replication from, which is why we
+ * export a snapshot at that point, which *can* be used to read normal data.
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/backend/replication/snapbuild.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "miscadmin.h"
+
+#include "access/heapam_xlog.h"
+#include "access/transam.h"
+#include "access/xact.h"
+
+#include "replication/logical.h"
+#include "replication/reorderbuffer.h"
+#include "replication/snapbuild.h"
+
+#include "utils/builtins.h"
+#include "utils/memutils.h"
+#include "utils/snapshot.h"
+#include "utils/snapmgr.h"
+#include "utils/tqual.h"
+
+#include "storage/block.h"		/* debugging output */
+#include "storage/fd.h"
+#include "storage/lmgr.h"
+#include "storage/proc.h"
+#include "storage/procarray.h"
+#include "storage/standby.h"
+
+/*
+ * This struct contains the current state of the snapshot building
+ * machinery. Besides a forward declaration in the header, it is not exposed
+ * to the public, so we can easily change it's contents.
+ */
+struct SnapBuild
+{
+	/* how far are we along building our first full snapshot */
+	SnapBuildState state;
+
+	/* private memory context used to allocate memory for this module. */
+	MemoryContext context;
+
+	/* all transactions < than this have committed/aborted */
+	TransactionId xmin;
+
+	/* all transactions >= than this are uncommitted */
+	TransactionId xmax;
+
+	/*
+	 * Don't replay commits from an LSN <= this LSN. This can be set
+	 * externally but it will also be advanced (never retreat) from within
+	 * snapbuild.c.
+	 */
+	XLogRecPtr	transactions_after;
+
+	/*
+	 * Don't start decoding WAL until the "xl_running_xacts" information
+	 * indicates there are no running xids with a xid smaller than this.
+	 */
+	TransactionId initial_xmin_horizon;
+
+	/*
+	 * Snapshot that's valid to see the catalog state seen at this moment.
+	 */
+	Snapshot	snapshot;
+
+	/*
+	 * LSN of the last location we are sure a snapshot has been serialized to.
+	 */
+	XLogRecPtr	last_serialized_snapshot;
+
+	/*
+	 * The reorderbuffer we need to update with usable snapshots et al.
+	 */
+	ReorderBuffer *reorder;
+
+	/*
+	 * Information about initially running transactions
+	 *
+	 * When we start building a snapshot there already may be transactions in
+	 * progress.  Those are stored in running.xip.	We don't have enough
+	 * information about those to decode their contents, so until they are
+	 * finished (xcnt=0) we cannot switch to a CONSISTENT state.
+	 */
+	struct
+	{
+		/*
+		 * As long as running.xcnt all XIDs < running.xmin and > running.xmax
+		 * have to be checked whether they still are running.
+		 */
+		TransactionId xmin;
+		TransactionId xmax;
+
+		size_t		xcnt;		/* number of used xip entries */
+		size_t		xcnt_space; /* allocated size of xip */
+		TransactionId *xip;		/* running xacts array, xidComparator-sorted */
+	}			running;
+
+	/*
+	 * Array of transactions which could have catalog changes that committed
+	 * between xmin and xmax.
+	 */
+	struct
+	{
+		/* number of committed transactions */
+		size_t		xcnt;
+
+		/* available space for committed transactions */
+		size_t		xcnt_space;
+
+		/*
+		 * Until we reach a CONSISTENT state, we record commits of all
+		 * transactions, not just the catalog changing ones. Record when that
+		 * changes so we know we cannot export a snapshot safely anymore.
+		 */
+		bool		includes_all_transactions;
+
+		/*
+		 * Array of committed transactions that have modified the catalog.
+		 *
+		 * As this array is frequently modified we do *not* keep it in
+		 * xidComparator order. Instead we sort the array when building &
+		 * distributing a snapshot.
+		 *
+		 * XXX: That doesn't seem to be good reasoning anymore. Every time we
+		 * add something here after becoming consistent will also require
+		 * distributing a snapshot. Storing them sorted would potentially make
+		 * it easier to purge as well (but more complicated wrt wraparound?).
+		 */
+		TransactionId *xip;
+	}			committed;
+};
+
+/*
+ * Starting a transaction -- which we need to do while exporting a snapshot --
+ * removes knowledge about the previously used resowner, so we save it here.
+ */
+ResourceOwner SavedResourceOwnerDuringExport = NULL;
+bool ExportInProgress = false;
+
+/* transaction state manipulation functions */
+static void SnapBuildEndTxn(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid);
+
+/* ->running manipulation */
+static bool SnapBuildTxnIsRunning(SnapBuild *builder, TransactionId xid);
+
+/* ->committed manipulation */
+static void SnapBuildPurgeCommittedTxn(SnapBuild *builder);
+
+/* snapshot building/manipulation/distribution functions */
+static Snapshot SnapBuildBuildSnapshot(SnapBuild *builder, TransactionId xid);
+
+static void SnapBuildFreeSnapshot(Snapshot snap);
+
+static void SnapBuildSnapIncRefcount(Snapshot snap);
+
+static void SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn);
+
+/* xlog reading helper functions for SnapBuildProcessRecord */
+static bool SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *running);
+
+/* serialization functions */
+static void SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn);
+static bool SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn);
+
+
+/*
+ * Allocate a new snapshot builder.
+ *
+ * xmin_horizon is the xid >=which we can be sure no catalog rows have been
+ * removed, start_lsn is the LSN >= we want to replay commits.
+ */
+SnapBuild *
+AllocateSnapshotBuilder(ReorderBuffer *reorder,
+						TransactionId xmin_horizon,
+						XLogRecPtr start_lsn)
+{
+	MemoryContext context;
+	MemoryContext oldcontext;
+	SnapBuild  *builder;
+
+	/* allocate memory in own context, to have better accountability */
+	context = AllocSetContextCreate(CurrentMemoryContext,
+									"snapshot builder context",
+									ALLOCSET_DEFAULT_MINSIZE,
+									ALLOCSET_DEFAULT_INITSIZE,
+									ALLOCSET_DEFAULT_MAXSIZE);
+	oldcontext = MemoryContextSwitchTo(context);
+
+	builder = palloc0(sizeof(SnapBuild));
+
+	builder->state = SNAPBUILD_START;
+	builder->context = context;
+	builder->reorder = reorder;
+	/* Other struct members initialized by zeroing via palloc0 above */
+
+	builder->committed.xcnt = 0;
+	builder->committed.xcnt_space = 128;		/* arbitrary number */
+	builder->committed.xip =
+		palloc0(builder->committed.xcnt_space * sizeof(TransactionId));
+	builder->committed.includes_all_transactions = true;
+	builder->committed.xip =
+		palloc0(builder->committed.xcnt_space * sizeof(TransactionId));
+	builder->initial_xmin_horizon = xmin_horizon;
+	builder->transactions_after = start_lsn;
+
+	MemoryContextSwitchTo(oldcontext);
+
+	return builder;
+}
+
+/*
+ * Free a snapshot builder.
+ */
+void
+FreeSnapshotBuilder(SnapBuild *builder)
+{
+	MemoryContext context = builder->context;
+
+	/* free snapshot explicitly, that contains some error checking */
+	if (builder->snapshot != NULL)
+	{
+		SnapBuildSnapDecRefcount(builder->snapshot);
+		builder->snapshot = NULL;
+	}
+
+	/* other resources are deallocated via memory context reset */
+	MemoryContextDelete(context);
+}
+
+/*
+ * Free an unreferenced snapshot that has previously been built by us.
+ */
+static void
+SnapBuildFreeSnapshot(Snapshot snap)
+{
+	/* make sure we don't get passed an external snapshot */
+	Assert(snap->satisfies == HeapTupleSatisfiesMVCCDuringDecoding);
+
+	/* make sure nobody modified our snapshot */
+	Assert(snap->curcid == FirstCommandId);
+	Assert(!snap->suboverflowed);
+	Assert(!snap->takenDuringRecovery);
+	Assert(!snap->regd_count);
+
+	/* slightly more likely, so it's checked even without c-asserts */
+	if (snap->copied)
+		elog(ERROR, "cannot free a copied snapshot");
+
+	if (snap->active_count)
+		elog(ERROR, "cannot free an active snapshot");
+
+	pfree(snap);
+}
+
+/*
+ * In which state of snapshot building are we?
+ */
+SnapBuildState
+SnapBuildCurrentState(SnapBuild *builder)
+{
+	return builder->state;
+}
+
+/*
+ * Should the contents of transaction ending at 'ptr' be decoded?
+ */
+bool
+SnapBuildXactNeedsSkip(SnapBuild *builder, XLogRecPtr ptr)
+{
+	return ptr <= builder->transactions_after;
+}
+
+/*
+ * Increase refcount of a snapshot.
+ *
+ * This is used when handing out a snapshot to some external resource or when
+ * adding a Snapshot as builder->snapshot.
+ */
+static void
+SnapBuildSnapIncRefcount(Snapshot snap)
+{
+	snap->active_count++;
+}
+
+/*
+ * Decrease refcount of a snapshot and free if the refcount reaches zero.
+ *
+ * Externally visible, so that external resources that have been handed an
+ * IncRef'ed Snapshot can adjust its refcount easily.
+ */
+void
+SnapBuildSnapDecRefcount(Snapshot snap)
+{
+	/* make sure we don't get passed an external snapshot */
+	Assert(snap->satisfies == HeapTupleSatisfiesMVCCDuringDecoding);
+
+	/* make sure nobody modified our snapshot */
+	Assert(snap->curcid == FirstCommandId);
+	Assert(!snap->suboverflowed);
+	Assert(!snap->takenDuringRecovery);
+	Assert(!snap->regd_count);
+
+	Assert(snap->active_count);
+
+	/* slightly more likely, so its checked even without casserts */
+	if (snap->copied)
+		elog(ERROR, "cannot free a copied snapshot");
+
+	snap->active_count--;
+	if (!snap->active_count)
+		SnapBuildFreeSnapshot(snap);
+}
+
+/*
+ * Build a new snapshot, based on currently committed catalog-modifying
+ * transactions.
+ *
+ * In-progress transactions with catalog access are *not* allowed to modify
+ * these snapshots; they have to copy them and fill in appropriate ->curcid
+ * and ->subxip/subxcnt values.
+ */
+static Snapshot
+SnapBuildBuildSnapshot(SnapBuild *builder, TransactionId xid)
+{
+	Snapshot	snapshot;
+	Size		ssize;
+
+	Assert(builder->state >= SNAPBUILD_FULL_SNAPSHOT);
+
+	ssize = sizeof(SnapshotData)
+		+ sizeof(TransactionId) * builder->committed.xcnt
+		+ sizeof(TransactionId) * 1 /* toplevel xid */ ;
+
+	snapshot = MemoryContextAllocZero(builder->context, ssize);
+
+	snapshot->satisfies = HeapTupleSatisfiesMVCCDuringDecoding;
+
+	/*
+	 * We misuse the original meaning of SnapshotData's xip and subxip fields
+	 * to make the more fitting for our needs.
+	 *
+	 * In the 'xip' array we store transactions that have to be treated as
+	 * committed. Since we will only ever look at tuples from transactions
+	 * that have modified the catalog its more efficient to store those few
+	 * that exist between xmin and xmax (frequently there are none).
+	 *
+	 * Snapshots that are used in transactions that have modified the catalog
+	 * also use the 'subxip' array to store their toplevel xid and all the
+	 * subtransaction xids so we can recognize when we need to treat rows as
+	 * visible that are not in xip but still need to be visible. Subxip only
+	 * gets filled when the transaction is copied into the context of a
+	 * catalog modifying transaction since we otherwise share a snapshot
+	 * between transactions. As long as a txn hasn't modified the catalog it
+	 * doesn't need to treat any uncommitted rows as visible, so there is no
+	 * need for those xids.
+	 *
+	 * Both arrays are qsort'ed so that we can use bsearch() on them.
+	 *
+	 * XXX: Do we want extra fields instead of misusing existing ones instead?
+	 */
+	Assert(TransactionIdIsNormal(builder->xmin));
+	Assert(TransactionIdIsNormal(builder->xmax));
+
+	snapshot->xmin = builder->xmin;
+	snapshot->xmax = builder->xmax;
+
+	/* store all transactions to be treated as committed by this snapshot */
+	snapshot->xip =
+		(TransactionId *) ((char *) snapshot + sizeof(SnapshotData));
+	snapshot->xcnt = builder->committed.xcnt;
+	memcpy(snapshot->xip,
+		   builder->committed.xip,
+		   builder->committed.xcnt * sizeof(TransactionId));
+
+	/* sort so we can bsearch() */
+	qsort(snapshot->xip, snapshot->xcnt, sizeof(TransactionId), xidComparator);
+
+	/*
+	 * Initially, subxip is empty, i.e. it's a snapshot to be used by
+	 * transactions that don't modify the catalog. Will be filled by
+	 * ReorderBufferCopySnap() if necessary.
+	 */
+	snapshot->subxcnt = 0;
+	snapshot->subxip = NULL;
+
+	snapshot->suboverflowed = false;
+	snapshot->takenDuringRecovery = false;
+	snapshot->copied = false;
+	snapshot->curcid = FirstCommandId;
+	snapshot->active_count = 0;
+	snapshot->regd_count = 0;
+
+	return snapshot;
+}
+
+/*
+ * Export a snapshot so it can be set in another session with SET TRANSACTION
+ * SNAPSHOT.
+ *
+ * For that we need to start a transaction in the current backend as the
+ * importing side checks whether the source transaction is still open to make
+ * sure the xmin horizon hasn't advanced since then.
+ *
+ * After that we convert a locally built snapshot into the normal variant
+ * understood by HeapTupleSatisfiesMVCC et al.
+ */
+const char *
+SnapBuildExportSnapshot(SnapBuild *builder)
+{
+	Snapshot	snap;
+	char	   *snapname;
+	TransactionId xid;
+	TransactionId *newxip;
+	int			newxcnt = 0;
+
+	if (builder->state != SNAPBUILD_CONSISTENT)
+		elog(ERROR, "cannot export a snapshot before reaching a consistent state");
+
+	if (!builder->committed.includes_all_transactions)
+		elog(ERROR, "cannot export a snapshot, not all transactions are monitored anymore");
+
+	/* so we don't overwrite the existing value */
+	if (TransactionIdIsValid(MyPgXact->xmin))
+		elog(ERROR, "cannot export a snapshot when MyPgXact->xmin already is valid");
+
+	if (IsTransactionOrTransactionBlock())
+		elog(ERROR, "cannot export a snapshot from within a transaction");
+
+	if (SavedResourceOwnerDuringExport)
+		elog(ERROR, "can only export one snapshot at a time");
+
+	SavedResourceOwnerDuringExport = CurrentResourceOwner;
+	ExportInProgress = true;
+
+	StartTransactionCommand();
+
+	Assert(!FirstSnapshotSet);
+
+	/* There doesn't seem to a nice API to set these */
+	XactIsoLevel = XACT_REPEATABLE_READ;
+	XactReadOnly = true;
+
+	snap = SnapBuildBuildSnapshot(builder, GetTopTransactionId());
+
+	/*
+	 * We know that snap->xmin is alive, enforced by the logical xmin
+	 * mechanism. Due to that we can do this without locks, we're only
+	 * changing our own value.
+	 */
+	MyPgXact->xmin = snap->xmin;
+
+	/* allocate in transaction context */
+	newxip = (TransactionId *)
+		palloc(sizeof(TransactionId) * GetMaxSnapshotXidCount());
+
+	/*
+	 * snapbuild.c builds transactions in an "inverted" manner, which means it
+	 * stores committed transactions in ->xip, not ones in progress. Build a
+	 * classical snapshot by marking all non-committed transactions as
+	 * in-progress. This can be expensive.
+	 */
+	for (xid = snap->xmin; NormalTransactionIdPrecedes(xid, snap->xmax);)
+	{
+		void	   *test;
+
+		/*
+		 * Check whether transaction committed using the decoding snapshot
+		 * meaning of ->xip.
+		 */
+		test = bsearch(&xid, snap->xip, snap->xcnt,
+					   sizeof(TransactionId), xidComparator);
+
+		if (test == NULL)
+		{
+			if (newxcnt >= GetMaxSnapshotXidCount())
+				elog(ERROR, "snapshot too large");
+
+			newxip[newxcnt++] = xid;
+		}
+
+		TransactionIdAdvance(xid);
+	}
+
+	snap->xcnt = newxcnt;
+	snap->xip = newxip;
+
+	/*
+	 * now that we've built a plain snapshot, use the normal mechanisms for
+	 * exporting it
+	 */
+	snapname = ExportSnapshot(snap);
+
+	ereport(LOG,
+			(errmsg("exported changeset extraction snapshot: \"%s\" with %u xids",
+					snapname, snap->xcnt)));
+	return snapname;
+}
+
+/*
+ * Reset a previously SnapBuildExportSnapshot()'ed snapshot if there is
+ * any. Aborts the previously started transaction and resets the resource
+ * owner back to it's original value.
+ */
+void
+SnapBuildClearExportedSnapshot()
+{
+	/* nothing exported, thats the usual case */
+	if (!ExportInProgress)
+		return;
+
+	if (!IsTransactionState())
+		elog(ERROR, "clearing exported snapshot in wrong transaction state");
+
+	/* make sure nothing  could have ever happened */
+	AbortCurrentTransaction();
+
+	CurrentResourceOwner = SavedResourceOwnerDuringExport;
+	SavedResourceOwnerDuringExport = NULL;
+	ExportInProgress = false;
+}
+
+/*
+ * Handle the effects of a single heap change, appropriate to the current state
+ * of the snapshot builder and returns whether changes made at (xid, lsn) can
+ * be decoded.
+ */
+bool
+SnapBuildProcessChange(SnapBuild *builder, TransactionId xid, XLogRecPtr lsn)
+{
+	bool is_old_tx;
+
+	/*
+	 * We can't handle data in transactions if we haven't built a snapshot
+	 * yet, so don't store them.
+	 */
+	if (builder->state < SNAPBUILD_FULL_SNAPSHOT)
+		return false;
+
+	/*
+	 * No point in keeping track of changes in transactions that we don't have
+	 * enough information about to decode. This means that they started before
+	 * we got into the SNAPBUILD_FULL_SNAPSHOT state.
+	 */
+	if (builder->state < SNAPBUILD_CONSISTENT &&
+		SnapBuildTxnIsRunning(builder, xid))
+		return false;
+
+	/*
+	 * If the reorderbuffer doesn't yet have a snapshot, add one now, it will
+	 * be needed to decode the change we're currently processing.
+	 */
+	is_old_tx = ReorderBufferIsXidKnown(builder->reorder, xid);
+
+	if (!is_old_tx || !ReorderBufferXidHasBaseSnapshot(builder->reorder, xid))
+	{
+		/* only build a new snapshot if we don't have a prebuilt one */
+		if (builder->snapshot == NULL)
+		{
+			builder->snapshot = SnapBuildBuildSnapshot(builder, xid);
+			/* inrease refcount for the snapshot builder */
+			SnapBuildSnapIncRefcount(builder->snapshot);
+		}
+
+		/*
+		 * Increase refcount for the transaction we're handing the snapshot
+		 * out to.
+		 */
+		SnapBuildSnapIncRefcount(builder->snapshot);
+		ReorderBufferSetBaseSnapshot(builder->reorder, xid, lsn,
+									 builder->snapshot);
+	}
+
+	return true;
+}
+
+/*
+ * Do CommandId/ComboCid handling after reading a xl_heap_new_cid record. This
+ * implies that a transaction has done some form of write to system catalogs.
+ */
+void
+SnapBuildProcessNewCid(SnapBuild *builder, TransactionId xid,
+					   XLogRecPtr lsn, xl_heap_new_cid *xlrec)
+{
+	CommandId	cid;
+
+	/*
+	 * we only log new_cid's if a catalog tuple was modified, so mark
+	 * the transaction as containing catalog modifications
+	 */
+	ReorderBufferXidSetCatalogChanges(builder->reorder, xid,lsn);
+
+	ReorderBufferAddNewTupleCids(builder->reorder, xlrec->top_xid, lsn,
+								 xlrec->target.node, xlrec->target.tid,
+								 xlrec->cmin, xlrec->cmax,
+								 xlrec->combocid);
+
+	/* figure out new command id */
+	if (xlrec->cmin != InvalidCommandId &&
+		xlrec->cmax != InvalidCommandId)
+		cid = Max(xlrec->cmin, xlrec->cmax);
+	else if (xlrec->cmax != InvalidCommandId)
+		cid = xlrec->cmax;
+	else if (xlrec->cmin != InvalidCommandId)
+		cid = xlrec->cmin;
+	else
+	{
+		cid = InvalidCommandId;		/* silence compiler */
+		elog(ERROR, "xl_heap_new_cid record without a valid CommandId");
+	}
+
+	ReorderBufferAddNewCommandId(builder->reorder, xid, lsn, cid + 1);
+}
+
+/*
+ * Check whether `xid` is currently 'running'.
+ *
+ * Running transactions in our parlance are transactions which we didn't
+ * observe from the start so we can't properly decode their contents. They
+ * only exist after we freshly started from an < CONSISTENT snapshot.
+ */
+static bool
+SnapBuildTxnIsRunning(SnapBuild *builder, TransactionId xid)
+{
+	Assert(builder->state < SNAPBUILD_CONSISTENT);
+	Assert(TransactionIdIsNormal(builder->running.xmin));
+	Assert(TransactionIdIsNormal(builder->running.xmax));
+
+	if (builder->running.xcnt &&
+		NormalTransactionIdFollows(xid, builder->running.xmin) &&
+		NormalTransactionIdPrecedes(xid, builder->running.xmax))
+	{
+		TransactionId *search =
+		bsearch(&xid, builder->running.xip, builder->running.xcnt_space,
+				sizeof(TransactionId), xidComparator);
+
+		if (search != NULL)
+		{
+			Assert(*search == xid);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/*
+ * Add a new Snapshot to all transactions we're decoding that currently are
+ * in-progress so they can see new catalog contents made by the transaction
+ * that just committed. This is necessary because those in-progress
+ * transactions will use the new catalog's contents from here on (at the very
+ * least everything they do needs to be compatible with newer catalog
+ * contents).
+ */
+static void
+SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn)
+{
+	dlist_iter	txn_i;
+	ReorderBufferTXN *txn;
+
+	/*
+	 * Iterate through all toplevel transactions. This can include
+	 * subtransactions which we just don't yet know to be that, but that's
+	 * fine, they will just get an unneccesary snapshot queued.
+	 */
+	dlist_foreach(txn_i, &builder->reorder->toplevel_by_lsn)
+	{
+		txn = dlist_container(ReorderBufferTXN, node, txn_i.cur);
+
+		Assert(TransactionIdIsValid(txn->xid));
+
+		/*
+		 * If we don't have a base snapshot yet, there are no changes in this
+		 * transaction which in turn implies we don't yet need a snapshot at
+		 * all. We'll add add a snapshot when the first change gets queued.
+		 *
+		 * XXX: is that fine if only a subtransaction has a base snapshot so
+		 * far?
+		 */
+		if (!ReorderBufferXidHasBaseSnapshot(builder->reorder, txn->xid))
+			continue;
+
+		elog(DEBUG2, "adding a new snapshot to %u at %X/%X",
+			 txn->xid, (uint32) (lsn >> 32), (uint32) lsn);
+
+		/*
+		 * increase the snapshot's refcount for the transaction we are handing
+		 * it out to
+		 */
+		SnapBuildSnapIncRefcount(builder->snapshot);
+		ReorderBufferAddSnapshot(builder->reorder, txn->xid, lsn,
+								 builder->snapshot);
+	}
+}
+
+/*
+ * Keep track of a new catalog changing transaction that has committed.
+ */
+static void
+SnapBuildAddCommittedTxn(SnapBuild *builder, TransactionId xid)
+{
+	Assert(TransactionIdIsValid(xid));
+
+	if (builder->committed.xcnt == builder->committed.xcnt_space)
+	{
+		builder->committed.xcnt_space = builder->committed.xcnt_space * 2 + 1;
+
+		/* XXX: put in a limit here as a defense against bugs? */
+
+		elog(DEBUG1, "increasing space for committed transactions to %u",
+			 (uint32) builder->committed.xcnt_space);
+
+		builder->committed.xip = repalloc(builder->committed.xip,
+					builder->committed.xcnt_space * sizeof(TransactionId));
+	}
+
+	/*
+	 * XXX: It might make sense to keep the array sorted here instead of doing
+	 * it every time we build a new snapshot. On the other hand this gets
+	 * called repeatedly when a transaction with subtransactions commits.
+	 */
+	builder->committed.xip[builder->committed.xcnt++] = xid;
+}
+
+/*
+ * Remove knowledge about transactions we treat as committed that are smaller
+ * than ->xmin. Those won't ever get checked via the ->commited array but via
+ * the clog machinery, so we don't need to waste memory on them.
+ */
+static void
+SnapBuildPurgeCommittedTxn(SnapBuild *builder)
+{
+	int			off;
+	TransactionId *workspace;
+	int			surviving_xids = 0;
+
+	/* not ready yet */
+	if (!TransactionIdIsNormal(builder->xmin))
+		return;
+
+	/* XXX: Neater algorithm? */
+	workspace =
+		MemoryContextAlloc(builder->context,
+						   builder->committed.xcnt * sizeof(TransactionId));
+
+	/* copy xids that still are interesting to workspace */
+	for (off = 0; off < builder->committed.xcnt; off++)
+	{
+		if (NormalTransactionIdPrecedes(builder->committed.xip[off],
+										builder->xmin))
+			;					/* remove */
+		else
+			workspace[surviving_xids++] = builder->committed.xip[off];
+	}
+
+	/* copy workspace back to persistent state */
+	memcpy(builder->committed.xip, workspace,
+		   surviving_xids * sizeof(TransactionId));
+
+	elog(DEBUG3, "purged committed transactions from %u to %u, xmin: %u, xmax: %u",
+		 (uint32) builder->committed.xcnt, (uint32) surviving_xids,
+		 builder->xmin, builder->xmax);
+	builder->committed.xcnt = surviving_xids;
+
+	pfree(workspace);
+}
+
+/*
+ * Common logic for SnapBuildAbortTxn and SnapBuildCommitTxn dealing with
+ * keeping track of the amount of running transactions.
+ */
+static void
+SnapBuildEndTxn(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid)
+{
+	if (builder->state == SNAPBUILD_CONSISTENT)
+		return;
+
+	/*
+	 * NB: This handles subtransactions correctly even if we started from
+	 * suboverflowed xl_running_xacts because we only keep track of toplevel
+	 * transactions. Since the latter are always are allocated before their
+	 * subxids and since they end at the same time it's sufficient to deal
+	 * with them here.
+	 */
+	if (SnapBuildTxnIsRunning(builder, xid))
+	{
+		Assert(builder->running.xcnt > 0);
+
+		if (!--builder->running.xcnt)
+		{
+			/*
+			 * None of the originally running transaction is running anymore,
+			 * so our incrementaly built snapshot now is consistent.
+			 */
+			ereport(LOG,
+					(errmsg("changeset extraction found consistent point at %X/%X",
+							(uint32)(lsn >> 32), (uint32)lsn),
+					 errdetail("xid %u finished, no running transactions anymore",
+							   xid)));
+			builder->state = SNAPBUILD_CONSISTENT;
+		}
+	}
+}
+
+/*
+ * Abort a transaction, throw away all state we kept.
+ */
+void
+SnapBuildAbortTxn(SnapBuild *builder, XLogRecPtr lsn,
+				  TransactionId xid,
+				  int nsubxacts, TransactionId *subxacts)
+{
+	int			i;
+
+	for (i = 0; i < nsubxacts; i++)
+	{
+		TransactionId subxid = subxacts[i];
+
+		SnapBuildEndTxn(builder, lsn, subxid);
+	}
+
+	SnapBuildEndTxn(builder, lsn, xid);
+}
+
+/*
+ * Handle everything that needs to be done when a transaction commits
+ */
+void
+SnapBuildCommitTxn(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid,
+				   int nsubxacts, TransactionId *subxacts)
+{
+	int			nxact;
+
+	bool		forced_timetravel = false;
+	bool		sub_needs_timetravel = false;
+	bool		top_needs_timetravel = false;
+
+	TransactionId xmax = xid;
+
+	/*
+	 * If we couldn't observe every change of a transaction because it was
+	 * already running at the point we started to observe we have to assume it
+	 * made catalog changes.
+	 *
+	 * This has the positive benefit that we afterwards have enough
+	 * information to build an exportable snapshot that's usable by pg_dump et
+	 * al.
+	 */
+	if (builder->state < SNAPBUILD_CONSISTENT)
+	{
+		/* ensure that only commits after this are getting replayed */
+		if (builder->transactions_after < lsn)
+			builder->transactions_after = lsn;
+
+		/*
+		 * We could avoid treating !SnapBuildTxnIsRunning transactions as
+		 * timetravel ones, but we want to be able to export a snapshot when
+		 * we reached consistency.
+		 */
+		forced_timetravel = true;
+		elog(DEBUG1, "forced to assume catalog changes for xid %u because it was running to early", xid);
+	}
+
+	for (nxact = 0; nxact < nsubxacts; nxact++)
+	{
+		TransactionId subxid = subxacts[nxact];
+
+		/*
+		 * make sure txn is not tracked in running txn's anymore, switch state
+		 */
+		SnapBuildEndTxn(builder, lsn, subxid);
+
+		/*
+		 * If we're forcing timetravel we also need visibility information
+		 * about subtransaction, so keep track of subtransaction's state.
+		 */
+		if (forced_timetravel)
+		{
+			SnapBuildAddCommittedTxn(builder, subxid);
+			if (NormalTransactionIdFollows(subxid, xmax))
+				xmax = subxid;
+		}
+
+		/*
+		 * Add subtransaction to base snapshot if it DDL, we don't distinguish
+		 * to toplevel transactions there.
+		 */
+		else if (ReorderBufferXidHasCatalogChanges(builder->reorder, subxid))
+		{
+			sub_needs_timetravel = true;
+
+			elog(DEBUG1, "found subtransaction %u:%u with catalog changes.",
+				 xid, subxid);
+
+			SnapBuildAddCommittedTxn(builder, subxid);
+
+			if (NormalTransactionIdFollows(subxid, xmax))
+				xmax = subxid;
+		}
+	}
+
+	/*
+	 * Make sure toplevel txn is not tracked in running txn's anymore, switch
+	 * state to consistent if possible.
+	 */
+	SnapBuildEndTxn(builder, lsn, xid);
+
+	if (forced_timetravel)
+	{
+		elog(DEBUG2, "forced transaction %u to do timetravel.", xid);
+
+		SnapBuildAddCommittedTxn(builder, xid);
+	}
+	/* add toplevel transaction to base snapshot */
+	else if (ReorderBufferXidHasCatalogChanges(builder->reorder, xid))
+	{
+		elog(DEBUG2, "found top level transaction %u, with catalog changes!",
+			 xid);
+
+		top_needs_timetravel = true;
+		SnapBuildAddCommittedTxn(builder, xid);
+	}
+	else if (sub_needs_timetravel)
+	{
+		/* mark toplevel txn as timetravel as well */
+		SnapBuildAddCommittedTxn(builder, xid);
+	}
+
+	/* if there's any reason to build a historic snapshot, to so now */
+	if (forced_timetravel || top_needs_timetravel || sub_needs_timetravel)
+	{
+		/*
+		 * Adjust xmax of the snapshot builder, we only do that for committed,
+		 * catalog modifying, transactions, everything else isn't interesting
+		 * for us since we'll never look at the respective rows.
+		 */
+		if (!TransactionIdIsValid(builder->xmax) ||
+			TransactionIdFollowsOrEquals(xmax, builder->xmax))
+		{
+			builder->xmax = xmax;
+			TransactionIdAdvance(builder->xmax);
+		}
+
+		/*
+		 * If we haven't built a complete snapshot yet there's no need to hand
+		 * it out, it wouldn't (and couldn't) be used anyway.
+		 */
+		if (builder->state < SNAPBUILD_FULL_SNAPSHOT)
+			return;
+
+		/*
+		 * Decrease the snapshot builder's refcount of the old snapshot, note
+		 * that it still will be used if it has been handed out to the
+		 * reorderbuffer earlier.
+		 */
+		if (builder->snapshot)
+			SnapBuildSnapDecRefcount(builder->snapshot);
+
+		builder->snapshot = SnapBuildBuildSnapshot(builder, xid);
+
+		/* we might need to execute invalidations, add snapshot */
+		if (!ReorderBufferXidHasBaseSnapshot(builder->reorder, xid))
+		{
+			SnapBuildSnapIncRefcount(builder->snapshot);
+			ReorderBufferSetBaseSnapshot(builder->reorder, xid, lsn,
+										 builder->snapshot);
+		}
+
+		/* refcount of the snapshot builder for the new snapshot */
+		SnapBuildSnapIncRefcount(builder->snapshot);
+
+		/* add a new SnapshotNow to all currently running transactions */
+		SnapBuildDistributeNewCatalogSnapshot(builder, lsn);
+	}
+	else
+	{
+		/* record that we cannot export a general snapshot anymore */
+		builder->committed.includes_all_transactions = false;
+	}
+}
+
+
+/* -----------------------------------
+ * Snapshot building functions dealing with xlog records
+ * -----------------------------------
+ */
+
+/*
+ * Process a running xacts record, and use it's information to first build a
+ * historic snapshot and later to release resources that aren't needed
+ * anymore.
+ */
+void
+SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *running)
+{
+	ReorderBufferTXN *txn;
+
+	/*
+	 * If we're not consistent yet, inspect the record to see whether it
+	 * allows to get closer to being consistent. If we are consistent, dump
+	 * our snapshot so others or we, after a restart, can use it.
+	 */
+	if (builder->state < SNAPBUILD_CONSISTENT)
+	{
+		/* returns false if there's no point in performing cleanup just yet */
+		if (!SnapBuildFindSnapshot(builder, lsn, running))
+			return;
+	}
+	else
+		SnapBuildSerialize(builder, lsn);
+
+	/*
+	 * Update range of interesting xids base don the running xacts
+	 * information. We don't increase ->xmax using it, because once we are in
+	 * a consistent state we can do that ourselves and much more efficiently
+	 * so, because we only need to do it for catalog transactions since we
+	 * only ever look at those.
+	 *
+	 * NB: Because of that xmax can be lower than xmin, because we only
+	 * increase xmax when a catalog modifying transaction commits. While odd
+	 * looking, its correct and actually more efficient this way since we hit
+	 * fast paths in tqual.c.
+	 */
+	builder->xmin = running->oldestRunningXid;
+
+	/* Remove transactions we don't need to keep track off anymore */
+	SnapBuildPurgeCommittedTxn(builder);
+
+	elog(DEBUG3, "xmin: %u, xmax: %u, oldestrunning: %u",
+		 builder->xmin, builder->xmax,
+		 running->oldestRunningXid);
+
+	/*
+	 * Inrease shared memory limits, so vacuum can work on tuples we prevented
+	 * from being pruned till now.
+	 */
+	IncreaseLogicalXminForSlot(lsn, running->oldestRunningXid);
+
+	/*
+	 * Also tell the slot where we can restart decoding from. We don't want to
+	 * do that after every commit because changing that implies an fsync of
+	 * the logical slot's state file, so we only do it every time we see a
+	 * running xacts record.
+	 *
+	 * Do so by looking for the oldest in progress transaction (determined by
+	 * the first LSN of any of its relevant records). Every transaction
+	 * remembers the last location we stored the snapshot to disk before its
+	 * beginning. That point is where we can restart from.
+	 */
+
+	/*
+	 * Can't know about a serialized snapshot's location if we're not
+	 * consistent
+	 */
+	if (builder->state < SNAPBUILD_CONSISTENT)
+		return;
+
+	txn = ReorderBufferGetOldestTXN(builder->reorder);
+
+	/*
+	 * oldest ongoing txn might have started when we didn't yet serialize
+	 * anything because we hadn't reached a consistent state yet.
+	 */
+	if (txn != NULL && txn->restart_decoding_lsn != InvalidXLogRecPtr)
+		IncreaseRestartDecodingForSlot(lsn, txn->restart_decoding_lsn);
+
+	/*
+	 * No in-progress transaction, can reuse the last serialized snapshot if we
+	 * have one.
+	 */
+	else if (txn == NULL &&
+			 builder->reorder->current_restart_decoding_lsn != InvalidXLogRecPtr &&
+			 builder->last_serialized_snapshot != InvalidXLogRecPtr)
+		IncreaseRestartDecodingForSlot(lsn, builder->last_serialized_snapshot);
+}
+
+
+/*
+ * Build the start of a snapshot that's capable of decoding the
+ * catalog. Helper function for SnapBuildProcessRunningXacts() while we're not
+ * yet consistent.
+ *
+ * Returns true if there is a point in performing internal maintenance/cleanup
+ * using the xl_running_xacts record.
+ */
+static bool
+SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *running)
+{
+	/* ---
+	 * Build catalog decoding snapshot incrementally using information about
+	 * the currently running transactions. There are several ways to do that:
+
+	 * a) There were no running transactions when the xl_running_xacts record
+	 *    was inserted, jump to CONSISTENT immediately. We might find such a
+	 *    state we were waiting for b) and c).
+
+	 * b) Wait for all toplevel transactions that were running to end. We
+	 *    simply track the number of in-progress toplevel transactions and
+	 *    lower it whenever one commits or aborts. When that number
+	 *    (builder->running.xcnt) reaches zero, we can go from FULL_SNAPSHOT
+	 *    to CONSISTENT.
+	 *	  NB: We need to search running.xip when seeing a transaction's end to
+	 *    make sure it's a toplevel transaction and it's been one of the
+	 *    intially running ones.
+	 *	  Interestingly, in contrast to HS this allows us not to care about
+	 *	  subtransactions - and by extension suboverflowed xl_running_xacts -
+	 *	  at all.
+	 *
+	 * c) This (in a previous run) or another decoding slot serialized a
+	 *    snapshot to disk that we can use.
+	 * ---
+	 */
+
+	/*
+	 * xl_running_xact record is older than what we can use, we might not have
+	 * all necessary catalog rows anymore.
+	 */
+	if (TransactionIdIsNormal(builder->initial_xmin_horizon) &&
+		NormalTransactionIdPrecedes(running->oldestRunningXid,
+									builder->initial_xmin_horizon))
+	{
+		ereport(DEBUG1,
+				(errmsg("skipping snapshot at %X/%X while building changeset extraction snapshot, xmin horizon too low",
+						(uint32) (lsn >> 32), (uint32) lsn),
+				 errdetail("initial xmin horizon of %u vs the snapshot's %u",
+						   builder->initial_xmin_horizon, running->oldestRunningXid)));
+		return true;
+	}
+
+	/*
+	 * a) No transaction were running, we can jump to consistent.
+	 *
+	 * NB: We might have already started to incrementally assemble a snapshot,
+	 * so we need to be careful to deal with that.
+	 */
+	if (running->xcnt == 0)
+	{
+		if (builder->transactions_after == InvalidXLogRecPtr ||
+			builder->transactions_after < lsn)
+			builder->transactions_after = lsn;
+
+		builder->xmin = running->oldestRunningXid;
+		builder->xmax = running->latestCompletedXid;
+		TransactionIdAdvance(builder->xmax);
+
+		Assert(TransactionIdIsNormal(builder->xmin));
+		Assert(TransactionIdIsNormal(builder->xmax));
+
+		/* no transactions running now */
+		builder->running.xcnt = 0;
+		builder->running.xmin = InvalidTransactionId;
+		builder->running.xmax = InvalidTransactionId;
+
+		builder->state = SNAPBUILD_CONSISTENT;
+
+		ereport(LOG,
+				(errmsg("changeset extraction found consistent point at %X/%X",
+						(uint32)(lsn >> 32), (uint32)lsn),
+				 errdetail("running xacts with xcnt == 0")));
+
+		return false;
+	}
+	/* c) valid on disk state */
+	else if (SnapBuildRestore(builder, lsn))
+	{
+		/* there won't be any state to cleanup */
+		return false;
+	}
+	/*
+	 * b) first encounter of a useable xl_running_xacts record. If we had
+	 * found one earlier we would either track running transactions
+	 * (i.e. builder->running.xcnt != 0) or be consistent (this function
+	 * wouldn't get called)..
+	 */
+	else if (!builder->running.xcnt)
+	{
+		int off;
+
+		/*
+		 * We only care about toplevel xids as those are the ones we
+		 * definitely see in the wal stream. As snapbuild.c tracks committed
+		 * instead of running transactions we don't need to know anything
+		 * about uncommitted subtransactions.
+		 */
+		builder->xmin = running->oldestRunningXid;
+		builder->xmax = running->latestCompletedXid;
+		TransactionIdAdvance(builder->xmax);
+
+		/* so we can safely use the faster comparisons */
+		Assert(TransactionIdIsNormal(builder->xmin));
+		Assert(TransactionIdIsNormal(builder->xmax));
+
+		builder->running.xcnt = running->xcnt;
+		builder->running.xcnt_space = running->xcnt;
+		builder->running.xip =
+			MemoryContextAlloc(builder->context,
+							builder->running.xcnt * sizeof(TransactionId));
+		memcpy(builder->running.xip, running->xids,
+			   builder->running.xcnt * sizeof(TransactionId));
+
+		/* sort so we can do a binary search */
+		qsort(builder->running.xip, builder->running.xcnt,
+			  sizeof(TransactionId), xidComparator);
+
+		builder->running.xmin = builder->running.xip[0];
+		builder->running.xmax = builder->running.xip[running->xcnt - 1];
+
+		/* makes comparisons cheaper later */
+		TransactionIdRetreat(builder->running.xmin);
+		TransactionIdAdvance(builder->running.xmax);
+
+		builder->state = SNAPBUILD_FULL_SNAPSHOT;
+
+		ereport(LOG,
+				(errmsg("changeset extraction found initial starting point at %X/%X",
+						(uint32)(lsn >> 32), (uint32)lsn),
+				 errdetail("%u xacts need to finish", (uint32) builder->running.xcnt)));
+
+		/*
+		 * Iterate through all xids, wait for them to finish.
+		 *
+		 * This isn't required for the correctness of decoding, but to allow
+		 * isolationtester to notice that we're currently waiting for
+		 * something.
+		 */
+		for(off = 0; off < builder->running.xcnt; off++)
+			XactLockTableWait(builder->running.xip[off]);
+
+		/* nothing could have built up so far, so don't perform cleanup */
+		return false;
+	}
+
+	/*
+	 * We already started to track running xacts and need to wait for all
+	 * in-progress ones to finish. We fall through to the normal processing of
+	 * records so incremental cleanup can be performed.
+	 */
+	return true;
+}
+
+
+/* -----------------------------------
+ * Snapshot serialization support
+ * -----------------------------------
+ */
+
+/*
+ * We store current state of struct SnapBuild on disk in the following manner:
+ *
+ * struct SnapBuildOnDisk;
+ * TransactionId * running.xcnt_space;
+ * TransactionId * committed.xcnt; (*not xcnt_space*)
+ *
+ */
+typedef struct SnapBuildOnDisk
+{
+	/* first part of this struct needs to be version independent */
+
+	/* data not covered by checksum */
+	uint32		magic;
+	pg_crc32	checksum;
+
+	/* data covered by checksum */
+
+	/* version, in case we want to support pg_upgrade */
+	uint32		version;
+	/* how large is the on disk data, excluding the constant sized part */
+	uint32		length;
+
+	/* version dependent part */
+	SnapBuild	builder;
+
+	/* variable amount of TransactionIds follows */
+} SnapBuildOnDisk;
+
+#define SnapBuildOnDiskConstantSize \
+	offsetof(SnapBuildOnDisk, builder)
+#define SnapBuildOnDiskNotChecksummedSize \
+	offsetof(SnapBuildOnDisk, version)
+
+#define SNAPBUILD_MAGIC 0x51A1E001
+#define SNAPBUILD_VERSION 1
+
+/*
+ * Store/Load a snapshot from disk, depending on the snapshot builder's state.
+ *
+ * Supposed to be used by external (i.e. not snapbuild.c) code that just reada
+ * record that's a potential location for a serialized snapshot.
+ */
+void
+SnapBuildSerializationPoint(SnapBuild *builder, XLogRecPtr lsn)
+{
+	if (builder->state < SNAPBUILD_CONSISTENT)
+		SnapBuildRestore(builder, lsn);
+	else
+		SnapBuildSerialize(builder, lsn);
+}
+
+/*
+ * Serialize the snapshot 'builder' at the location 'lsn' if it hasn't already
+ * been done by another decoding process.
+ */
+static void
+SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
+{
+	Size		needed_length;
+	SnapBuildOnDisk *ondisk;
+	char	   *ondisk_c;
+	int			fd;
+	char		tmppath[MAXPGPATH];
+	char		path[MAXPGPATH];
+	int			ret;
+	struct stat stat_buf;
+	uint32		sz;
+
+	Assert(lsn != InvalidXLogRecPtr);
+	Assert(builder->last_serialized_snapshot == InvalidXLogRecPtr ||
+		   builder->last_serialized_snapshot <= lsn);
+
+	/*
+	 * no point in serializing if we cannot continue to work immediately after
+	 * restoring the snapshot
+	 */
+	if (builder->state < SNAPBUILD_CONSISTENT)
+		return;
+
+	/*
+	 * FIXME: Timeline handling/naming.
+	 */
+
+	/*
+	 * first check whether some other backend already has written the snapshot
+	 * for this LSN. It's perfectly fine if there's none, so we accept ENOENT
+	 * as a valid state. Everything else is an unexpected error.
+	 */
+	sprintf(path, "pg_llog/snapshots/%X-%X.snap",
+			(uint32) (lsn >> 32), (uint32) lsn);
+
+	ret = stat(path, &stat_buf);
+
+	if (ret != 0 && errno != ENOENT)
+		ereport(ERROR,
+				(errmsg("could not stat file \"%s\": %m", path)));
+
+	else if (ret == 0)
+	{
+		/*
+		 * somebody else has already serialized to this point, don't overwrite
+		 * but remember location, so we don't need to read old data again.
+		 *
+		 * To be sure it has been synced to disk after the rename() from the
+		 * tempfile filename to the real filename, we just repeat the
+		 * fsync. That ought to be cheap because in most scenarios it should
+		 * already be safely on disk.
+		 */
+		fsync_fname(path, false);
+		fsync_fname("pg_llog/snapshots", true);
+
+		builder->last_serialized_snapshot = lsn;
+		goto out;
+	}
+
+	/*
+	 * there is an obvious race condition here between the time we stat(2) the
+	 * file and us writing the file. But we rename the file into place
+	 * atomically and all files created need to contain the same data anyway,
+	 * so this is perfectly fine, although a bit of a resource waste. Locking
+	 * seems like pointless complication.
+	 */
+	elog(DEBUG1, "serializing snapshot to %s", path);
+
+	/* to make sure only we will write to this tempfile, include pid */
+	sprintf(tmppath, "pg_llog/snapshots/%X-%X.snap.%u.tmp",
+			(uint32) (lsn >> 32), (uint32) lsn, MyProcPid);
+
+	/*
+	 * Unlink temporary file if it already exists, needs to have been before a
+	 * crash/error since we won't enter this function twice from within a
+	 * single decoding slot/backend and the temporary file contains the pid of
+	 * the current process.
+	 */
+	if (unlink(tmppath) != 0 && errno != ENOENT)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not unlink file \"%s\": %m",	path)));
+
+	needed_length = sizeof(SnapBuildOnDisk) +
+		sizeof(TransactionId) * builder->running.xcnt_space +
+		sizeof(TransactionId) * builder->committed.xcnt;
+
+	ondisk_c = MemoryContextAllocZero(builder->context, needed_length);
+	ondisk = (SnapBuildOnDisk *) ondisk_c;
+	ondisk->magic = SNAPBUILD_MAGIC;
+	ondisk->version = SNAPBUILD_VERSION;
+	ondisk->length = needed_length;
+	INIT_CRC32(ondisk->checksum);
+	COMP_CRC32(ondisk->checksum,
+			   ((char *) ondisk) + SnapBuildOnDiskNotChecksummedSize,
+			   SnapBuildOnDiskConstantSize - SnapBuildOnDiskNotChecksummedSize);
+	ondisk_c += sizeof(SnapBuildOnDisk);
+
+	memcpy(&ondisk->builder, builder, sizeof(SnapBuild));
+	/* NULL-ify memory-only data */
+	ondisk->builder.context = NULL;
+	ondisk->builder.snapshot = NULL;
+	ondisk->builder.reorder = NULL;
+	ondisk->builder.running.xip = NULL;
+	ondisk->builder.committed.xip = NULL;
+
+	COMP_CRC32(ondisk->checksum,
+			   &ondisk->builder,
+			   sizeof(SnapBuild));
+
+	/* copy running xacts */
+	sz = sizeof(TransactionId) * builder->running.xcnt_space;
+	memcpy(ondisk_c, builder->running.xip, sz);
+	COMP_CRC32(ondisk->checksum, ondisk_c, sz);
+	ondisk_c += sz;
+
+	/* copy committed xacts */
+	sz = sizeof(TransactionId) * builder->committed.xcnt;
+	memcpy(ondisk_c, builder->committed.xip, sz);
+	COMP_CRC32(ondisk->checksum, ondisk_c, sz);
+	ondisk_c += sz;
+
+	/* we have valid data now, open tempfile and write it there */
+	fd = OpenTransientFile(tmppath,
+						   O_CREAT | O_EXCL | O_WRONLY | PG_BINARY,
+						   S_IRUSR | S_IWUSR);
+	if (fd < 0)
+		ereport(ERROR,
+				(errmsg("could not open file \"%s\": %m", path)));
+
+	if ((write(fd, ondisk, needed_length)) != needed_length)
+	{
+		CloseTransientFile(fd);
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not write to file \"%s\": %m", tmppath)));
+	}
+
+	/*
+	 * fsync the file before renaming so that even if we crash after this we
+	 * have either a fully valid file or nothing.
+	 *
+	 * TODO: Do the fsync() via checkpoints/restartpoints, doing it here has
+	 * some noticeable overhead since it's performed synchronously during
+	 * decoding?
+	 */
+	if (pg_fsync(fd) != 0)
+	{
+		CloseTransientFile(fd);
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not fsync file \"%s\": %m", tmppath)));
+	}
+	CloseTransientFile(fd);
+
+	fsync_fname("pg_llog/snapshots", true);
+
+	/*
+	 * We may overwrite the work from some other backend, but that's ok, our
+	 * snapshot is valid as well, we'll just have done some superflous work.
+	 */
+	if (rename(tmppath, path) != 0)
+	{
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not rename file \"%s\" to \"%s\": %m",
+						tmppath, path)));
+	}
+
+	/* make sure we persist */
+	fsync_fname(path, false);
+	fsync_fname("pg_llog/snapshots", true);
+
+	/*
+	 * Now there's no way we can loose the dumped state anymore, remember
+	 * this as a serialization point.
+	 */
+	builder->last_serialized_snapshot = lsn;
+
+out:
+	ReorderBufferSetRestartPoint(builder->reorder,
+								 builder->last_serialized_snapshot);
+}
+
+/*
+ * Restore a snapshot into 'builder' if previously one has been stored at the
+ * location indicated by 'lsn'. Returns true if successfull, false otherwise.
+ */
+static bool
+SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
+{
+	SnapBuildOnDisk ondisk;
+	int			fd;
+	char		path[MAXPGPATH];
+	Size		sz;
+	int			readBytes;
+	pg_crc32	checksum;
+
+	/* no point in loading a snapshot if we're already there */
+	if (builder->state == SNAPBUILD_CONSISTENT)
+		return false;
+
+	sprintf(path, "pg_llog/snapshots/%X-%X.snap",
+			(uint32) (lsn >> 32), (uint32) lsn);
+
+	fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+
+	if (fd < 0 && errno == ENOENT)
+		return false;
+	else if (fd < 0)
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not open file \"%s\": %m", path)));
+
+	/* ----
+	 * Make sure the snapshot had been stored safely to disk, that's normally
+	 * cheap.
+	 * Note that we do not need PANIC here, nobody will be able to use the
+	 * slot without fsyncing, and saving it won't suceed without an fsync()
+	 * either...
+	 * ----
+	 */
+	fsync_fname(path, false);
+	fsync_fname("pg_llog/snapshots", true);
+
+
+	/* read statically sized portion of snapshot */
+	readBytes = read(fd, &ondisk, SnapBuildOnDiskConstantSize);
+	if (readBytes != SnapBuildOnDiskConstantSize)
+	{
+		CloseTransientFile(fd);
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not read file \"%s\", read %d of %d: %m",
+						path, readBytes, (int) SnapBuildOnDiskConstantSize)));
+	}
+
+	if (ondisk.magic != SNAPBUILD_MAGIC)
+		ereport(ERROR,
+				(errmsg("snapbuild state file \"%s\" has wrong magic %u instead of %u",
+						path, ondisk.magic, SNAPBUILD_MAGIC)));
+
+	if (ondisk.version != SNAPBUILD_VERSION)
+		ereport(ERROR,
+				(errmsg("snapbuild state file \"%s\" has unsupported version %u instead of %u",
+						path, ondisk.version, SNAPBUILD_VERSION)));
+
+	INIT_CRC32(checksum);
+	COMP_CRC32(checksum,
+			   ((char *) &ondisk) + SnapBuildOnDiskNotChecksummedSize,
+			   SnapBuildOnDiskConstantSize - SnapBuildOnDiskNotChecksummedSize);
+
+	/* read SnapBuild */
+	readBytes = read(fd, &ondisk.builder, sizeof(SnapBuild));
+	if (readBytes != sizeof(SnapBuild))
+	{
+		CloseTransientFile(fd);
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not read file \"%s\", read %d of %d: %m",
+						path, readBytes, (int) sizeof(SnapBuild))));
+	}
+	COMP_CRC32(checksum, &ondisk.builder, sizeof(SnapBuild));
+
+	/* restore running xacts information */
+	sz = sizeof(TransactionId) * ondisk.builder.running.xcnt_space;
+	ondisk.builder.running.xip = MemoryContextAlloc(builder->context, sz);
+	readBytes = read(fd, ondisk.builder.running.xip, sz);
+	if (readBytes != sz)
+	{
+		CloseTransientFile(fd);
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not read file \"%s\", read %d of %d: %m",
+						path, readBytes, (int) sz)));
+	}
+	COMP_CRC32(checksum, ondisk.builder.running.xip, sz);
+
+	/* restore committed xacts information */
+	sz = sizeof(TransactionId) * ondisk.builder.committed.xcnt;
+	ondisk.builder.committed.xip = MemoryContextAlloc(builder->context, sz);
+	readBytes = read(fd, ondisk.builder.committed.xip, sz);
+	if (readBytes != sz)
+	{
+		CloseTransientFile(fd);
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not read file \"%s\", read %d of %d: %m",
+						path, readBytes, (int) sz)));
+	}
+	COMP_CRC32(checksum, ondisk.builder.committed.xip, sz);
+
+	CloseTransientFile(fd);
+
+	/* verify checksum of what we've read */
+	if (!EQ_CRC32(checksum, ondisk.checksum))
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("snapbuild state file %s: checksum mismatch, is %u, should be %u",
+						path, checksum, ondisk.checksum)));
+
+	/*
+	 * ok, we now have a sensible snapshot here, figure out if it has more
+	 * information than we have.
+	 */
+
+	/*
+	 * We are only interested in consistent snapshots for now, comparing
+	 * whether one imcomplete snapshot is more "advanced" seems to be
+	 * unnecessarily complex.
+	 */
+	if (ondisk.builder.state < SNAPBUILD_CONSISTENT)
+		goto snapshot_not_interesting;
+
+	/*
+	 * Don't use a snapshot that requires an xmin that we cannot guarantee to
+	 * be available.
+	 */
+	if (TransactionIdPrecedes(ondisk.builder.xmin, builder->initial_xmin_horizon))
+		goto snapshot_not_interesting;
+
+	/*
+	 * XXX: transactions_after needs to be updated differently, to be checked
+	 * here
+	 */
+
+	/* ok, we think the snapshot is sensible, copy over everything important */
+	builder->xmin = ondisk.builder.xmin;
+	builder->xmax = ondisk.builder.xmax;
+	builder->state = ondisk.builder.state;
+
+	builder->committed.xcnt = ondisk.builder.committed.xcnt;
+	/* We only allocated/stored xcnt, not xcnt_space xids ! */
+	/* don't overwrite preallocated xip, if we don't have anything here */
+	if (builder->committed.xcnt > 0)
+	{
+		pfree(builder->committed.xip);
+		builder->committed.xcnt_space = ondisk.builder.committed.xcnt;
+		builder->committed.xip = ondisk.builder.committed.xip;
+	}
+	ondisk.builder.committed.xip = NULL;
+
+	builder->running.xcnt = ondisk.builder.committed.xcnt;
+	if (builder->running.xip)
+		pfree(builder->running.xip);
+	builder->running.xcnt_space = ondisk.builder.committed.xcnt_space;
+	builder->running.xip = ondisk.builder.running.xip;
+
+	/* our snapshot is not interesting anymore, build a new one */
+	if (builder->snapshot != NULL)
+	{
+		SnapBuildSnapDecRefcount(builder->snapshot);
+	}
+	builder->snapshot = SnapBuildBuildSnapshot(builder, InvalidTransactionId);
+	SnapBuildSnapIncRefcount(builder->snapshot);
+
+	ReorderBufferSetRestartPoint(builder->reorder, lsn);
+
+	Assert(builder->state == SNAPBUILD_CONSISTENT);
+
+	ereport(LOG,
+			(errmsg("changeset extraction found consistent point at %X/%X",
+					(uint32)(lsn >> 32), (uint32)lsn),
+			 errdetail("found initial snapshot in snapbuild file")));
+	return true;
+
+snapshot_not_interesting:
+	if (ondisk.builder.running.xip != NULL)
+		pfree(ondisk.builder.running.xip);
+	if (ondisk.builder.committed.xip != NULL)
+		pfree(ondisk.builder.committed.xip);
+	return false;
+}
+
+/*
+ * Remove all serialized snapshots that are not required anymore because no
+ * slot can need them. This doesn't actually have to run during a checkpoint,
+ * but it's a convenient point to schedule this.
+ *
+ * NB: We run this during checkpoints even if logical decoding is disabled so
+ * we cleanup old slots at some point after it got disabled.
+ */
+void
+CheckPointSnapBuild(void)
+{
+	XLogRecPtr	cutoff;
+	XLogRecPtr	redo;
+	DIR		   *snap_dir;
+	struct dirent *snap_de;
+	char		path[MAXPGPATH];
+
+	/*
+	 * We start of with a minimum of the last redo pointer. No new replication
+	 * slot will start before that, so that's a safe upper bound for removal.
+	 */
+	redo = GetRedoRecPtr();
+
+	/* now check for the restart ptrs from existing slots */
+	cutoff = ComputeLogicalRestartLSN();
+
+	/* don't start earlier than the restart lsn */
+	if (redo < cutoff)
+		cutoff = redo;
+
+	snap_dir = AllocateDir("pg_llog/snapshots");
+	while ((snap_de = ReadDir(snap_dir, "pg_llog/snapshots")) != NULL)
+	{
+		uint32		hi;
+		uint32		lo;
+		XLogRecPtr	lsn;
+		struct stat	statbuf;
+
+		if (strcmp(snap_de->d_name, ".") == 0 ||
+			strcmp(snap_de->d_name, "..") == 0)
+			continue;
+
+		snprintf(path, MAXPGPATH, "pg_llog/snapshots/%s", snap_de->d_name);
+
+		if (lstat(path, &statbuf) == 0 && !S_ISREG(statbuf.st_mode))
+		{
+			elog(DEBUG1, "only regular files expected: %s", path);
+			continue;
+		}
+
+		/*
+		 * temporary filenames from SnapBuildSerialize() include the LSN and
+		 * everything but are postfixed by .$pid.tmp. We can just remove them
+		 * the same as other files because there can be none that are currently
+		 * being written that are older than cutoff.
+		 *
+		 * We just log a message if a file doesn't fit the pattern, it's
+		 * probably some editors lock/state file or similar...
+		 */
+		if (sscanf(snap_de->d_name, "%X-%X.snap", &hi, &lo) != 2)
+		{
+			ereport(LOG,
+					(errmsg("could not parse filename \"%s\"", path)));
+			continue;
+		}
+
+		lsn = ((uint64) hi) << 32 | lo;
+
+		/* check whether we still need it */
+		if (lsn < cutoff || cutoff == InvalidXLogRecPtr)
+		{
+			elog(DEBUG1, "removing snapbuild snapshot %s", path);
+
+			/*
+			 * It's not particularly harmful, though strange, if we can't
+			 * remove the file here. Don't prevent the checkpoint from
+			 * completing, that'd be cure worse than the disease.
+			 */
+			if (unlink(path) < 0)
+			{
+				ereport(LOG,
+						(errcode_for_file_access(),
+						 errmsg("could not unlink file \"%s\": %m",
+								path)));
+				continue;
+			}
+		}
+	}
+	FreeDir(snap_dir);
+}
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 826c7f0..88b137c 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -43,6 +43,7 @@
 #include "miscadmin.h"
 #include "replication/slot.h"
 #include "storage/fd.h"
+#include "storage/proc.h"
 #include "storage/procarray.h"
 
 /*
@@ -356,6 +357,11 @@ ReplicationSlotRelease(void)
 		SpinLockRelease(&slot->mutex);
 		MyReplicationSlot = NULL;
 	}
+
+	/* might not have been set when we've been a plain slot */
+	LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+	MyPgXact->vacuumFlags &= ~PROC_IN_LOGICAL_DECODING;
+	LWLockRelease(ProcArrayLock);
 }
 
 /*
@@ -461,7 +467,7 @@ ReplicationSlotDrop(const char *name)
 	 * Slot is dead and doesn't prevent resource removal anymore, recompute
 	 * limits.
 	 */
-	ReplicationSlotsComputeRequiredXmin();
+	ReplicationSlotsComputeRequiredXmin(false);
 	ReplicationSlotsComputeRequiredLSN();
 
 	/*
@@ -522,18 +528,22 @@ ReplicationSlotMarkDirty(void)
  * Compute the oldest xmin across all slots and store it in the ProcArray.
  */
 void
-ReplicationSlotsComputeRequiredXmin(void)
+ReplicationSlotsComputeRequiredXmin(bool already_locked)
 {
 	int			i;
 	TransactionId agg_xmin = InvalidTransactionId;
+	TransactionId agg_catalog_xmin = InvalidTransactionId;
 
 	Assert(ReplicationSlotCtl != NULL);
 
-	LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
+	if (!already_locked)
+		LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
+
 	for (i = 0; i < max_replication_slots; i++)
 	{
 		ReplicationSlot *s = &ReplicationSlotCtl->replication_slots[i];
 		TransactionId	effective_xmin;
+		TransactionId	effective_catalog_xmin;
 
 		if (!s->in_use)
 			continue;
@@ -543,6 +553,7 @@ ReplicationSlotsComputeRequiredXmin(void)
 
 			SpinLockAcquire(&s->mutex);
 			effective_xmin = vslot->effective_xmin;
+			effective_catalog_xmin = vslot->effective_catalog_xmin;
 			SpinLockRelease(&s->mutex);
 		}
 
@@ -551,10 +562,18 @@ ReplicationSlotsComputeRequiredXmin(void)
 			(!TransactionIdIsValid(agg_xmin) ||
 			 TransactionIdPrecedes(effective_xmin, agg_xmin)))
 			agg_xmin = effective_xmin;
+
+		/* check the catalog xmin */
+		if (TransactionIdIsValid(effective_catalog_xmin) &&
+			(!TransactionIdIsValid(agg_catalog_xmin) ||
+			 TransactionIdPrecedes(effective_catalog_xmin, agg_catalog_xmin)))
+			agg_catalog_xmin = effective_catalog_xmin;
 	}
-	LWLockRelease(ReplicationSlotControlLock);
 
-	ProcArraySetReplicationSlotXmin(agg_xmin);
+	if (!already_locked)
+		LWLockRelease(ReplicationSlotControlLock);
+
+	ProcArraySetReplicationSlotXmin(agg_xmin, agg_catalog_xmin, already_locked);
 }
 
 /*
@@ -614,6 +633,31 @@ CheckSlotRequirements(void)
 }
 
 /*
+ * Make sure this backend hasn't acquired a replication slot when exiting.
+ */
+void
+ReplicationSlotAtProcExit(void)
+{
+	if (MyReplicationSlot && MyReplicationSlot->active)
+	{
+		/*
+		 * Acquire spinlock so other backends are guaranteed to see this in
+		 * time - we cannot generally acquire the lwlock here since we might
+		 * be still holding it in an error path.
+		 */
+		SpinLockAcquire(&MyReplicationSlot->mutex);
+		MyReplicationSlot->active = false;
+		SpinLockRelease(&MyReplicationSlot->mutex);
+
+		/* might not have been set when we've been a plain slot */
+		LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+		MyPgXact->vacuumFlags &= ~PROC_IN_LOGICAL_DECODING;
+		LWLockRelease(ProcArrayLock);
+	}
+	MyReplicationSlot = NULL;
+}
+
+/*
  * Returns whether the string `str' has the postfix `end'.
  */
 static bool
@@ -723,7 +767,7 @@ StartupReplicationSlots(XLogRecPtr checkPointRedo)
 		return;
 
 	/* Now that we have recovered all the data, compute replication xmin */
-	ReplicationSlotsComputeRequiredXmin();
+	ReplicationSlotsComputeRequiredXmin(false);
 	ReplicationSlotsComputeRequiredLSN();
 }
 
@@ -1052,6 +1096,13 @@ RestoreSlotFromDisk(const char *name)
 
 		/* initialize in memory state */
 		slot->effective_xmin = cp.slotdata.xmin;
+		slot->effective_catalog_xmin = cp.slotdata.catalog_xmin;
+
+		slot->candidate_catalog_xmin = InvalidTransactionId;
+		slot->candidate_xmin_lsn = InvalidXLogRecPtr;
+		slot->candidate_restart_lsn = InvalidXLogRecPtr;
+		slot->candidate_restart_valid = InvalidXLogRecPtr;
+
 		slot->in_use = true;
 		slot->active = false;
 
diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c
index 98a860e..980545b 100644
--- a/src/backend/replication/slotfuncs.c
+++ b/src/backend/replication/slotfuncs.c
@@ -91,7 +91,7 @@ pg_drop_replication_slot(PG_FUNCTION_ARGS)
 Datum
 pg_get_replication_slots(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_REPLICATION_SLOTS_COLS 6
+#define PG_GET_REPLICATION_SLOTS_COLS 8
 	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
 	TupleDesc	tupdesc;
 	Tuplestorestate *tupstore;
@@ -133,14 +133,16 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
 	for (slotno = 0; slotno < max_replication_slots; slotno++)
 	{
 		ReplicationSlot *slot = &ReplicationSlotCtl->replication_slots[slotno];
-		Datum		values[PG_STAT_GET_REPLICATION_SLOTS_COLS];
-		bool		nulls[PG_STAT_GET_REPLICATION_SLOTS_COLS];
+		Datum		values[PG_GET_REPLICATION_SLOTS_COLS];
+		bool		nulls[PG_GET_REPLICATION_SLOTS_COLS];
 
 		TransactionId xmin;
+		TransactionId catalog_xmin;
 		XLogRecPtr	restart_lsn;
 		bool		active;
 		Oid			database;
 		const char *slot_name;
+		const char *plugin;
 
 		char		restart_lsn_s[MAXFNAMELEN];
 		int			i;
@@ -154,9 +156,11 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
 		else
 		{
 			xmin = slot->data.xmin;
+			catalog_xmin = slot->data.catalog_xmin;
 			database = slot->data.database;
 			restart_lsn = slot->data.restart_lsn;
 			slot_name = pstrdup(NameStr(slot->data.name));
+			plugin = pstrdup(NameStr(slot->data.plugin));
 
 			active = slot->active;
 		}
@@ -169,16 +173,22 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
 
 		i = 0;
 		values[i++] = CStringGetTextDatum(slot_name);
+		values[i++] = CStringGetTextDatum(plugin);
 		if (database == InvalidOid)
 			values[i++] = CStringGetTextDatum("physical");
 		else
 			values[i++] = CStringGetTextDatum("logical");
 		values[i++] = database;
 		values[i++] = BoolGetDatum(active);
+
 		if (xmin != InvalidTransactionId)
 			values[i++] = TransactionIdGetDatum(xmin);
 		else
 			nulls[i++] = true;
+		if (xmin != InvalidTransactionId)
+			values[i++] = TransactionIdGetDatum(catalog_xmin);
+		else
+			nulls[i++] = true;
 		if (restart_lsn != InvalidTransactionId)
 			values[i++] = CStringGetTextDatum(restart_lsn_s);
 		else
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index e31977e..77e0df8 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -1147,7 +1147,7 @@ XLogWalRcvSendHSFeedback(bool immed)
 	 * everything else has been checked.
 	 */
 	if (hot_standby_feedback)
-		xmin = GetOldestXmin(true, false);
+		xmin = GetOldestXmin(true, true, true);
 	else
 		xmin = InvalidTransactionId;
 
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 06b22e2..88119b9 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -55,6 +55,7 @@
 #include "replication/basebackup.h"
 #include "replication/slot.h"
 #include "replication/syncrep.h"
+#include "replication/slot.h"
 #include "replication/walreceiver.h"
 #include "replication/walsender.h"
 #include "replication/walsender_private.h"
@@ -1049,7 +1050,7 @@ PhysicalReplicationSlotNewXmin(TransactionId feedbackXmin)
 	if (changed)
 	{
 		ReplicationSlotMarkDirty();
-		ReplicationSlotsComputeRequiredXmin();
+		ReplicationSlotsComputeRequiredXmin(false);
 	}
 }
 
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 082115b..6829da0 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -84,6 +84,8 @@ typedef struct ProcArrayStruct
 
 	/* oldest xmin of any replication slot */
 	TransactionId replication_slot_xmin;
+	/* oldest catalog xmin of any replication slot */
+	TransactionId replication_slot_catalog_xmin;
 
 	/*
 	 * We declare pgprocnos[] as 1 entry because C wants a fixed-size array,
@@ -1152,12 +1154,13 @@ TransactionIdIsActive(TransactionId xid)
  * GetOldestXmin() move backwards, with no consequences for data integrity.
  */
 TransactionId
-GetOldestXmin(bool allDbs, bool ignoreVacuum)
+GetOldestXmin(bool allDbs, bool ignoreVacuum, bool systable)
 {
 	ProcArrayStruct *arrayP = procArray;
 	TransactionId result;
 	int			index;
 	volatile TransactionId replication_slot_xmin = InvalidTransactionId;
+	volatile TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
 
 	/* Cannot look for individual databases during recovery */
 	Assert(allDbs || !RecoveryInProgress());
@@ -1180,6 +1183,13 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum)
 		volatile PGPROC *proc = &allProcs[pgprocno];
 		volatile PGXACT *pgxact = &allPgXact[pgprocno];
 
+		/*
+		 * Backend is doing logical decoding which manages xmin
+		 * separately, check below.
+		 */
+		if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING)
+			continue;
+
 		if (ignoreVacuum && (pgxact->vacuumFlags & PROC_IN_VACUUM))
 			continue;
 
@@ -1211,6 +1221,7 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum)
 
 	/* fetch into volatile var while ProcArrayLock is held */
 	replication_slot_xmin = procArray->replication_slot_xmin;
+	replication_slot_catalog_xmin = procArray->replication_slot_catalog_xmin;
 
 	if (RecoveryInProgress())
 	{
@@ -1259,6 +1270,14 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum)
 		NormalTransactionIdPrecedes(replication_slot_xmin, result))
 		result = replication_slot_xmin;
 
+	/*
+	 * after locks are released and defer_cleanup_age has been applied, check
+	 * whether we need to back up further to make logical decoding possible.
+	 */
+	if (systable && TransactionIdIsValid(replication_slot_catalog_xmin) &&
+		NormalTransactionIdPrecedes(replication_slot_catalog_xmin, result))
+		result = replication_slot_catalog_xmin;
+
 	return result;
 }
 
@@ -1313,6 +1332,8 @@ GetMaxSnapshotSubxidCount(void)
  *		RecentGlobalXmin: the global xmin (oldest TransactionXmin across all
  *			running transactions, except those running LAZY VACUUM).  This is
  *			the same computation done by GetOldestXmin(true, true).
+ *		RecentGlobalDataXmin: the global xmin for non-catalog tables
+ *			>= RecentGlobalXmin
  *
  * Note: this function should probably not be called with an argument that's
  * not statically allocated (see xip allocation below).
@@ -1329,6 +1350,7 @@ GetSnapshotData(Snapshot snapshot)
 	int			subcount = 0;
 	bool		suboverflowed = false;
 	volatile TransactionId replication_slot_xmin = InvalidTransactionId;
+	volatile TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
 
 	Assert(snapshot != NULL);
 
@@ -1397,6 +1419,13 @@ GetSnapshotData(Snapshot snapshot)
 			volatile PGXACT *pgxact = &allPgXact[pgprocno];
 			TransactionId xid;
 
+			/*
+			 * Backend is doing logical decoding which manages xmin
+			 * separately, check below.
+			 */
+			if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING)
+				continue;
+
 			/* Ignore procs running LAZY VACUUM */
 			if (pgxact->vacuumFlags & PROC_IN_VACUUM)
 				continue;
@@ -1509,6 +1538,7 @@ GetSnapshotData(Snapshot snapshot)
 
 	/* fetch into volatile var while ProcArrayLock is held */
 	replication_slot_xmin = procArray->replication_slot_xmin;
+	replication_slot_catalog_xmin = procArray->replication_slot_catalog_xmin;
 
 	if (!TransactionIdIsValid(MyPgXact->xmin))
 		MyPgXact->xmin = TransactionXmin = xmin;
@@ -1533,6 +1563,17 @@ GetSnapshotData(Snapshot snapshot)
 		NormalTransactionIdPrecedes(replication_slot_xmin, RecentGlobalXmin))
 		RecentGlobalXmin = replication_slot_xmin;
 
+	/* Non-catalog tables can be vacuumed if older than this xid */
+	RecentGlobalDataXmin = RecentGlobalXmin;
+
+	/*
+	 * Check whether there's a replication slot requiring an older catalog
+	 * xmin.
+	 */
+	if (TransactionIdIsNormal(replication_slot_catalog_xmin) &&
+		NormalTransactionIdPrecedes(replication_slot_catalog_xmin, RecentGlobalXmin))
+		RecentGlobalXmin = replication_slot_catalog_xmin;
+
 	RecentXmin = xmin;
 
 	snapshot->xmin = xmin;
@@ -1633,9 +1674,11 @@ ProcArrayInstallImportedXmin(TransactionId xmin, TransactionId sourcexid)
  * Similar to GetSnapshotData but returns more information. We include
  * all PGXACTs with an assigned TransactionId, even VACUUM processes.
  *
- * We acquire XidGenLock, but the caller is responsible for releasing it.
- * This ensures that no new XIDs enter the proc array until the caller has
- * WAL-logged this snapshot, and releases the lock.
+ * We acquire XidGenLock and ProcArrayLock, but the caller is responsible for
+ * releasing them. Acquiring XidGenLock ensures that no new XIDs enter the proc
+ * array until the caller has WAL-logged this snapshot, and releases the
+ * lock. Acquiring ProcArrayLock ensures that no transactions commit until the
+ * lock is released.
  *
  * The returned data structure is statically allocated; caller should not
  * modify it, and must not assume it is valid past the next call.
@@ -1770,6 +1813,13 @@ GetRunningTransactionData(void)
 		}
 	}
 
+	/*
+	 * It's important *not* to track decoding tasks here because
+	 * snapbuild.c uses ->oldestRunningXid to manage its xmin. If it
+	 * were to be included here the initial value could never
+	 * increase.
+	 */
+
 	CurrentRunningXacts->xcnt = count - subcount;
 	CurrentRunningXacts->subxcnt = subcount;
 	CurrentRunningXacts->subxid_overflow = suboverflowed;
@@ -1777,13 +1827,12 @@ GetRunningTransactionData(void)
 	CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
 	CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
 
-	/* We don't release XidGenLock here, the caller is responsible for that */
-	LWLockRelease(ProcArrayLock);
-
 	Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
 	Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
 	Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
 
+	/* We don't release the locks here, the caller is responsible for that */
+
 	return CurrentRunningXacts;
 }
 
@@ -1853,6 +1902,92 @@ GetOldestActiveTransactionId(void)
 }
 
 /*
+ * GetOldestSafeDecodingTransactionId -- lowest xid not affected by vacuum
+ *
+ * Returns the oldest xid that we can guarantee not to have been affected by
+ * vacuum, i.e. no rows >= that xid have been vacuumed away unless the
+ * transaction aborted. Note that the value can (and most of the time will) be
+ * much more conservative than what really has been affected by vacuum, but we
+ * currently don't have better data available.
+ *
+ * This is useful to initalize the cutoff xid after which a new changeset
+ * extraction replication slot can start decoding changes.
+ *
+ * Must be called with ProcArrayLock held either shared or exclusively,
+ * although most callers will want to use exclusive mode since it is expected
+ * that the caller will immediately use the xid to peg the xmin horizon.
+ */
+TransactionId
+GetOldestSafeDecodingTransactionId(void)
+{
+	ProcArrayStruct *arrayP = procArray;
+	TransactionId oldestSafeXid;
+	int			index;
+	bool		recovery_in_progress = RecoveryInProgress();
+
+	Assert(LWLockHeldByMe(ProcArrayLock));
+
+	/*
+	 * Acquire XidGenLock, so no transactions can acquire an xid while we're
+	 * running. If no transaction with xid were running concurrently a new xid
+	 * could influence the the RecentXmin et al.
+	 *
+	 * We initialize the computation to nextXid since that's guaranteed to be
+	 * a safe, albeit pessimal, value.
+	 */
+	LWLockAcquire(XidGenLock, LW_SHARED);
+	oldestSafeXid = ShmemVariableCache->nextXid;
+
+	/*
+	 * If there's already a slot pegging the xmin horizon, we can start with
+	 * that value, it's guaranteed to be safe since it's computed by this
+	 * routine initally and has been enforced since.
+	 */
+	if (TransactionIdIsValid(procArray->replication_slot_catalog_xmin) &&
+		TransactionIdPrecedes(procArray->replication_slot_catalog_xmin,
+							  oldestSafeXid))
+		oldestSafeXid = procArray->replication_slot_catalog_xmin;
+
+	/*
+	 * If we're not in recovery, we walk over the procarray and collect the
+	 * lowest xid. Since we're called with ProcArrayLock held and have
+	 * acquired XidGenLock, no entries can vanish concurrently, since
+	 * PGXACT->xid is only set with XidGenLock held and only cleared with
+	 * ProcArrayLock held.
+	 *
+	 * In recovery we can't lower the safe value besides what we've computed
+	 * above, so we'll have to wait a bit longer there. We unfortunately can
+	 * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
+	 * machinery can miss values and return an older value than is safe.
+	 */
+	if (!recovery_in_progress)
+	{
+		/*
+		 * Spin over procArray collecting all min(PGXACT->xid)
+		 */
+		for (index = 0; index < arrayP->numProcs; index++)
+		{
+			int			pgprocno = arrayP->pgprocnos[index];
+			volatile PGXACT *pgxact = &allPgXact[pgprocno];
+			TransactionId xid;
+
+			/* Fetch xid just once - see GetNewTransactionId */
+			xid = pgxact->xid;
+
+			if (!TransactionIdIsNormal(xid))
+				continue;
+
+			if (TransactionIdPrecedes(xid, oldestSafeXid))
+				oldestSafeXid = xid;
+		}
+	}
+
+	LWLockRelease(XidGenLock);
+
+	return oldestSafeXid;
+}
+
+/*
  * GetVirtualXIDsDelayingChkpt -- Get the VXIDs of transactions that are
  * delaying checkpoint because they have critical actions in progress.
  *
@@ -2526,10 +2661,32 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
  * replicaton slots.
  */
 void
-ProcArraySetReplicationSlotXmin(TransactionId xmin)
+ProcArraySetReplicationSlotXmin(TransactionId xmin, TransactionId catalog_xmin,
+								bool already_locked)
 {
-	LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+	if (!already_locked)
+		LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+
 	procArray->replication_slot_xmin = xmin;
+	procArray->replication_slot_catalog_xmin = catalog_xmin;
+
+	if (!already_locked)
+		LWLockRelease(ProcArrayLock);
+}
+
+
+void
+ProcArrayGetReplicationSlotXmin(TransactionId *xmin,
+								TransactionId *catalog_xmin)
+{
+	LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+
+	if (xmin != NULL)
+		*xmin = procArray->replication_slot_xmin;
+
+	if (catalog_xmin != NULL)
+		*catalog_xmin = procArray->replication_slot_catalog_xmin;
+
 	LWLockRelease(ProcArrayLock);
 }
 
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index fb5f18e..e23c200 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -879,8 +879,23 @@ LogStandbySnapshot(void)
 	 * record we write, because standby will open up when it sees this.
 	 */
 	running = GetRunningTransactionData();
+
+	/*
+	 * GetRunningTransactionData() acquired ProcArrayLock, we must release
+	 * it. We can do that before inserting the WAL record because
+	 * ProcArrayApplyRecoveryInfo can recheck the commit status using the
+	 * clog. If we're doing logical replication we can't do that though, so
+	 * hold the lock for a moment longer.
+	 */
+	if (wal_level < WAL_LEVEL_LOGICAL)
+		LWLockRelease(ProcArrayLock);
+
 	recptr = LogCurrentRunningXacts(running);
 
+	/* Release lock if we kept it longer ... */
+	if (wal_level >= WAL_LEVEL_LOGICAL)
+		LWLockRelease(ProcArrayLock);
+
 	/* GetRunningTransactionData() acquired XidGenLock, we must release it */
 	LWLockRelease(XidGenLock);
 
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 4423fe0..115bcac 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -512,7 +512,7 @@ RegisterSnapshotInvalidation(Oid dbId, Oid relId)
  * Only the local caches are flushed; this does not transmit the message
  * to other backends.
  */
-static void
+void
 LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
 {
 	if (msg->id >= 0)
@@ -596,7 +596,7 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
  *		since that tells us we've lost some shared-inval messages and hence
  *		don't know what needs to be invalidated.
  */
-static void
+void
 InvalidateSystemCaches(void)
 {
 	int			i;
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 2810b35..a105a23 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -73,6 +73,7 @@
 #include "utils/memutils.h"
 #include "utils/relmapper.h"
 #include "utils/resowner_private.h"
+#include "utils/snapmgr.h"
 #include "utils/syscache.h"
 #include "utils/tqual.h"
 
@@ -235,7 +236,7 @@ static void formrdesc(const char *relationName, Oid relationReltype,
 		  bool isshared, bool hasoids,
 		  int natts, const FormData_pg_attribute *attrs);
 
-static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK);
+static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK, bool suspend_snap);
 static Relation AllocateRelationDesc(Form_pg_class relp);
 static void RelationParseRelOptions(Relation relation, HeapTuple tuple);
 static void RelationBuildTupleDesc(Relation relation);
@@ -274,7 +275,7 @@ static void unlink_initfile(const char *initfilename);
  *		and must eventually be freed with heap_freetuple.
  */
 static HeapTuple
-ScanPgRelation(Oid targetRelId, bool indexOK)
+ScanPgRelation(Oid targetRelId, bool indexOK, bool suspend_snap)
 {
 	HeapTuple	pg_class_tuple;
 	Relation	pg_class_desc;
@@ -305,6 +306,10 @@ ScanPgRelation(Oid targetRelId, bool indexOK)
 	 * scan by setting indexOK == false.
 	 */
 	pg_class_desc = heap_open(RelationRelationId, AccessShareLock);
+
+	if (suspend_snap)
+		SuspendDecodingSnapshots();
+
 	pg_class_scan = systable_beginscan(pg_class_desc, ClassOidIndexId,
 									   indexOK && criticalRelcachesBuilt,
 									   NULL,
@@ -312,6 +317,9 @@ ScanPgRelation(Oid targetRelId, bool indexOK)
 
 	pg_class_tuple = systable_getnext(pg_class_scan);
 
+	if (suspend_snap)
+		UnSuspendDecodingSnapshots();
+
 	/*
 	 * Must copy tuple before releasing buffer.
 	 */
@@ -836,7 +844,7 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
 	/*
 	 * find the tuple in pg_class corresponding to the given relation id
 	 */
-	pg_class_tuple = ScanPgRelation(targetRelId, true);
+	pg_class_tuple = ScanPgRelation(targetRelId, true, false);
 
 	/*
 	 * if no such tuple exists, return NULL
@@ -990,7 +998,39 @@ RelationInitPhysicalAddr(Relation relation)
 	else
 		relation->rd_node.dbNode = MyDatabaseId;
 	if (relation->rd_rel->relfilenode)
+	{
+		/*
+		 * Even if we are using a decoding snapshot that doesn't represent
+		 * the current state of the catalog we need to make sure the
+		 * filenode points to the current file since the older file will
+		 * be gone (or truncated). The new file will still contain older
+		 * rows so lookups in them will work correctly. This wouldn't work
+		 * correctly if rewrites were allowed to change the schema in a
+		 * noncompatible way, but those are prevented both on catalog
+		 * tables and on user tables declared as additional catalog
+		 * tables.
+		 */
+		if (DecodingSnapshotsActive()
+			&& RelationIsAccessibleInLogicalDecoding(relation))
+		{
+			HeapTuple		phys_tuple;
+			Form_pg_class	physrel;
+
+			phys_tuple = ScanPgRelation(RelationGetRelid(relation),
+										RelationGetRelid(relation) != ClassOidIndexId,
+										true);
+			if (!HeapTupleIsValid(phys_tuple))
+				elog(ERROR, "could not find pg_class entry for %u",
+					 RelationGetRelid(relation));
+			physrel = (Form_pg_class) GETSTRUCT(phys_tuple);
+
+			relation->rd_rel->reltablespace = physrel->reltablespace;
+			relation->rd_rel->relfilenode = physrel->relfilenode;
+			heap_freetuple(phys_tuple);
+		}
+
 		relation->rd_node.relNode = relation->rd_rel->relfilenode;
+	}
 	else
 	{
 		/* Consult the relation mapper */
@@ -1613,6 +1653,10 @@ RelationIdGetRelation(Oid relationId)
 	rd = RelationBuildDesc(relationId, true);
 	if (RelationIsValid(rd))
 		RelationIncrementReferenceCount(rd);
+
+	/* Make sure we're in a xact, even if this ends up being a cache hit */
+	Assert(rd->rd_isnailed || IsTransactionOrTransactionBlock());
+
 	return rd;
 }
 
@@ -1742,7 +1786,7 @@ RelationReloadIndexInfo(Relation relation)
 	 * for pg_class_oid_index ...
 	 */
 	indexOK = (RelationGetRelid(relation) != ClassOidIndexId);
-	pg_class_tuple = ScanPgRelation(RelationGetRelid(relation), indexOK);
+	pg_class_tuple = ScanPgRelation(RelationGetRelid(relation), indexOK, false);
 	if (!HeapTupleIsValid(pg_class_tuple))
 		elog(ERROR, "could not find pg_class tuple for index %u",
 			 RelationGetRelid(relation));
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 4c0e0ac..9917201 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -69,7 +69,7 @@
  */
 static SnapshotData CurrentSnapshotData = {HeapTupleSatisfiesMVCC};
 static SnapshotData SecondarySnapshotData = {HeapTupleSatisfiesMVCC};
-static SnapshotData CatalogSnapshotData = {HeapTupleSatisfiesMVCC};
+SnapshotData CatalogSnapshotData = {HeapTupleSatisfiesMVCC};
 
 /* Pointers to valid snapshots */
 static Snapshot CurrentSnapshot = NULL;
@@ -86,13 +86,15 @@ static bool CatalogSnapshotStale = true;
  * for the convenience of TransactionIdIsInProgress: even in bootstrap
  * mode, we don't want it to say that BootstrapTransactionId is in progress.
  *
- * RecentGlobalXmin is initialized to InvalidTransactionId, to ensure that no
- * one tries to use a stale value.	Readers should ensure that it has been set
- * to something else before using it.
+ * RecentGlobalXmin and RecentGlobalDataXmin are initialized to
+ * InvalidTransactionId, to ensure that no one tries to use a stale
+ * value. Readers should ensure that it has been set to something else
+ * before using it.
  */
 TransactionId TransactionXmin = FirstNormalTransactionId;
 TransactionId RecentXmin = FirstNormalTransactionId;
 TransactionId RecentGlobalXmin = InvalidTransactionId;
+TransactionId RecentGlobalDataXmin = InvalidTransactionId;
 
 /*
  * Elements of the active snapshot stack.
@@ -796,7 +798,7 @@ AtEOXact_Snapshot(bool isCommit)
  *		Returns the token (the file name) that can be used to import this
  *		snapshot.
  */
-static char *
+char *
 ExportSnapshot(Snapshot snapshot)
 {
 	TransactionId topXid;
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index f626755..7d0a825 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -62,6 +62,8 @@
 #include "access/xact.h"
 #include "storage/bufmgr.h"
 #include "storage/procarray.h"
+#include "utils/builtins.h"
+#include "utils/combocid.h"
 #include "utils/tqual.h"
 
 
@@ -70,9 +72,17 @@ SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf};
 SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny};
 SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast};
 
+static Snapshot TimetravelSnapshot;
+/* (table, ctid) => (cmin, cmax) mapping during timetravel */
+static HTAB *tuplecid_data = NULL;
+static int timetravel_suspended = 0;
+
+
 /* local functions */
 static bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
-
+static bool FailsSatisfies(HeapTuple htup, Snapshot snapshot, Buffer buffer);
+static bool RedirectSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
+								 Buffer buffer);
 
 /*
  * SetHintBits()
@@ -1545,3 +1555,266 @@ HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
 	 */
 	return true;
 }
+
+/*
+ * check whether the transaciont id 'xid' in in the pre-sorted array 'xip'.
+ */
+static bool
+TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
+{
+	return bsearch(&xid, xip, num,
+				   sizeof(TransactionId), xidComparator) != NULL;
+}
+
+/*
+ * See the comments for HeapTupleSatisfiesMVCC for the semantics this function
+ * obeys.
+ *
+ * Only usable on tuples from catalog tables!
+ *
+ * We don't need to support HEAP_MOVED_(IN|OFF) for now because we only support
+ * reading catalog pages which couldn't have been created in an older version.
+ *
+ * We don't set any hint bits in here as it seems unlikely to be beneficial as
+ * those should already be set by normal access and it seems to be too
+ * dangerous to do so as the semantics of doing so during timetravel are more
+ * complicated than when dealing "only" with the present.
+ */
+bool
+HeapTupleSatisfiesMVCCDuringDecoding(HeapTuple htup, Snapshot snapshot,
+									 Buffer buffer)
+{
+	HeapTupleHeader tuple = htup->t_data;
+	TransactionId xmin = HeapTupleHeaderGetXmin(tuple);
+	TransactionId xmax = HeapTupleHeaderGetRawXmax(tuple);
+
+	Assert(ItemPointerIsValid(&htup->t_self));
+	Assert(htup->t_tableOid != InvalidOid);
+
+	/* inserting transaction aborted */
+	if (HeapTupleHeaderXminInvalid(tuple))
+	{
+		Assert(!TransactionIdDidCommit(xmin));
+		return false;
+	}
+	/* check if its one of our txids, toplevel is also in there */
+	else if (TransactionIdInArray(xmin, snapshot->subxip, snapshot->subxcnt))
+	{
+		bool		resolved;
+		CommandId	cmin = HeapTupleHeaderGetRawCommandId(tuple);
+		CommandId	cmax = InvalidCommandId;
+
+		/*
+		 * another transaction might have (tried to) delete this tuple or
+		 * cmin/cmax was stored in a combocid. S we need to to lookup the
+		 * actual values externally.
+		 */
+		resolved = ResolveCminCmaxDuringDecoding(tuplecid_data, snapshot,
+												 htup, buffer,
+												 &cmin, &cmax);
+
+		if (!resolved)
+			elog(ERROR, "could not resolve cmin/cmax of catalog tuple");
+
+		Assert(cmin != InvalidCommandId);
+
+		if (cmin >= snapshot->curcid)
+			return false;	/* inserted after scan started */
+		/* fall through */
+	}
+	/* committed before our xmin horizon. Do a normal visibility check. */
+	else if (TransactionIdPrecedes(xmin, snapshot->xmin))
+	{
+		Assert(!(HeapTupleHeaderXminCommitted(tuple) &&
+				 !TransactionIdDidCommit(xmin)));
+
+		/* check for hint bit first, consult clog afterwards */
+		if (!HeapTupleHeaderXminCommitted(tuple) &&
+			!TransactionIdDidCommit(xmin))
+			return false;
+		/* fall through */
+	}
+	/* beyond our xmax horizon, i.e. invisible */
+	else if (TransactionIdFollowsOrEquals(xmin, snapshot->xmax))
+	{
+		return false;
+	}
+	/* check if it's a committed transaction in [xmin, xmax) */
+	else if(TransactionIdInArray(xmin, snapshot->xip, snapshot->xcnt))
+	{
+		/* fall through */
+	}
+	/*
+	 * none of the above, i.e. between [xmin, xmax) but hasn't
+	 * committed. I.e. invisible.
+	 */
+	else
+	{
+		return false;
+	}
+
+	/* at this point we know xmin is visible, go on to check xmax */
+
+	/* xid invalid or aborted */
+	if (tuple->t_infomask & HEAP_XMAX_INVALID)
+		return true;
+	/* locked tuples are always visible */
+	else if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
+		return true;
+	/*
+	 * We can see multis here if we're looking at user tables or if
+	 * somebody SELECT ... FOR SHARE/UPDATE a system table.
+	 */
+	else if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
+	{
+		xmax = HeapTupleGetUpdateXid(tuple);
+	}
+
+	/* check if its one of our txids, toplevel is also in there */
+	if (TransactionIdInArray(xmax, snapshot->subxip, snapshot->subxcnt))
+	{
+		bool resolved;
+		CommandId cmin;
+		CommandId cmax = HeapTupleHeaderGetRawCommandId(tuple);
+
+		/* Lookup actual cmin/cmax values */
+		resolved = ResolveCminCmaxDuringDecoding(tuplecid_data, snapshot,
+												 htup, buffer,
+												 &cmin, &cmax);
+
+		if (!resolved)
+			elog(ERROR, "could not resolve combocid to cmax");
+
+		Assert(cmax != InvalidCommandId);
+
+		if (cmax >= snapshot->curcid)
+			return true;	/* deleted after scan started */
+		else
+			return false;	/* deleted before scan started */
+	}
+	/* below xmin horizon, normal transaction state is valid */
+	else if (TransactionIdPrecedes(xmax, snapshot->xmin))
+	{
+		Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED &&
+				 !TransactionIdDidCommit(xmax)));
+
+		/* check hint bit first */
+		if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
+			return false;
+
+		/* check clog */
+		return !TransactionIdDidCommit(xmax);
+	}
+	/* above xmax horizon, we cannot possibly see the deleting transaction */
+	else if (TransactionIdFollowsOrEquals(xmax, snapshot->xmax))
+		return true;
+	/* xmax is between [xmin, xmax), check known committed array */
+	else if (TransactionIdInArray(xmax, snapshot->xip, snapshot->xcnt))
+		return false;
+	/* xmax is between [xmin, xmax), but known not to have committed yet */
+	else
+		return true;
+}
+
+/*
+ * Setup a snapshot that replaces normal catalog snapshots that allows catalog
+ * access to behave just like it did at a certain point in the past.
+ *
+ * Needed for after-the-fact WAL decoding.
+ */
+void
+SetupDecodingSnapshots(Snapshot timetravel_snapshot, HTAB *tuplecids)
+{
+	/* prevent recursively setting up decoding snapshots */
+	Assert(CatalogSnapshotData.satisfies != RedirectSatisfiesMVCC);
+
+	CatalogSnapshotData.satisfies = RedirectSatisfiesMVCC;
+	/* make sure normal snapshots aren't used*/
+	SnapshotSelfData.satisfies = FailsSatisfies;
+	SnapshotAnyData.satisfies = FailsSatisfies;
+	SnapshotToastData.satisfies = FailsSatisfies;
+	/* don't overwrite SnapshotToastData, we want that to behave normally */
+
+	/* setup the timetravel snapshot */
+	TimetravelSnapshot = timetravel_snapshot;
+
+	/* setup (cmin, cmax) lookup hash */
+	tuplecid_data = tuplecids;
+
+	timetravel_suspended = 0;
+}
+
+
+/*
+ * Make catalog snapshots behave normally again.
+ */
+void
+RevertFromDecodingSnapshots(bool is_error)
+{
+	Assert(timetravel_suspended == 0 || is_error);
+
+	TimetravelSnapshot = NULL;
+	tuplecid_data = NULL;
+
+	/* rally to restore sanity and/or boredom */
+	CatalogSnapshotData.satisfies = HeapTupleSatisfiesMVCC;
+	SnapshotSelfData.satisfies = HeapTupleSatisfiesSelf;
+	SnapshotAnyData.satisfies = HeapTupleSatisfiesAny;
+	SnapshotToastData.satisfies = HeapTupleSatisfiesToast;
+	timetravel_suspended = 0;
+}
+
+/*
+ * Disable catalog snapshot timetravel and perform old-fashioned access but
+ * make re-enabling cheap.. This is useful for accessing catalog entries which
+ * must stay up2date like the pg_class entries of system relations.
+ *
+ * Can be called several times in a nested fashion since several of it's
+ * callers suspend timetravel access on several code levels.
+ */
+void
+SuspendDecodingSnapshots(void)
+{
+	timetravel_suspended++;
+}
+
+/*
+ * Enable timetravel again, After SuspendDecodingSnapshots it.
+ */
+void
+UnSuspendDecodingSnapshots(void)
+{
+	Assert(timetravel_suspended > 0);
+	timetravel_suspended--;
+}
+
+bool
+DecodingSnapshotsActive(void)
+{
+	return TimetravelSnapshot != NULL;
+}
+
+/*
+ * Error out if a normal snapshot is used. That is neither legal nor expected
+ * during timetravel, so this is just extra assurance.
+ */
+static bool
+FailsSatisfies(HeapTuple htup, Snapshot snapshot, Buffer buffer)
+{
+	elog(ERROR, "Normal snapshots cannot be used during timetravel access.");
+	return false;
+}
+
+
+/*
+ * Call the replacement SatisifiesMVCC with the required Snapshot data.
+ */
+static bool
+RedirectSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
+{
+	Assert(TimetravelSnapshot != NULL);
+	if (timetravel_suspended > 0)
+		return HeapTupleSatisfiesMVCC(htup, snapshot, buffer);
+	return HeapTupleSatisfiesMVCCDuringDecoding(htup, TimetravelSnapshot,
+												buffer);
+}
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index a71320d..2beea6d 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -198,7 +198,10 @@ const char *subdirs[] = {
 	"pg_replslot",
 	"pg_tblspc",
 	"pg_stat",
-	"pg_stat_tmp"
+	"pg_stat_tmp",
+	"pg_llog",
+	"pg_llog/snapshots",
+	"pg_llog/mappings"
 };
 
 
diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h
index d4383ab..1946359 100644
--- a/src/include/access/heapam_xlog.h
+++ b/src/include/access/heapam_xlog.h
@@ -48,7 +48,7 @@
  * the ones above associated with RM_HEAP_ID.  XLOG_HEAP_OPMASK applies to
  * these, too.
  */
-/* 0x00 is free, was XLOG_HEAP2_FREEZE */
+#define XLOG_HEAP2_REWRITE		0x00
 #define XLOG_HEAP2_CLEAN		0x10
 #define XLOG_HEAP2_FREEZE_PAGE	0x20
 #define XLOG_HEAP2_CLEANUP_INFO 0x30
@@ -332,6 +332,17 @@ typedef struct xl_heap_new_cid
 	xl_heaptid target;
 } xl_heap_new_cid;
 
+/* logical rewrite xlog record header */
+typedef struct xl_heap_rewrite_mapping
+{
+	TransactionId		mapped_xid;	/* xid that might need to see the row */
+	Oid					mapped_db;	/* DbOid or InvalidOid for shared rels */
+	Oid					mapped_rel;	/* Oid of the mapped relation */
+	off_t				offset;		/* How far have we written so far */
+	uint32				num_mappings; /* Number of in-memory mappings */
+	XLogRecPtr			start_lsn;	/* Insert LSN at begin of rewrite */
+} xl_heap_rewrite_mapping;
+
 #define SizeOfHeapNewCid (offsetof(xl_heap_new_cid, target) + SizeOfHeapTid)
 
 extern void HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
@@ -341,6 +352,7 @@ extern void heap_redo(XLogRecPtr lsn, XLogRecord *rptr);
 extern void heap_desc(StringInfo buf, uint8 xl_info, char *rec);
 extern void heap2_redo(XLogRecPtr lsn, XLogRecord *rptr);
 extern void heap2_desc(StringInfo buf, uint8 xl_info, char *rec);
+extern void heap_xlog_logical_rewrite(XLogRecPtr lsn, XLogRecord *r);
 
 extern XLogRecPtr log_heap_cleanup_info(RelFileNode rnode,
 					  TransactionId latestRemovedXid);
diff --git a/src/include/access/rewriteheap.h b/src/include/access/rewriteheap.h
index d098a0b..e03dec9 100644
--- a/src/include/access/rewriteheap.h
+++ b/src/include/access/rewriteheap.h
@@ -14,12 +14,14 @@
 #define REWRITE_HEAP_H
 
 #include "access/htup.h"
+#include "storage/itemptr.h"
+#include "storage/relfilenode.h"
 #include "utils/relcache.h"
 
 /* struct definition is private to rewriteheap.c */
 typedef struct RewriteStateData *RewriteState;
 
-extern RewriteState begin_heap_rewrite(Relation NewHeap,
+extern RewriteState begin_heap_rewrite(Relation OldHeap, Relation NewHeap,
 				   TransactionId OldestXmin, TransactionId FreezeXid,
 				   MultiXactId MultiXactCutoff, bool use_wal);
 extern void end_heap_rewrite(RewriteState state);
@@ -27,4 +29,30 @@ extern void rewrite_heap_tuple(RewriteState state, HeapTuple oldTuple,
 				   HeapTuple newTuple);
 extern bool rewrite_heap_dead_tuple(RewriteState state, HeapTuple oldTuple);
 
+/*
+ * On-Disk data format for an individual logical rewrite mapping.
+ */
+typedef struct LogicalRewriteMappingData
+{
+	RelFileNode		old_node;
+	RelFileNode		new_node;
+	ItemPointerData	old_tid;
+	ItemPointerData	new_tid;
+} LogicalRewriteMappingData;
+
+/* ---
+ * The filename consists out of the following, dash separated,
+ * components:
+ * 1) database oid or InvalidOid for shared relations
+ * 2) the oid of the relation
+ * 3) xid we are mapping for
+ * 4) LSN at which a rewrite started
+ * 5) xid of the xact performing the mapping
+ *
+ * XXX: use hex format for the LSN as well?
+ * ---
+ */
+#define LOGICAL_REWRITE_FORMAT "map-%x-%x-"UINT64_FORMAT"-%x-%x"
+void CheckpointLogicalRewriteHeap(void);
+
 #endif   /* REWRITE_HEAP_H */
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
index 8376dfd..a9774e9 100644
--- a/src/include/access/transam.h
+++ b/src/include/access/transam.h
@@ -63,6 +63,11 @@
 	(AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \
 	(int32) ((id1) - (id2)) < 0)
 
+/* compare two XIDs already known to be normal; this is a macro for speed */
+#define NormalTransactionIdFollows(id1, id2) \
+	(AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \
+	(int32) ((id1) - (id2)) > 0)
+
 /* ----------
  *		Object ID (OID) zero is InvalidOid.
  *
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index e6713a6..a190d72 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -4787,8 +4787,18 @@ DATA(insert OID = 3779 (  pg_create_physical_replication_slot PGNSP PGUID 12 1 0
 DESCR("create a physical replication slot");
 DATA(insert OID = 3780 (  pg_drop_replication_slot PGNSP PGUID 12 1 0 0 0 f f f f f f v 1 0 2278 "19" _null_ _null_ _null_ _null_ pg_drop_replication_slot _null_ _null_ _null_ ));
 DESCR("drop a replication slot");
-DATA(insert OID = 3781 (  pg_get_replication_slots	PGNSP PGUID 12 1 10 0 0 f f f f f t s 0 0 2249 "" "{25,25,26,16,28,25}" "{o,o,o,o,o,o}" "{slot_name,slot_type,datoid,active,xmin,restart_lsn}" _null_ pg_get_replication_slots _null_ _null_ _null_ ));
+DATA(insert OID = 3781 (  pg_get_replication_slots	PGNSP PGUID 12 1 10 0 0 f f f f f t s 0 0 2249 "" "{25,25,25,26,16,28,28,25}" "{o,o,o,o,o,o,o,o}" "{slot_name,plugin,slot_type,datoid,active,xmin,catalog_xmin,restart_lsn}" _null_ pg_get_replication_slots _null_ _null_ _null_ ));
 DESCR("information about replication slots currently in use");
+DATA(insert OID = 3786 (  pg_create_decoding_replication_slot PGNSP PGUID 12 1 0 0 0 f f f f f f v 2 0 2249 "19 19" "{19,19,25,25}" "{i,i,o,o}" "{slotname,plugin,slotname,xlog_position}" _null_ pg_create_decoding_replication_slot _null_ _null_ _null_ ));
+DESCR("set up a logical replication slot");
+DATA(insert OID = 3782 (  pg_decoding_slot_get_changes PGNSP PGUID 12 1000 1000 25 0 f f f f t t v 3 0 2249 "19 25 1009" "{19,25,1009,25,28,25}" "{i,i,v,o,o,o}" "{slotname,pos,options,location,xid,data}" _null_ pg_decoding_slot_get_changes _null_ _null_ _null_ ));
+DESCR("get changes from replication slot");
+DATA(insert OID = 3783 (  pg_decoding_slot_get_binary_changes PGNSP PGUID 12 1000 1000 25 0 f f f f t t v 3 0 2249 "19 25 1009" "{19,25,1009,25,28,17}" "{i,i,v,o,o,o}" "{slotname,pos,options,location,xid,data}" _null_ pg_decoding_slot_get_binary_changes _null_ _null_ _null_ ));
+DESCR("get binary changes from replication slot");
+DATA(insert OID = 3784 (  pg_decoding_slot_peek_changes PGNSP PGUID 12 1000 1000 25 0 f f f f t t v 3 0 2249 "19 25 1009" "{19,25,1009,25,28,25}" "{i,i,v,o,o,o}" "{slotname,pos,options,location,xid,data}" _null_ pg_decoding_slot_peek_changes _null_ _null_ _null_ ));
+DESCR("peek at changes from replication slot");
+DATA(insert OID = 3785 (  pg_decoding_slot_peek_binary_changes PGNSP PGUID 12 1000 1000 25 0 f f f f t t v 3 0 2249 "19 25 1009" "{19,25,1009,25,28,17}" "{i,i,v,o,o,o}" "{slotname,pos,options,location,xid,data}" _null_ pg_decoding_slot_peek_binary_changes _null_ _null_ _null_ ));
+DESCR("peek at binary changes from replication slot");
 
 /* event triggers */
 DATA(insert OID = 3566 (  pg_event_trigger_dropped_objects		PGNSP PGUID 12 10 100 0 0 f f f f t t s 0 0 2249 "" "{26,26,23,25,25,25,25}" "{o,o,o,o,o,o,o}" "{classid, objid, objsubid, object_type, schema_name, object_name, object_identity}" _null_ pg_event_trigger_dropped_objects _null_ _null_ _null_ ));
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 7c36890..f1b8093 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -156,7 +156,7 @@ extern void vac_update_relstats(Relation relation,
 					TransactionId frozenxid,
 					MultiXactId minmulti);
 extern void vacuum_set_xid_limits(int freeze_min_age, int freeze_table_age,
-					  bool sharedRel,
+					  bool sharedRel, bool catalogRel,
 					  TransactionId *oldestXmin,
 					  TransactionId *freezeLimit,
 					  TransactionId *xidFullScanLimit,
diff --git a/src/include/replication/decode.h b/src/include/replication/decode.h
new file mode 100644
index 0000000..7f55d78
--- /dev/null
+++ b/src/include/replication/decode.h
@@ -0,0 +1,19 @@
+/*-------------------------------------------------------------------------
+ * decode.h
+ *	   PostgreSQL WAL to logical transformation
+ *
+ * Portions Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DECODE_H
+#define DECODE_H
+
+#include "access/xlogreader.h"
+#include "replication/reorderbuffer.h"
+#include "replication/logical.h"
+
+void LogicalDecodingProcessRecord(LogicalDecodingContext *ctx,
+								  XLogRecord *record);
+
+#endif
diff --git a/src/include/replication/logical.h b/src/include/replication/logical.h
new file mode 100644
index 0000000..506a576
--- /dev/null
+++ b/src/include/replication/logical.h
@@ -0,0 +1,107 @@
+/*-------------------------------------------------------------------------
+ * logical.h
+ *	   PostgreSQL changeset extraction coordination
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOGICAL_H
+#define LOGICAL_H
+
+#include "replication/slot.h"
+
+#include "access/xlog.h"
+#include "access/xlogreader.h"
+#include "replication/output_plugin.h"
+#include "storage/shmem.h"
+#include "storage/spin.h"
+
+
+struct LogicalDecodingContext;
+
+
+
+typedef void (*LogicalOutputPluginWriterWrite) (
+										   struct LogicalDecodingContext *lr,
+															XLogRecPtr Ptr,
+															TransactionId xid,
+															bool last_write
+);
+
+typedef LogicalOutputPluginWriterWrite LogicalOutputPluginWriterPrepareWrite;
+
+typedef struct LogicalDecodingContext
+{
+	/* memory context this is all allocated in */
+	MemoryContext context;
+
+	/* infrastructure pieces */
+	struct XLogReaderState *reader;
+	struct ReplicationSlot *slot;
+	struct ReorderBuffer *reorder;
+	struct SnapBuild *snapshot_builder;
+
+	struct OutputPluginCallbacks callbacks;
+
+	/*
+	 * User specified options
+	 */
+	List	   *output_plugin_options;
+
+	/*
+	 * User-Provided callback for writing/streaming out data.
+	 */
+	LogicalOutputPluginWriterPrepareWrite prepare_write;
+	LogicalOutputPluginWriterWrite write;
+
+	/*
+	 * Output buffer.
+	 */
+	StringInfo	out;
+
+	/*
+	 * Private data pointer of the output plugin.
+	 */
+	void	   *output_plugin_private;
+
+	/*
+	 * Private data pointer for the data writer.
+	 */
+	void	   *output_writer_private;
+
+	/*
+	 * State for writing output.
+	 */
+	bool accept_writes;
+	bool prepared_write;
+	XLogRecPtr write_location;
+	TransactionId write_xid;
+} LogicalDecodingContext;
+
+extern bool LogicalDecodingCountDBSlots(Oid dboid, int *nslots, int *nactive);
+
+extern XLogRecPtr ComputeLogicalRestartLSN(void);
+
+/* change logical xmin */
+extern void IncreaseLogicalXminForSlot(XLogRecPtr lsn, TransactionId xmin);
+
+/* change recovery restart location */
+extern void IncreaseRestartDecodingForSlot(XLogRecPtr current_lsn, XLogRecPtr restart_lsn);
+
+extern void LogicalConfirmReceivedLocation(XLogRecPtr lsn);
+
+extern void CheckLogicalDecodingRequirements(void);
+
+extern LogicalDecodingContext *CreateDecodingContext(
+							 bool is_init, char *plugin,
+							 XLogRecPtr	start_lsn,
+							 List *output_plugin_options,
+							 XLogPageReadCB read_page,
+						 LogicalOutputPluginWriterPrepareWrite prepare_write,
+							 LogicalOutputPluginWriterWrite do_write);
+extern void DecodingContextFindStartpoint(LogicalDecodingContext *ctx);
+extern bool DecodingContextReady(LogicalDecodingContext *ctx);
+extern void FreeDecodingContext(LogicalDecodingContext *ctx);
+
+#endif
diff --git a/src/include/replication/logicalfuncs.h b/src/include/replication/logicalfuncs.h
new file mode 100644
index 0000000..75f11df
--- /dev/null
+++ b/src/include/replication/logicalfuncs.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ * logicalfuncs.h
+ *	   PostgreSQL WAL to logical transformation support functions
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOGICALFUNCS_H
+#define LOGICALFUNCS_H
+
+#include "replication/logical.h"
+
+extern int logical_read_local_xlog_page(XLogReaderState *state,
+							 XLogRecPtr targetPagePtr,
+							 int reqLen, XLogRecPtr targetRecPtr,
+							 char *cur_page, TimeLineID *pageTLI);
+
+extern Datum pg_create_decoding_replication_slot(PG_FUNCTION_ARGS);
+extern Datum pg_decoding_slot_get_changes(PG_FUNCTION_ARGS);
+extern Datum pg_decoding_slot_get_binary_changes(PG_FUNCTION_ARGS);
+extern Datum pg_decoding_slot_peek_changes(PG_FUNCTION_ARGS);
+extern Datum pg_decoding_slot_peek_binary_changes(PG_FUNCTION_ARGS);
+
+#endif
diff --git a/src/include/replication/output_plugin.h b/src/include/replication/output_plugin.h
new file mode 100644
index 0000000..f10e99d
--- /dev/null
+++ b/src/include/replication/output_plugin.h
@@ -0,0 +1,83 @@
+/*-------------------------------------------------------------------------
+ * output_plugin.h
+ *	   PostgreSQL Logical Decode Plugin Interface
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef OUTPUT_PLUGIN_H
+#define OUTPUT_PLUGIN_H
+
+#include "replication/reorderbuffer.h"
+
+struct LogicalDecodingContext;
+struct OutputPluginCallbacks;
+
+/*
+ * Type of the shared library symbol _PG_output_plugin_init that is looked up
+ * when loading an output plugin shared library.
+ */
+typedef void (*LogicalOutputPluginInit)(struct OutputPluginCallbacks *cb);
+
+/*
+ * Callback that gets called in a user-defined plugin. ctx->private_data can
+ * be set to some private data.
+ *
+ * "is_init" will be set to "true" if the decoding slot just got defined. When
+ * the same slot is used from there one, it will be "false".
+ */
+typedef void (*LogicalDecodeStartupCB) (
+										  struct LogicalDecodingContext *ctx,
+												 bool is_init
+);
+
+/*
+ * Callback called for every (explicit or implicit) BEGIN of a successful
+ * transaction.
+ */
+typedef void (*LogicalDecodeBeginCB) (
+											 struct LogicalDecodingContext *,
+												  ReorderBufferTXN *txn);
+
+/*
+ * Callback for every individual change in a successful transaction.
+ */
+typedef void (*LogicalDecodeChangeCB) (
+											 struct LogicalDecodingContext *,
+												   ReorderBufferTXN *txn,
+												   Relation relation,
+												   ReorderBufferChange *change
+);
+
+/*
+ * Called for every (explicit or implicit) COMMIT of a successful transaction.
+ */
+typedef void (*LogicalDecodeCommitCB) (
+											 struct LogicalDecodingContext *,
+												   ReorderBufferTXN *txn,
+												   XLogRecPtr commit_lsn);
+
+/*
+ * Called to shutdown an output plugin.
+ */
+typedef void (*LogicalDecodeShutdownCB) (
+											  struct LogicalDecodingContext *
+);
+
+/*
+ * Output plugin callbacks
+ */
+typedef struct OutputPluginCallbacks
+{
+	LogicalDecodeStartupCB startup_cb;
+	LogicalDecodeBeginCB begin_cb;
+	LogicalDecodeChangeCB change_cb;
+	LogicalDecodeCommitCB commit_cb;
+	LogicalDecodeShutdownCB shutdown_cb;
+} OutputPluginCallbacks;
+
+void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write);
+void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write);
+
+#endif   /* OUTPUT_PLUGIN_H */
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
new file mode 100644
index 0000000..2e9c91e
--- /dev/null
+++ b/src/include/replication/reorderbuffer.h
@@ -0,0 +1,349 @@
+/*
+ * reorderbuffer.h
+ *    PostgreSQL logical replay/reorder buffer management.
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ * src/include/replication/reorderbuffer.h
+ */
+#ifndef REORDERBUFFER_H
+#define REORDERBUFFER_H
+
+#include "access/htup_details.h"
+
+#include "lib/ilist.h"
+
+#include "storage/sinval.h"
+
+#include "utils/hsearch.h"
+#include "utils/rel.h"
+#include "utils/snapshot.h"
+#include "utils/timestamp.h"
+
+/* an individual tuple, stored in one chunk of memory */
+typedef struct ReorderBufferTupleBuf
+{
+	/* position in preallocated list */
+	slist_node	node;
+
+	/* tuple, stored sequentially */
+	HeapTupleData tuple;
+	HeapTupleHeaderData header;
+	char		data[MaxHeapTupleSize];
+} ReorderBufferTupleBuf;
+
+/* types of the change passed to a 'change' callback */
+enum ReorderBufferChangeType
+{
+	REORDER_BUFFER_CHANGE_INSERT,
+	REORDER_BUFFER_CHANGE_UPDATE,
+	REORDER_BUFFER_CHANGE_DELETE
+};
+
+/*
+ * a single 'change', can be an insert (with one tuple), an update (old, new),
+ * or a delete (old).
+ *
+ * The same struct is also used internally for other purposes but that should
+ * never be visible outside reorderbuffer.c.
+ */
+typedef struct ReorderBufferChange
+{
+	XLogRecPtr	lsn;
+
+	/* type of change */
+	union
+	{
+		enum ReorderBufferChangeType action;
+		/* do not leak internal enum values to the outside */
+		int			action_internal;
+	};
+
+	/*
+	 * Context data for the change, which part of the union is valid depends
+	 * on action/action_internal.
+	 */
+	union
+	{
+		/* old, new tuples when action == *_INSERT|UPDATE|DELETE */
+		struct
+		{
+			/* relation that has been changed */
+			RelFileNode relnode;
+			/* valid for DELETE || UPDATE */
+			ReorderBufferTupleBuf *oldtuple;
+			/* valid for INSERT || UPDATE */
+			ReorderBufferTupleBuf *newtuple;
+		} tp;
+
+		/* new snapshot */
+		Snapshot	snapshot;
+
+		/* new command id for existing snapshot in a catalog changing tx */
+		CommandId	command_id;
+
+		/* new cid mapping for catalog changing transaction */
+		struct
+		{
+			RelFileNode node;
+			ItemPointerData tid;
+			CommandId	cmin;
+			CommandId	cmax;
+			CommandId	combocid;
+		}			tuplecid;
+	};
+
+	/*
+	 * While in use this is how a change is linked into a transactions,
+	 * otherwise it's the preallocated list.
+	 */
+	dlist_node	node;
+} ReorderBufferChange;
+
+typedef struct ReorderBufferTXN
+{
+	/*
+	 * The transactions transaction id, can be a toplevel or sub xid.
+	 */
+	TransactionId xid;
+
+	/* did the TX have catalog changes */
+	bool		has_catalog_changes;
+
+	/*
+	 * Do we know this is a subxact?
+	 */
+	bool		is_known_as_subxact;
+
+	/*
+	 * LSN of the first data carrying, WAL record with knowledge about this
+	 * xid. This is allowed to *not* be first record adorned with this xid, if
+	 * the previous records aren't relevant for logical decoding.
+	 */
+	XLogRecPtr	first_lsn;
+
+	/* ----
+	 * LSN of the record that lead to this xact to be committed or
+	 * aborted. This can be a
+	 * * plain commit record
+	 * * plain commit record, of a parent transaction
+	 * * prepared transaction commit
+	 * * plain abort record
+	 * * prepared transaction abort
+	 * * error during decoding
+	 * ----
+	 */
+	XLogRecPtr	final_lsn;
+
+	/*
+	 * LSN pointing to the end of the commit record + 1.
+	 */
+	XLogRecPtr	end_lsn;
+
+	/*
+	 * LSN of the last lsn at which snapshot information reside, so we can
+	 * restart decoding from there and fully recover this transaction from
+	 * WAL.
+	 */
+	XLogRecPtr	restart_decoding_lsn;
+
+	/*
+	 * Commit time, only known when we read the actual commit record.
+	 */
+	TimestampTz	commit_time;
+
+	/*
+	 * Base snapshot or NULL.
+	 */
+	Snapshot	base_snapshot;
+
+	/*
+	 * How many ReorderBufferChange's do we have in this txn.
+	 *
+	 * Changes in subtransactions are *not* included but tracked separately.
+	 */
+	uint64		nentries;
+
+	/*
+	 * How many of the above entries are stored in memory in contrast to being
+	 * spilled to disk.
+	 */
+	uint64		nentries_mem;
+
+	/*
+	 * List of ReorderBufferChange structs, including new Snapshots and new
+	 * CommandIds
+	 */
+	dlist_head	changes;
+
+	/*
+	 * List of (relation, ctid) => (cmin, cmax) mappings for catalog tuples.
+	 * Those are always assigned to the toplevel transaction. (Keep track of
+	 * #entries to create a hash of the right size)
+	 */
+	dlist_head	tuplecids;
+	uint64		ntuplecids;
+
+	/*
+	 * On-demand built hash for looking up the above values.
+	 */
+	HTAB	   *tuplecid_hash;
+
+	/*
+	 * Hash containing (potentially partial) toast entries. NULL if no toast
+	 * tuples have been found for the current change.
+	 */
+	HTAB	   *toast_hash;
+
+	/*
+	 * non-hierarchical list of subtransactions that are *not* aborted. Only
+	 * used in toplevel transactions.
+	 */
+	dlist_head	subtxns;
+	uint32		nsubtxns;
+
+	/*
+	 * Stored cache invalidations. This is not a linked list because we get
+	 * all the invalidations at once.
+	 */
+	uint32		ninvalidations;
+	SharedInvalidationMessage *invalidations;
+
+	/* ---
+	 * Position in one of three lists:
+	 * * list of subtransactions if we are *known* to be subxact
+	 * * list of toplevel xacts (can be a as-yet unknown subxact)
+	 * * list of preallocated ReorderBufferTXNs
+	 * ---
+	 */
+	dlist_node	node;
+
+} ReorderBufferTXN;
+
+/* so we can define the callbacks used inside struct ReorderBuffer itself */
+typedef struct ReorderBuffer ReorderBuffer;
+
+/* change callback signature */
+typedef void (*ReorderBufferApplyChangeCB) (
+														ReorderBuffer *rb,
+														ReorderBufferTXN *txn,
+														Relation relation,
+												ReorderBufferChange *change);
+
+/* begin callback signature */
+typedef void (*ReorderBufferBeginCB) (
+												  ReorderBuffer *rb,
+												  ReorderBufferTXN *txn);
+
+/* commit callback signature */
+typedef void (*ReorderBufferCommitCB) (
+												   ReorderBuffer *rb,
+												   ReorderBufferTXN *txn,
+												   XLogRecPtr commit_lsn);
+
+struct ReorderBuffer
+{
+	/*
+	 * xid => ReorderBufferTXN lookup table
+	 */
+	HTAB	   *by_txn;
+
+	/*
+	 * Transactions that could be a toplevel xact, ordered by LSN of the first
+	 * record bearing that xid..
+	 */
+	dlist_head	toplevel_by_lsn;
+
+	/*
+	 * one-entry sized cache for by_txn. Very frequently the same txn gets
+	 * looked up over and over again.
+	 */
+	TransactionId by_txn_last_xid;
+	ReorderBufferTXN *by_txn_last_txn;
+
+	/*
+	 * Callacks to be called when a transactions commits.
+	 */
+	ReorderBufferBeginCB begin;
+	ReorderBufferApplyChangeCB apply_change;
+	ReorderBufferCommitCB commit;
+
+	/*
+	 * Pointer that will be passed untouched to the callbacks.
+	 */
+	void	   *private_data;
+
+	/*
+	 * Private memory context.
+	 */
+	MemoryContext context;
+
+	/*
+	 * Data structure slab cache.
+	 *
+	 * We allocate/deallocate some structures very frequently, to avoid bigger
+	 * overhead we cache some unused ones here.
+	 *
+	 * The maximum number of cached entries is controlled by const variables
+	 * ontop of reorderbuffer.c
+	 */
+
+	/* cached ReorderBufferTXNs */
+	dlist_head	cached_transactions;
+	Size		nr_cached_transactions;
+
+	/* cached ReorderBufferChanges */
+	dlist_head	cached_changes;
+	Size		nr_cached_changes;
+
+	/* cached ReorderBufferTupleBufs */
+	slist_head	cached_tuplebufs;
+	Size		nr_cached_tuplebufs;
+
+	XLogRecPtr	current_restart_decoding_lsn;
+
+	/* buffer for disk<->memory conversions */
+	char	   *outbuf;
+	Size		outbufsize;
+};
+
+
+ReorderBuffer *ReorderBufferAllocate(void);
+void		ReorderBufferFree(ReorderBuffer *);
+
+ReorderBufferTupleBuf *ReorderBufferGetTupleBuf(ReorderBuffer *);
+void		ReorderBufferReturnTupleBuf(ReorderBuffer *, ReorderBufferTupleBuf *tuple);
+ReorderBufferChange *ReorderBufferGetChange(ReorderBuffer *);
+void		ReorderBufferReturnChange(ReorderBuffer *, ReorderBufferChange *);
+
+void		ReorderBufferQueueChange(ReorderBuffer *, TransactionId, XLogRecPtr lsn, ReorderBufferChange *);
+void		ReorderBufferCommit(ReorderBuffer *, TransactionId,
+							XLogRecPtr commit_lsn, XLogRecPtr end_lsn,
+							TimestampTz commit_time);
+void		ReorderBufferAssignChild(ReorderBuffer *, TransactionId, TransactionId, XLogRecPtr commit_lsn);
+void		ReorderBufferCommitChild(ReorderBuffer *, TransactionId, TransactionId,
+									 XLogRecPtr commit_lsn, XLogRecPtr end_lsn);
+void		ReorderBufferAbort(ReorderBuffer *, TransactionId, XLogRecPtr lsn);
+void		ReorderBufferAbortOld(ReorderBuffer *, TransactionId xid);
+
+void		ReorderBufferSetBaseSnapshot(ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap);
+void		ReorderBufferAddSnapshot(ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap);
+void ReorderBufferAddNewCommandId(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
+							 CommandId cid);
+void ReorderBufferAddNewTupleCids(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
+							 RelFileNode node, ItemPointerData pt,
+						 CommandId cmin, CommandId cmax, CommandId combocid);
+void ReorderBufferAddInvalidations(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
+							  Size nmsgs, SharedInvalidationMessage *msgs);
+bool		ReorderBufferIsXidKnown(ReorderBuffer *, TransactionId xid);
+void		ReorderBufferXidSetCatalogChanges(ReorderBuffer *, TransactionId xid, XLogRecPtr lsn);
+bool		ReorderBufferXidHasCatalogChanges(ReorderBuffer *, TransactionId xid);
+bool		ReorderBufferXidHasBaseSnapshot(ReorderBuffer *, TransactionId xid);
+
+ReorderBufferTXN *ReorderBufferGetOldestTXN(ReorderBuffer *);
+
+void		ReorderBufferSetRestartPoint(ReorderBuffer *, XLogRecPtr ptr);
+
+void		StartupReorderBuffer(void);
+
+#endif
diff --git a/src/include/replication/slot.h b/src/include/replication/slot.h
index 089b0f4..26e0241 100644
--- a/src/include/replication/slot.h
+++ b/src/include/replication/slot.h
@@ -32,9 +32,22 @@ typedef struct ReplicationSlotPersistentData
 	 */
 	TransactionId xmin;
 
+	/*
+	 * xmin horizon for catalog tuples
+	 *
+	 * NB: This may represent a value that hasn't been written to disk yet;
+	 * see notes for effective_xmin, below.
+	 */
+	TransactionId catalog_xmin;
+
 	/* oldest LSN that might be required by this replication slot */
 	XLogRecPtr	restart_lsn;
 
+	/* oldest LSN that the client has acked receipt for */
+	XLogRecPtr	confirmed_flush;
+
+	/* plugin name */
+	NameData	plugin;
 } ReplicationSlotPersistentData;
 
 /*
@@ -67,12 +80,26 @@ typedef struct ReplicationSlot
 	 * same as the persistent value (data.xmin).
 	 */
 	TransactionId effective_xmin;
+	TransactionId effective_catalog_xmin;
 
 	/* data surviving shutdowns and crashes */
 	ReplicationSlotPersistentData data;
 
 	/* is somebody performing io on this slot? */
 	LWLock	   *io_in_progress_lock;
+
+	/* all the remaining data is only used for logical slots */
+
+	/* ----
+	 * When the client has confirmed flushes >= candidate_xmin_after we can
+	 * a) advance the pegged xmin
+	 * b) advance restart_decoding_from so we have to read/keep less WAL
+	 * ----
+	 */
+	TransactionId candidate_catalog_xmin;
+	XLogRecPtr	candidate_xmin_lsn;
+	XLogRecPtr	candidate_restart_valid;
+	XLogRecPtr	candidate_restart_lsn;
 } ReplicationSlot;
 
 /*
@@ -106,7 +133,7 @@ extern void ReplicationSlotMarkDirty(void);
 
 /* misc stuff */
 extern bool ReplicationSlotValidateName(const char *name, int elevel);
-extern void ReplicationSlotsComputeRequiredXmin(void);
+extern void ReplicationSlotsComputeRequiredXmin(bool already_locked);
 extern void ReplicationSlotsComputeRequiredLSN(void);
 extern void StartupReplicationSlots(XLogRecPtr checkPointRedo);
 extern void CheckPointReplicationSlots(void);
diff --git a/src/include/replication/snapbuild.h b/src/include/replication/snapbuild.h
new file mode 100644
index 0000000..087c0e5
--- /dev/null
+++ b/src/include/replication/snapbuild.h
@@ -0,0 +1,83 @@
+/*-------------------------------------------------------------------------
+ *
+ * snapbuild.h
+ *	  Exports from replication/logical/snapbuild.c.
+ *
+ * Copyright (c) 2012-2014, PostgreSQL Global Development Group
+ *
+ * src/include/replication/snapbuild.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SNAPBUILD_H
+#define SNAPBUILD_H
+
+#include "access/xlogdefs.h"
+#include "utils/snapmgr.h"
+
+typedef enum
+{
+	/*
+	 * Initial state, we can't do much yet.
+	 */
+	SNAPBUILD_START,
+
+	/*
+	 * We have collected enough information to decode tuples in transactions
+	 * that started after this.
+	 *
+	 * Once we reached this we start to collect changes. We cannot apply them
+	 * yet because the might be based on transactions that were still running
+	 * when we reached them yet.
+	 */
+	SNAPBUILD_FULL_SNAPSHOT,
+
+	/*
+	 * Found a point after hitting built_full_snapshot where all transactions
+	 * that were running at that point finished. Till we reach that we hold
+	 * off calling any commit callbacks.
+	 */
+	SNAPBUILD_CONSISTENT
+} SnapBuildState;
+
+/* forward declare so we don't have to expose the struct to the public */
+struct SnapBuild;
+typedef struct SnapBuild SnapBuild;
+
+/* forward declare so we don't have to include reorderbuffer.h */
+struct ReorderBuffer;
+
+/* forward declare so we don't have to include heapam_xlog.h */
+struct xl_heap_new_cid;
+struct xl_running_xacts;
+
+extern void CheckPointSnapBuild(void);
+
+extern SnapBuild *AllocateSnapshotBuilder(struct ReorderBuffer *cache,
+						  TransactionId xmin_horizon, XLogRecPtr start_lsn);
+extern void FreeSnapshotBuilder(SnapBuild *cache);
+
+extern void SnapBuildSnapDecRefcount(Snapshot snap);
+
+extern const char *SnapBuildExportSnapshot(SnapBuild *snapstate);
+extern void SnapBuildClearExportedSnapshot(void);
+
+extern SnapBuildState SnapBuildCurrentState(SnapBuild *snapstate);
+
+extern bool SnapBuildXactNeedsSkip(SnapBuild *snapstate, XLogRecPtr ptr);
+
+extern void SnapBuildCommitTxn(SnapBuild *builder, XLogRecPtr lsn,
+							   TransactionId xid, int nsubxacts,
+							   TransactionId *subxacts);
+extern void SnapBuildAbortTxn(SnapBuild *builder, XLogRecPtr lsn,
+							  TransactionId xid, int nsubxacts,
+							  TransactionId *subxacts);
+extern bool SnapBuildProcessChange(SnapBuild *builder, TransactionId xid,
+								   XLogRecPtr lsn);
+extern void SnapBuildProcessNewCid(SnapBuild *builder, TransactionId xid,
+								   XLogRecPtr lsn, struct xl_heap_new_cid *cid);
+extern void SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn,
+										 struct xl_running_xacts *running);
+extern void SnapBuildSerializationPoint(SnapBuild *builder, XLogRecPtr lsn);
+
+#endif   /* SNAPBUILD_H */
diff --git a/src/include/storage/itemptr.h b/src/include/storage/itemptr.h
index 67bbdbb..0b81d53 100644
--- a/src/include/storage/itemptr.h
+++ b/src/include/storage/itemptr.h
@@ -116,6 +116,9 @@ typedef ItemPointerData *ItemPointer;
 /*
  * ItemPointerCopy
  *		Copies the contents of one disk item pointer to another.
+ *
+ * Should there ever be padding in an ItemPointer this would need to be handled
+ * differently as it's used as hash key.
  */
 #define ItemPointerCopy(fromPointer, toPointer) \
 ( \
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index a3cadd9..5218b44 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -41,10 +41,12 @@ struct XidCache
 #define		PROC_IS_AUTOVACUUM	0x01	/* is it an autovac worker? */
 #define		PROC_IN_VACUUM		0x02	/* currently running lazy vacuum */
 #define		PROC_IN_ANALYZE		0x04	/* currently running analyze */
-#define		PROC_VACUUM_FOR_WRAPAROUND 0x08		/* set by autovac only */
+#define		PROC_VACUUM_FOR_WRAPAROUND	0x08 /* set by autovac only */
+#define		PROC_IN_LOGICAL_DECODING	0x10 /* currently doing logical decoding */
 
 /* flags reset at EOXact */
-#define		PROC_VACUUM_STATE_MASK (0x0E)
+#define		PROC_VACUUM_STATE_MASK \
+	(PROC_IN_VACUUM | PROC_IN_ANALYZE | PROC_VACUUM_FOR_WRAPAROUND)
 
 /*
  * We allow a small number of "weak" relation locks (AccesShareLock,
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index d1a58a3..284d746 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -50,8 +50,9 @@ extern RunningTransactions GetRunningTransactionData(void);
 
 extern bool TransactionIdIsInProgress(TransactionId xid);
 extern bool TransactionIdIsActive(TransactionId xid);
-extern TransactionId GetOldestXmin(bool allDbs, bool ignoreVacuum);
+extern TransactionId GetOldestXmin(bool allDbs, bool ignoreVacuum, bool systable);
 extern TransactionId GetOldestActiveTransactionId(void);
+extern TransactionId GetOldestSafeDecodingTransactionId(void);
 
 extern VirtualTransactionId *GetVirtualXIDsDelayingChkpt(int *nvxids);
 extern bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids);
@@ -77,6 +78,10 @@ extern void XidCacheRemoveRunningXids(TransactionId xid,
 						  int nxids, const TransactionId *xids,
 						  TransactionId latestXid);
 
-extern void ProcArraySetReplicationSlotXmin(TransactionId xmin);
+extern void ProcArraySetReplicationSlotXmin(TransactionId xmin,
+							TransactionId catalog_xmin, bool already_locked);
+
+extern void ProcArrayGetReplicationSlotXmin(TransactionId *xmin,
+											TransactionId *catalog_xmin);
 
 #endif   /* PROCARRAY_H */
diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h
index 0cae810..d5bb850 100644
--- a/src/include/storage/sinval.h
+++ b/src/include/storage/sinval.h
@@ -147,4 +147,6 @@ extern void ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs
 									 int nmsgs, bool RelcacheInitFileInval,
 									 Oid dbid, Oid tsid);
 
+extern void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg);
+
 #endif   /* SINVAL_H */
diff --git a/src/include/utils/inval.h b/src/include/utils/inval.h
index c1409c8..6156e02 100644
--- a/src/include/utils/inval.h
+++ b/src/include/utils/inval.h
@@ -64,4 +64,5 @@ extern void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func,
 
 extern void CallSyscacheCallbacks(int cacheid, uint32 hashvalue);
 
+extern void InvalidateSystemCaches(void);
 #endif   /* INVAL_H */
diff --git a/src/include/utils/snapmgr.h b/src/include/utils/snapmgr.h
index c601770..fb50f84 100644
--- a/src/include/utils/snapmgr.h
+++ b/src/include/utils/snapmgr.h
@@ -23,6 +23,7 @@ extern bool FirstSnapshotSet;
 extern TransactionId TransactionXmin;
 extern TransactionId RecentXmin;
 extern TransactionId RecentGlobalXmin;
+extern TransactionId RecentGlobalDataXmin;
 
 extern Snapshot GetTransactionSnapshot(void);
 extern Snapshot GetLatestSnapshot(void);
@@ -53,4 +54,6 @@ extern bool XactHasExportedSnapshots(void);
 extern void DeleteAllExportedSnapshotFiles(void);
 extern bool ThereAreNoPriorRegisteredSnapshots(void);
 
+extern char *ExportSnapshot(Snapshot snapshot);
+
 #endif   /* SNAPMGR_H */
diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h
index e34c28a..52c2e3f 100644
--- a/src/include/utils/tqual.h
+++ b/src/include/utils/tqual.h
@@ -22,6 +22,7 @@
 extern PGDLLIMPORT SnapshotData SnapshotSelfData;
 extern PGDLLIMPORT SnapshotData SnapshotAnyData;
 extern PGDLLIMPORT SnapshotData SnapshotToastData;
+extern PGDLLIMPORT SnapshotData CatalogSnapshotData;
 
 #define SnapshotSelf		(&SnapshotSelfData)
 #define SnapshotAny			(&SnapshotAnyData)
@@ -37,7 +38,8 @@ extern PGDLLIMPORT SnapshotData SnapshotToastData;
 
 /* This macro encodes the knowledge of which snapshots are MVCC-safe */
 #define IsMVCCSnapshot(snapshot)  \
-	((snapshot)->satisfies == HeapTupleSatisfiesMVCC)
+	((snapshot)->satisfies == HeapTupleSatisfiesMVCC || \
+	 (snapshot)->satisfies == HeapTupleSatisfiesMVCCDuringDecoding)
 
 /*
  * HeapTupleSatisfiesVisibility
@@ -86,4 +88,23 @@ extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
 					 uint16 infomask, TransactionId xid);
 extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
 
+/* Support for catalog timetravel */
+struct HTAB;
+extern bool HeapTupleSatisfiesMVCCDuringDecoding(HeapTuple htup,
+												 Snapshot snapshot, Buffer buffer);
+extern void SetupDecodingSnapshots(Snapshot snapshot_now, struct HTAB *tuplecids);
+extern void RevertFromDecodingSnapshots(bool is_error);
+extern void SuspendDecodingSnapshots(void);
+extern void UnSuspendDecodingSnapshots(void);
+extern bool DecodingSnapshotsActive(void);
+
+/*
+ * To avoid leaking to much knowledge about reorderbuffer implementation
+ * details this is implemented in reorderbuffer.c not tqual.c.
+ */
+extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data,
+										  Snapshot snapshot,
+										  HeapTuple htup,
+										  Buffer buffer,
+										  CommandId *cmin, CommandId *cmax);
 #endif   /* TQUAL_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 220e18b..5f3fb37 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1368,13 +1368,15 @@ pg_prepared_xacts| SELECT p.transaction,
    LEFT JOIN pg_authid u ON ((p.ownerid = u.oid)))
    LEFT JOIN pg_database d ON ((p.dbid = d.oid)));
 pg_replication_slots| SELECT l.slot_name,
+    l.plugin,
     l.slot_type,
     l.datoid,
     d.datname AS database,
     l.active,
     l.xmin,
+    l.catalog_xmin,
     l.restart_lsn
-   FROM (pg_get_replication_slots() l(slot_name, slot_type, datoid, active, xmin, restart_lsn)
+   FROM (pg_get_replication_slots() l(slot_name, plugin, slot_type, datoid, active, xmin, catalog_xmin, restart_lsn)
    LEFT JOIN pg_database d ON ((l.datoid = d.oid)));
 pg_roles| SELECT pg_authid.rolname,
     pg_authid.rolsuper,
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 3b7f61e..f960454 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -940,6 +940,17 @@ LockTupleMode
 LockingClause
 LogOpts
 LogStmtLevel
+LogicalDecodeBeginCB
+LogicalDecodeChangeCB
+LogicalDecodeCleanupCB
+LogicalDecodeCommitCB
+LogicalDecodeInitCB
+LogicalDecodingCheckpointData
+LogicalDecodingContext
+LogicalDecodingCtlData
+LogicalDecodingSlot
+LogicalOutputPluginWriterPrepareWrite
+LogicalOutputPluginWriterWrite
 LogicalTape
 LogicalTapeSet
 MAGIC
@@ -1053,6 +1064,7 @@ OprInfo
 OprProofCacheEntry
 OprProofCacheKey
 OutputContext
+OutputPluginCallbacks
 OverrideSearchPath
 OverrideStackEntry
 PACE_HEADER
@@ -1468,6 +1480,21 @@ Relids
 RelocationBufferInfo
 RenameStmt
 ReopenPtr
+ReorderBuffer
+ReorderBufferApplyChangeCB
+ReorderBufferBeginCB
+ReorderBufferChange
+ReorderBufferChangeTypeInternal
+ReorderBufferCommitCB
+ReorderBufferDiskChange
+ReorderBufferIterTXNEntry
+ReorderBufferIterTXNState
+ReorderBufferToastEnt
+ReorderBufferTupleBuf
+ReorderBufferTupleCidEnt
+ReorderBufferTupleCidKey
+ReorderBufferTXN
+ReorderBufferTXNByIdEnt
 ReplaceVarsFromTargetList_context
 ReplaceVarsNoMatchOption
 ResTarget
@@ -1522,6 +1549,8 @@ SID_NAME_USE
 SISeg
 SMgrRelation
 SMgrRelationData
+SnapBuildAction
+SnapBuildState
 SOCKADDR
 SOCKET
 SPELL
@@ -1613,6 +1642,8 @@ SlruSharedData
 Snapshot
 SnapshotData
 SnapshotSatisfiesFunc
+Snapstate
+SnapstateOnDisk
 SockAddr
 Sort
 SortBy
@@ -1929,6 +1960,7 @@ XLogReaderState
 XLogRecData
 XLogRecPtr
 XLogRecord
+XLogRecordBuffer
 XLogSegNo
 XLogSource
 XLogwrtResult
@@ -2351,6 +2383,7 @@ symbol
 tablespaceinfo
 teReqs
 teSection
+TestDecodingData
 temp_tablespaces_extra
 text
 timeKEY
-- 
1.8.5.rc2.dirty

0002-wal_decoding-logical-changeset-extraction-walsender-.patchtext/x-patch; charset=us-asciiDownload
>From 0e3fccca205842e5eeef6580be5b0c529530e1e7 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 27 Jan 2014 17:13:48 +0100
Subject: [PATCH 2/5] wal_decoding: logical changeset extraction walsender
 interface

This exposes the changeset extraction feature via walsenders which
allows the data to be received in a streaming fashion and supports
synchronous replication.

To do this walsenders need to be able to connect to a specific
database. For that it extend the existing 'replication' parameter to
not only allow a boolean value but also "database". If the latter is
specified we connect to the database specified in 'dbname'.
---
 doc/src/sgml/protocol.sgml                         |  24 +-
 src/backend/postmaster/postmaster.c                |  23 +-
 .../libpqwalreceiver/libpqwalreceiver.c            |   4 +-
 src/backend/replication/repl_gram.y                |  78 ++-
 src/backend/replication/repl_scanner.l             |   1 +
 src/backend/replication/walsender.c                | 666 +++++++++++++++++++--
 src/backend/utils/init/postinit.c                  |   5 +
 src/bin/pg_basebackup/pg_basebackup.c              |   6 +-
 src/bin/pg_basebackup/pg_receivexlog.c             |   6 +-
 src/bin/pg_basebackup/receivelog.c                 |   6 +-
 src/include/replication/walsender.h                |   1 +
 src/include/replication/walsender_private.h        |   3 +
 src/tools/pgindent/typedefs.list                   |   1 +
 13 files changed, 735 insertions(+), 89 deletions(-)

diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 832524e..8d890ba 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1302,10 +1302,13 @@
 
 <para>
 To initiate streaming replication, the frontend sends the
-<literal>replication</> parameter in the startup message. This tells the
-backend to go into walsender mode, wherein a small set of replication commands
-can be issued instead of SQL statements. Only the simple query protocol can be
-used in walsender mode.
+<literal>replication</> parameter in the startup message. A boolean value
+of <literal>true</> tells the backend to go into walsender mode, wherein a
+small set of replication commands can be issued instead of SQL statements. Only
+the simple query protocol can be used in walsender mode.
+Passing a <literal>database</> as the value instructs walsender to connect to
+the database specified in the <literal>dbname</> paramter which will in future
+allow some additional commands to the ones specified below to be run.
 
 The commands accepted in walsender mode are:
 
@@ -1315,7 +1318,7 @@ The commands accepted in walsender mode are:
     <listitem>
      <para>
       Requests the server to identify itself. Server replies with a result
-      set of a single row, containing three fields:
+      set of a single row, containing four fields:
      </para>
 
      <para>
@@ -1357,6 +1360,17 @@ The commands accepted in walsender mode are:
       </listitem>
       </varlistentry>
 
+      <varlistentry>
+      <term>
+       dbname
+      </term>
+      <listitem>
+      <para>
+       Database connected to or NULL.
+      </para>
+      </listitem>
+      </varlistentry>
+
       </variablelist>
      </para>
     </listitem>
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 5468eb1..5bc5213 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1894,10 +1894,21 @@ retry1:
 				port->cmdline_options = pstrdup(valptr);
 			else if (strcmp(nameptr, "replication") == 0)
 			{
-				if (!parse_bool(valptr, &am_walsender))
+				/*
+				 * Due to backward compatibility concerns replication is a
+				 * bybrid beast which allows the value to be either a boolean
+				 * or the string 'database'. The latter connects to a specific
+				 * database which is e.g. required for changeset extraction.
+				 */
+				if (strcmp(valptr, "database") == 0)
+				{
+					am_walsender = true;
+					am_db_walsender = true;
+				}
+				else if (!parse_bool(valptr, &am_walsender))
 					ereport(FATAL,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("invalid value for boolean option \"replication\"")));
+							 errmsg("invalid value for option \"replication\", legal values are false, 0, true, 1 or database")));
 			}
 			else
 			{
@@ -1978,8 +1989,12 @@ retry1:
 	if (strlen(port->user_name) >= NAMEDATALEN)
 		port->user_name[NAMEDATALEN - 1] = '\0';
 
-	/* Walsender is not related to a particular database */
-	if (am_walsender)
+	/*
+	 * Generic walsender, e.g. for streaming replication, is not connected to a
+	 * particular database. But walsenders used for logical replication need to
+	 * connect to a specific database.
+	 */
+	if (am_walsender && !am_db_walsender)
 		port->database_name[0] = '\0';
 
 	/*
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index ecec8b3..7546be9 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -131,7 +131,7 @@ libpqrcv_identify_system(TimeLineID *primary_tli)
 						"the primary server: %s",
 						PQerrorMessage(streamConn))));
 	}
-	if (PQnfields(res) != 3 || PQntuples(res) != 1)
+	if (PQnfields(res) < 3 || PQntuples(res) != 1)
 	{
 		int			ntuples = PQntuples(res);
 		int			nfields = PQnfields(res);
@@ -139,7 +139,7 @@ libpqrcv_identify_system(TimeLineID *primary_tli)
 		PQclear(res);
 		ereport(ERROR,
 				(errmsg("invalid response from primary server"),
-				 errdetail("Expected 1 tuple with 3 fields, got %d tuples with %d fields.",
+				 errdetail("Expected 1 tuple with 3 or more fields, got %d tuples with %d fields.",
 						   ntuples, nfields)));
 	}
 	primary_sysid = PQgetvalue(res, 0, 0);
diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y
index c3f4a24..163965a 100644
--- a/src/backend/replication/repl_gram.y
+++ b/src/backend/replication/repl_gram.y
@@ -72,13 +72,17 @@ Node *replication_parse_result;
 %token K_WAL
 %token K_TIMELINE
 %token K_PHYSICAL
+%token K_LOGICAL
 %token K_SLOT
 
 %type <node>	command
-%type <node>	base_backup start_replication create_replication_slot drop_replication_slot identify_system timeline_history
+%type <node>	base_backup start_replication start_logical_replication create_replication_slot drop_replication_slot identify_system timeline_history
 %type <list>	base_backup_opt_list
 %type <defelt>	base_backup_opt
 %type <uintval>	opt_timeline
+%type <list>	plugin_options plugin_opt_list
+%type <defelt>	plugin_opt_elem
+%type <node>	plugin_opt_arg
 %type <str>		opt_slot
 
 %%
@@ -97,6 +101,7 @@ command:
 			identify_system
 			| base_backup
 			| start_replication
+			| start_logical_replication
 			| create_replication_slot
 			| drop_replication_slot
 			| timeline_history
@@ -169,6 +174,17 @@ create_replication_slot:
 					cmd->slotname = $2;
 					$$ = (Node *) cmd;
 				}
+			|
+/* CREATE_REPLICATION_SLOT SLOT slot LOGICAL plugin */
+			K_CREATE_REPLICATION_SLOT IDENT K_LOGICAL IDENT
+				{
+					CreateReplicationSlotCmd *cmd;
+					cmd = makeNode(CreateReplicationSlotCmd);
+					cmd->kind = REPLICATION_KIND_LOGICAL;
+					cmd->slotname = $2;
+					cmd->plugin = $4;
+					$$ = (Node *) cmd;
+				}
 			;
 
 /* DROP_REPLICATION_SLOT SLOT slot */
@@ -199,19 +215,19 @@ start_replication:
 				}
 			;
 
-opt_timeline:
-			K_TIMELINE UCONST
+/* START_REPLICATION SLOT slot LOGICAL %X/%X options */
+start_logical_replication:
+			K_START_REPLICATION K_SLOT IDENT K_LOGICAL RECPTR plugin_options
 				{
-					if ($2 <= 0)
-						ereport(ERROR,
-								(errcode(ERRCODE_SYNTAX_ERROR),
-								 (errmsg("invalid timeline %u", $2))));
-					$$ = $2;
+					StartReplicationCmd *cmd;
+					cmd = makeNode(StartReplicationCmd);
+					cmd->kind = REPLICATION_KIND_LOGICAL;;
+					cmd->slotname = $3;
+					cmd->startpoint = $5;
+					cmd->options = $6;
+					$$ = (Node *) cmd;
 				}
-			| /* EMPTY */
-				{ $$ = 0; }
 			;
-
 /*
  * TIMELINE_HISTORY %d
  */
@@ -244,6 +260,46 @@ opt_slot:
 				{ $$ = NULL; }
 			;
 
+opt_timeline:
+			K_TIMELINE UCONST
+				{
+					if ($2 <= 0)
+						ereport(ERROR,
+								(errcode(ERRCODE_SYNTAX_ERROR),
+								 (errmsg("invalid timeline %u", $2))));
+					$$ = $2;
+				}
+				| /* EMPTY */			{ $$ = 0; }
+			;
+
+
+plugin_options:
+			'(' plugin_opt_list ')'			{ $$ = $2; }
+			| /* EMPTY */					{ $$ = NIL; }
+		;
+
+plugin_opt_list:
+			plugin_opt_elem
+				{
+					$$ = list_make1($1);
+				}
+			| plugin_opt_list ',' plugin_opt_elem
+				{
+					$$ = lappend($1, $3);
+				}
+		;
+
+plugin_opt_elem:
+			IDENT plugin_opt_arg
+				{
+					$$ = makeDefElem($1, $2);
+				}
+		;
+
+plugin_opt_arg:
+			SCONST							{ $$ = (Node *) makeString($1); }
+			| /* EMPTY */					{ $$ = NULL; }
+		;
 %%
 
 #include "repl_scanner.c"
diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l
index 24195a5..6418b7a 100644
--- a/src/backend/replication/repl_scanner.l
+++ b/src/backend/replication/repl_scanner.l
@@ -93,6 +93,7 @@ CREATE_REPLICATION_SLOT		{ return K_CREATE_REPLICATION_SLOT; }
 DROP_REPLICATION_SLOT		{ return K_DROP_REPLICATION_SLOT; }
 TIMELINE_HISTORY	{ return K_TIMELINE_HISTORY; }
 PHYSICAL			{ return K_PHYSICAL; }
+LOGICAL				{ return K_LOGICAL; }
 SLOT				{ return K_SLOT; }
 
 ","				{ return ','; }
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 88119b9..8ebe026 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -45,15 +45,22 @@
 
 #include "access/timeline.h"
 #include "access/transam.h"
+#include "access/xact.h"
 #include "access/xlog_internal.h"
+
 #include "catalog/pg_type.h"
+#include "commands/dbcommands.h"
 #include "funcapi.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "nodes/replnodes.h"
 #include "replication/basebackup.h"
+#include "replication/decode.h"
+#include "replication/logical.h"
+#include "replication/logicalfuncs.h"
 #include "replication/slot.h"
+#include "replication/snapbuild.h"
 #include "replication/syncrep.h"
 #include "replication/slot.h"
 #include "replication/walreceiver.h"
@@ -91,9 +98,10 @@ WalSndCtlData *WalSndCtl = NULL;
 WalSnd	   *MyWalSnd = NULL;
 
 /* Global state */
-bool		am_walsender = false;		/* Am I a walsender process ? */
+bool		am_walsender = false;		/* Am I a walsender process? */
 bool		am_cascading_walsender = false;		/* Am I cascading WAL to
-												 * another standby ? */
+												 * another standby? */
+bool		am_db_walsender = false;		/* connect to database? */
 
 /* User-settable parameters for walsender */
 int			max_wal_senders = 0;	/* the maximum number of concurrent walsenders */
@@ -155,6 +163,9 @@ static bool ping_sent = false;
 static bool streamingDoneSending;
 static bool streamingDoneReceiving;
 
+/* Are we there yet? */
+static bool		WalSndCaughtUp = false;
+
 /* Flags set by signal handlers for later service in main loop */
 static volatile sig_atomic_t got_SIGHUP = false;
 static volatile sig_atomic_t walsender_ready_to_stop = false;
@@ -167,24 +178,36 @@ static volatile sig_atomic_t walsender_ready_to_stop = false;
  */
 static volatile sig_atomic_t replication_active = false;
 
+static LogicalDecodingContext *logical_decoding_ctx = NULL;
+static XLogRecPtr  logical_startptr = InvalidXLogRecPtr;
+
 /* Signal handlers */
 static void WalSndSigHupHandler(SIGNAL_ARGS);
 static void WalSndXLogSendHandler(SIGNAL_ARGS);
 static void WalSndLastCycleHandler(SIGNAL_ARGS);
 
 /* Prototypes for private functions */
-static void WalSndLoop(void);
+typedef void (*WalSndSendData)(void);
+static void WalSndLoop(WalSndSendData send_data);
 static void InitWalSenderSlot(void);
 static void WalSndKill(int code, Datum arg);
-static void XLogSend(bool *caughtup);
+static void XLogSendPhysical(void);
+static void XLogSendLogical(void);
+static void WalSndDone(WalSndSendData send_data);
 static XLogRecPtr GetStandbyFlushRecPtr(void);
 static void IdentifySystem(void);
+static void CreateReplicationSlot(CreateReplicationSlotCmd *cmd);
+static void DropReplicationSlot(DropReplicationSlotCmd *cmd);
 static void StartReplication(StartReplicationCmd *cmd);
+static void StartLogicalReplication(StartReplicationCmd *cmd);
 static void ProcessStandbyMessage(void);
 static void ProcessStandbyReplyMessage(void);
 static void ProcessStandbyHSFeedbackMessage(void);
 static void ProcessRepliesIfAny(void);
 static void WalSndKeepalive(bool requestReply);
+static void WalSndPrepareWrite(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write);
+static void WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write);
+static void XLogRead(char *buf, XLogRecPtr startptr, Size count);
 
 
 /* Initialize walsender process before entering the main command loop */
@@ -250,10 +273,12 @@ IdentifySystem(void)
 	char		tli[11];
 	char		xpos[MAXFNAMELEN];
 	XLogRecPtr	logptr;
+	char	   *dbname = NULL;
 
 	/*
-	 * Reply with a result set with one row, three columns. First col is
-	 * system ID, second is timeline ID, and third is current xlog location.
+	 * Reply with a result set with one row, four columns. First col is system
+	 * ID, second is timeline ID, third is current xlog location and the fourth
+	 * contains the database name if we are connected to one.
 	 */
 
 	snprintf(sysid, sizeof(sysid), UINT64_FORMAT,
@@ -272,9 +297,23 @@ IdentifySystem(void)
 
 	snprintf(xpos, sizeof(xpos), "%X/%X", (uint32) (logptr >> 32), (uint32) logptr);
 
+	if (MyDatabaseId != InvalidOid)
+	{
+		MemoryContext cur = CurrentMemoryContext;
+
+		/* syscache access needs a transaction env. */
+		StartTransactionCommand();
+		/* make dbname live outside TX context */
+		MemoryContextSwitchTo(cur);
+		dbname = get_database_name(MyDatabaseId);
+		CommitTransactionCommand();
+		/* CommitTransactionCommand switches to TopMemoryContext */
+		MemoryContextSwitchTo(cur);
+	}
+
 	/* Send a RowDescription message */
 	pq_beginmessage(&buf, 'T');
-	pq_sendint(&buf, 3, 2);		/* 3 fields */
+	pq_sendint(&buf, 4, 2);		/* 4 fields */
 
 	/* first field */
 	pq_sendstring(&buf, "systemid");	/* col name */
@@ -295,24 +334,43 @@ IdentifySystem(void)
 	pq_sendint(&buf, 0, 2);		/* format code */
 
 	/* third field */
-	pq_sendstring(&buf, "xlogpos");
-	pq_sendint(&buf, 0, 4);
-	pq_sendint(&buf, 0, 2);
-	pq_sendint(&buf, TEXTOID, 4);
-	pq_sendint(&buf, -1, 2);
-	pq_sendint(&buf, 0, 4);
-	pq_sendint(&buf, 0, 2);
+	pq_sendstring(&buf, "xlogpos"); /* col name */
+	pq_sendint(&buf, 0, 4);     /* table oid */
+	pq_sendint(&buf, 0, 2);     /* attnum */
+	pq_sendint(&buf, TEXTOID, 4);       /* type oid */
+	pq_sendint(&buf, -1, 2);        /* typlen */
+	pq_sendint(&buf, 0, 4);     /* typmod */
+	pq_sendint(&buf, 0, 2);     /* format code */
+
+	/* fourth field */
+	pq_sendstring(&buf, "dbname");  /* col name */
+	pq_sendint(&buf, 0, 4);     /* table oid */
+	pq_sendint(&buf, 0, 2);     /* attnum */
+	pq_sendint(&buf, TEXTOID, 4);       /* type oid */
+	pq_sendint(&buf, -1, 2);        /* typlen */
+	pq_sendint(&buf, 0, 4);     /* typmod */
+	pq_sendint(&buf, 0, 2);     /* format code */
 	pq_endmessage(&buf);
 
 	/* Send a DataRow message */
 	pq_beginmessage(&buf, 'D');
-	pq_sendint(&buf, 3, 2);		/* # of columns */
+	pq_sendint(&buf, 4, 2);		/* # of columns */
 	pq_sendint(&buf, strlen(sysid), 4); /* col1 len */
 	pq_sendbytes(&buf, (char *) &sysid, strlen(sysid));
 	pq_sendint(&buf, strlen(tli), 4);	/* col2 len */
 	pq_sendbytes(&buf, (char *) tli, strlen(tli));
 	pq_sendint(&buf, strlen(xpos), 4);	/* col3 len */
 	pq_sendbytes(&buf, (char *) xpos, strlen(xpos));
+	/* send NULL if not connected to a database */
+	if (dbname)
+	{
+		pq_sendint(&buf, strlen(dbname), 4);    /* col4 len */
+		pq_sendbytes(&buf, (char *) dbname, strlen(dbname));
+	}
+	else
+	{
+		pq_sendint(&buf, -1, 4);    /* col4 len, NULL */
+	}
 
 	pq_endmessage(&buf);
 }
@@ -571,7 +629,7 @@ StartReplication(StartReplicationCmd *cmd)
 		/* Main loop of walsender */
 		replication_active = true;
 
-		WalSndLoop();
+		WalSndLoop(XLogSendPhysical);
 
 		replication_active = false;
 		if (walsender_ready_to_stop)
@@ -641,6 +699,31 @@ StartReplication(StartReplicationCmd *cmd)
 	pq_puttextmessage('C', "START_STREAMING");
 }
 
+static int
+replay_read_page(XLogReaderState* state, XLogRecPtr targetPagePtr, int reqLen,
+				 XLogRecPtr targetRecPtr, char* cur_page, TimeLineID *pageTLI)
+{
+	XLogRecPtr flushptr;
+	int		count;
+
+	flushptr = WalSndWaitForWal(targetPagePtr + reqLen);
+
+	/* more than one block available */
+	if (targetPagePtr + XLOG_BLCKSZ <= flushptr)
+		count = XLOG_BLCKSZ;
+	/* not enough data there */
+	else if (targetPagePtr + reqLen > flushptr)
+		return -1;
+	/* part of the page available */
+	else
+		count = flushptr - targetPagePtr;
+
+	/* FIXME: more sensible/efficient implementation */
+	XLogRead(cur_page, targetPagePtr, XLOG_BLCKSZ);
+
+	return count;
+}
+
 /*
  * Create a new replication slot.
  */
@@ -648,6 +731,8 @@ static void
 CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 {
 	const char *slot_name;
+	const char *snapshot_name = NULL;
+	char        xpos[MAXFNAMELEN];
 	StringInfoData buf;
 
 	Assert(!MyReplicationSlot);
@@ -656,22 +741,51 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 	sendTimeLineIsHistoric = false;
 	sendTimeLine = ThisTimeLineID;
 
+	if (cmd->kind == REPLICATION_KIND_LOGICAL)
+		CheckLogicalDecodingRequirements();
+
 	ReplicationSlotCreate(cmd->slotname, cmd->kind == REPLICATION_KIND_LOGICAL);
 
 	initStringInfo(&output_message);
 
 	slot_name = NameStr(MyReplicationSlot->data.name);
 
-	/*
-	 * It may seem somewhat pointless to send back the same slot name the
-	 * client just requested and nothing else, but logical replication
-	 * will add more fields here.  (We could consider removing the slot
-	 * name from what's sent back, though, since the client has specified
-	 * that.)
-	 */
+	if (cmd->kind == REPLICATION_KIND_LOGICAL)
+	{
+
+		PG_TRY();
+		{
+			LogicalDecodingContext *ctx;
+
+			ctx = CreateDecodingContext(
+				true, cmd->plugin, InvalidXLogRecPtr, NIL,
+				replay_read_page, WalSndPrepareWrite, WalSndWriteData);
+
+			/* build initial snapshot, might take a while */
+			DecodingContextFindStartpoint(ctx);
+
+			/* export plain, importable, snapshot to the user */
+			snapshot_name = SnapBuildExportSnapshot(ctx->snapshot_builder);
+
+			/* don't need the decoding context anymore */
+			FreeDecodingContext(ctx);
+		}
+		PG_CATCH();
+		{
+			ReplicationSlotRelease();
+			ReplicationSlotDrop(cmd->slotname);
+			PG_RE_THROW();
+		}
+		PG_END_TRY();
+	}
+
+	slot_name = NameStr(MyReplicationSlot->data.name);
+	snprintf(xpos, sizeof(xpos), "%X/%X",
+			 (uint32) (MyReplicationSlot->data.confirmed_flush >> 32),
+			 (uint32) MyReplicationSlot->data.confirmed_flush);
 
 	pq_beginmessage(&buf, 'T');
-	pq_sendint(&buf, 1, 2);		/* 1 field */
+	pq_sendint(&buf, 1, 2);		/* 4 fields */
 
 	/* first field: slot name */
 	pq_sendstring(&buf, "slot_name");	/* col name */
@@ -682,16 +796,65 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 	pq_sendint(&buf, 0, 4);		/* typmod */
 	pq_sendint(&buf, 0, 2);		/* format code */
 
+	/* second field: LSN at which we became consistent */
+	pq_sendstring(&buf, "consistent_point");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
+	/* third field: exported snapshot's name */
+	pq_sendstring(&buf, "snapshot_name");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
+	/* fourth field: output plugin */
+	pq_sendstring(&buf, "output_plugin");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
 	pq_endmessage(&buf);
 
 	/* Send a DataRow message */
 	pq_beginmessage(&buf, 'D');
-	pq_sendint(&buf, 1, 2);		/* # of columns */
+	pq_sendint(&buf, 4, 2);		/* # of columns */
 
 	/* slot_name */
 	pq_sendint(&buf, strlen(slot_name), 4); /* col1 len */
 	pq_sendbytes(&buf, slot_name, strlen(slot_name));
 
+	/* consistent wal location */
+	pq_sendint(&buf, strlen(xpos), 4); /* col2 len */
+	pq_sendbytes(&buf, xpos, strlen(xpos));
+
+	/* snapshot name */
+	if (snapshot_name != NULL)
+	{
+		pq_sendint(&buf, strlen(snapshot_name), 4); /* col3 len */
+		pq_sendbytes(&buf, snapshot_name, strlen(snapshot_name));
+	}
+	else
+		pq_sendint(&buf, -1, 4);    /* col3 len, NULL */
+
+    /* plugin */
+    if (cmd->plugin != NULL)
+    {
+        pq_sendint(&buf, strlen(cmd->plugin), 4); /* col4 len */
+        pq_sendbytes(&buf, cmd->plugin, strlen(cmd->plugin));
+    }
+    else
+        pq_sendint(&buf, -1, 4);    /* col4 len, NULL */
+
 	pq_endmessage(&buf);
 
 	/*
@@ -711,6 +874,320 @@ DropReplicationSlot(DropReplicationSlotCmd *cmd)
 }
 
 /*
+ * Load previously initiated logical slot and prepare for sending data (via
+ * WalSndLoop).
+ */
+static void
+StartLogicalReplication(StartReplicationCmd *cmd)
+{
+	StringInfoData buf;
+
+	/* make sure that our requirements are still fulfilled */
+	CheckLogicalDecodingRequirements();
+
+	Assert(!MyReplicationSlot);
+
+	ReplicationSlotAcquire(cmd->slotname);
+
+	if (am_cascading_walsender && !RecoveryInProgress())
+	{
+		ereport(LOG,
+				(errmsg("terminating walsender process to force cascaded standby to update timeline and reconnect")));
+		walsender_ready_to_stop = true;
+	}
+
+	WalSndSetState(WALSNDSTATE_CATCHUP);
+
+	/* Send a CopyBothResponse message, and start streaming */
+	pq_beginmessage(&buf, 'W');
+	pq_sendbyte(&buf, 0);
+	pq_sendint(&buf, 0, 2);
+	pq_endmessage(&buf);
+	pq_flush();
+
+	/* setup state for XLogReadPage */
+	sendTimeLineIsHistoric = false;
+	sendTimeLine = ThisTimeLineID;
+
+	/*
+	 * Initialize position to the last ack'ed one, then the xlog records begin
+	 * to be shipped from that position.
+	 */
+	logical_decoding_ctx = CreateDecodingContext(
+		false, NULL, cmd->startpoint, cmd->options,
+		replay_read_page, WalSndPrepareWrite, WalSndWriteData);
+
+	/*
+	 * XXX: For feedback purposes it would be nicer to set sentPtr to
+	 * cmd->startpoint, but we use it to know where to read xlog in the main
+	 * loop...
+	 */
+	sentPtr = MyReplicationSlot->data.restart_lsn;
+	logical_startptr = sentPtr;
+
+	/* Also update the start position status in shared memory */
+	{
+		/* use volatile pointer to prevent code rearrangement */
+		volatile WalSnd *walsnd = MyWalSnd;
+
+		SpinLockAcquire(&walsnd->mutex);
+		walsnd->sentPtr = MyReplicationSlot->data.restart_lsn;
+		SpinLockRelease(&walsnd->mutex);
+	}
+
+	replication_active = true;
+
+	SyncRepInitConfig();
+
+	/* Main loop of walsender */
+	WalSndLoop(XLogSendLogical);
+
+	FreeDecodingContext(logical_decoding_ctx);
+	ReplicationSlotRelease();
+
+	replication_active = false;
+	if (walsender_ready_to_stop)
+		proc_exit(0);
+	WalSndSetState(WALSNDSTATE_STARTUP);
+
+	/* Get out of COPY mode (CommandComplete). */
+	EndCommand("COPY 0", DestRemote);
+}
+
+/*
+ * LogicalDecodingContext 'prepare_write' callback.
+ *
+ * Prepare a write into a StringInfo.
+ *
+ * Don't do anything lasting in here, it's quite possible that nothing will done
+ * with the data.
+ */
+static void
+WalSndPrepareWrite(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write)
+{
+	/* can't have sync rep confused by sending the same LSN several times */
+	if (!last_write)
+		lsn = InvalidXLogRecPtr;
+
+	resetStringInfo(ctx->out);
+
+	pq_sendbyte(ctx->out, 'w');
+	pq_sendint64(ctx->out, lsn);	/* dataStart */
+	/* XXX: overwrite when data is assembled */
+	pq_sendint64(ctx->out, lsn);	/* walEnd */
+	/* XXX: gather that value later just as it's done in XLogSendPhysical */
+	pq_sendint64(ctx->out, 0 /*GetCurrentIntegerTimestamp() */);/* sendtime */
+}
+
+/*
+ * LogicalDecodingContext 'write' callback.
+ *
+ * Actually write out data previously prepared by WalSndPrepareWrite out to the
+ * network, take as long as needed but process replies from the other side
+ * during that.
+ */
+static void
+WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write)
+{
+	/* output previously gathered data in a CopyData packet */
+	pq_putmessage_noblock('d', ctx->out->data, ctx->out->len);
+
+	/* fast path */
+	/* Try to flush pending output to the client */
+	if (pq_flush_if_writable() != 0)
+		return;
+
+	if (!pq_is_send_pending())
+		return;
+
+	for (;;)
+	{
+		int			wakeEvents;
+		long		sleeptime = 10000;		/* 10s */
+
+		/*
+		 * Emergency bailout if postmaster has died.  This is to avoid the
+		 * necessity for manual cleanup of all postmaster children.
+		 */
+		if (!PostmasterIsAlive())
+			exit(1);
+
+		/* Process any requests or signals received recently */
+		if (got_SIGHUP)
+		{
+			got_SIGHUP = false;
+			ProcessConfigFile(PGC_SIGHUP);
+			SyncRepInitConfig();
+		}
+
+		CHECK_FOR_INTERRUPTS();
+
+		/* Check for input from the client */
+		ProcessRepliesIfAny();
+
+		/* Clear any already-pending wakeups */
+		ResetLatch(&MyWalSnd->latch);
+
+		/* Try to flush pending output to the client */
+		if (pq_flush_if_writable() != 0)
+			break;
+
+		/* If we finished clearing the buffered data, we're done here. */
+		if (!pq_is_send_pending())
+			break;
+
+		/*
+		 * Note we don't set a timeout here.  It would be pointless, because
+		 * if the socket is not writable there's not much we can do elsewhere
+		 * anyway.
+		 */
+		wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH |
+			WL_SOCKET_WRITEABLE | WL_SOCKET_READABLE | WL_TIMEOUT;
+
+		ImmediateInterruptOK = true;
+		CHECK_FOR_INTERRUPTS();
+		WaitLatchOrSocket(&MyWalSnd->latch, wakeEvents,
+						  MyProcPort->sock, sleeptime);
+		ImmediateInterruptOK = false;
+	}
+
+	/* reactivate latch so WalSndLoop knows to continue */
+	SetLatch(&MyWalSnd->latch);
+}
+
+/*
+ * Wait till WAL < loc is flushed to disk so it can be safely read.
+ */
+XLogRecPtr
+WalSndWaitForWal(XLogRecPtr loc)
+{
+	int			wakeEvents;
+	XLogRecPtr  flushptr;
+
+	/* fast path if everything is there already */
+	/*
+	 * XXX: introduce RecentFlushPtr to avoid acquiring the spinlock in the
+	 * fast path case where we already know we have enough WAL available.
+	 */
+	if (!RecoveryInProgress())
+		flushptr = GetFlushRecPtr();
+	else
+		flushptr = GetXLogReplayRecPtr(NULL);
+
+	if (loc <= flushptr)
+		return flushptr;
+
+	/*
+	 * Waiting for new WAL, we've caught up.
+	 */
+	WalSndCaughtUp = true;
+
+	for (;;)
+	{
+		long		sleeptime = 10000;		/* 10 s */
+
+		wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH |
+			WL_SOCKET_READABLE | WL_TIMEOUT;
+
+		/*
+		 * Emergency bailout if postmaster has died.  This is to avoid the
+		 * necessity for manual cleanup of all postmaster children.
+		 */
+		if (!PostmasterIsAlive())
+			exit(1);
+
+		/* Process any requests or signals received recently */
+		if (got_SIGHUP)
+		{
+			got_SIGHUP = false;
+			ProcessConfigFile(PGC_SIGHUP);
+			SyncRepInitConfig();
+		}
+
+		CHECK_FOR_INTERRUPTS();
+
+		/* Check for input from the client */
+		ProcessRepliesIfAny();
+
+		/* Clear any already-pending wakeups */
+		ResetLatch(&MyWalSnd->latch);
+
+		/* Update our idea of flushed position. */
+		if (!RecoveryInProgress())
+			flushptr = GetFlushRecPtr();
+		else
+			flushptr = GetXLogReplayRecPtr(NULL);
+
+		/* If postmaster asked us to stop, don't wait here anymore */
+		if (walsender_ready_to_stop)
+			break;
+
+		/* check whether we're done */
+		if (loc <= flushptr)
+			break;
+
+		/*
+		 * We only send regular messages to the client for full
+		 * decoded transactions. If the flush position differs
+		 */
+		if (MyWalSnd->flush < sentPtr && !ping_sent)
+			WalSndKeepalive(true);
+
+		/* Try to flush pending output to the client */
+		if (pq_is_send_pending())
+		{
+			pq_flush_if_writable();
+			if (pq_is_send_pending())
+				wakeEvents |= WL_SOCKET_WRITEABLE;
+		}
+
+		/* Determine time until replication timeout */
+		if (wal_sender_timeout > 0)
+		{
+			if (!ping_sent)
+			{
+				TimestampTz timeout;
+
+				/*
+				 * If half of wal_sender_timeout has lapsed without receiving
+				 * any reply from standby, send a keep-alive message to standby
+				 * requesting an immediate reply.
+				 */
+				timeout = TimestampTzPlusMilliseconds(last_reply_timestamp,
+													  wal_sender_timeout / 2);
+				if (GetCurrentTimestamp() >= timeout)
+				{
+					WalSndKeepalive(true);
+					ping_sent = true;
+					wakeEvents |= WL_SOCKET_WRITEABLE;
+					/* Try to flush pending output to the client */
+					if (pq_flush_if_writable() != 0)
+						break;
+				}
+			}
+
+			sleeptime = 1 + (wal_sender_timeout / 10);
+		}
+
+		ImmediateInterruptOK = true;
+		CHECK_FOR_INTERRUPTS();
+		WaitLatchOrSocket(&MyWalSnd->latch, wakeEvents,
+						  MyProcPort->sock, sleeptime);
+		ImmediateInterruptOK = false;
+
+		/*
+		 * The equivalent code in WalSndLoop checks here that replication
+		 * timeout hasn't been exceeded.  We don't do that here.   XXX explain
+		 * why.
+		 */
+	}
+
+	/* reactivate latch so WalSndLoop knows to continue */
+	SetLatch(&MyWalSnd->latch);
+	return flushptr;
+}
+
+/*
  * Execute an incoming replication command.
  */
 void
@@ -721,6 +1198,12 @@ exec_replication_command(const char *cmd_string)
 	MemoryContext cmd_context;
 	MemoryContext old_context;
 
+	/*
+	 * INIT_LOGICAL_REPLICATION exports a snapshot until the next command
+	 * arrives. Clean up the old stuff if there's anything.
+	 */
+	SnapBuildClearExportedSnapshot();
+
 	elog(DEBUG1, "received replication command: %s", cmd_string);
 
 	CHECK_FOR_INTERRUPTS();
@@ -766,7 +1249,7 @@ exec_replication_command(const char *cmd_string)
 				if (cmd->kind == REPLICATION_KIND_PHYSICAL)
 					StartReplication(cmd);
 				else
-					elog(ERROR, "cannot handle changeset extraction yet");
+					StartLogicalReplication(cmd);
 				break;
 			}
 
@@ -1017,7 +1500,7 @@ ProcessStandbyReplyMessage(void)
 	if (MyReplicationSlot && flushPtr != InvalidXLogRecPtr)
 	{
 		if (MyReplicationSlot->data.database != InvalidOid)
-			elog(ERROR, "cannot handle changeset extraction yet");
+			LogicalConfirmReceivedLocation(flushPtr);
 		else
 			PhysicalConfirmReceivedLocation(flushPtr);
 	}
@@ -1145,10 +1628,8 @@ ProcessStandbyHSFeedbackMessage(void)
 
 /* Main loop of walsender process that streams the WAL over Copy messages. */
 static void
-WalSndLoop(void)
+WalSndLoop(WalSndSendData send_data)
 {
-	bool		caughtup = false;
-
 	/*
 	 * Allocate buffers that will be used for each outgoing and incoming
 	 * message.  We do this just once to reduce palloc overhead.
@@ -1200,21 +1681,21 @@ WalSndLoop(void)
 
 		/*
 		 * If we don't have any pending data in the output buffer, try to send
-		 * some more.  If there is some, we don't bother to call XLogSend
+		 * some more.  If there is some, we don't bother to call send_data
 		 * again until we've flushed it ... but we'd better assume we are not
 		 * caught up.
 		 */
 		if (!pq_is_send_pending())
-			XLogSend(&caughtup);
+			send_data();
 		else
-			caughtup = false;
+			WalSndCaughtUp = false;
 
 		/* Try to flush pending output to the client */
 		if (pq_flush_if_writable() != 0)
 			goto send_failure;
 
 		/* If nothing remains to be sent right now ... */
-		if (caughtup && !pq_is_send_pending())
+		if (WalSndCaughtUp && !pq_is_send_pending())
 		{
 			/*
 			 * If we're in catchup state, move to streaming.  This is an
@@ -1240,29 +1721,17 @@ WalSndLoop(void)
 			 * the walsender is not sure which.
 			 */
 			if (walsender_ready_to_stop)
-			{
-				/* ... let's just be real sure we're caught up ... */
-				XLogSend(&caughtup);
-				if (caughtup && sentPtr == MyWalSnd->flush &&
-					!pq_is_send_pending())
-				{
-					/* Inform the standby that XLOG streaming is done */
-					EndCommand("COPY 0", DestRemote);
-					pq_flush();
-
-					proc_exit(0);
-				}
-			}
+				WalSndDone(send_data);
 		}
 
 		/*
 		 * We don't block if not caught up, unless there is unsent data
 		 * pending in which case we'd better block until the socket is
-		 * write-ready.  This test is only needed for the case where XLogSend
+		 * write-ready.  This test is only needed for the case where send_data
 		 * loaded a subset of the available data but then pq_flush_if_writable
 		 * flushed it all --- we should immediately try to send more.
 		 */
-		if ((caughtup && !streamingDoneSending) || pq_is_send_pending())
+		if ((WalSndCaughtUp && !streamingDoneSending) || pq_is_send_pending())
 		{
 			TimestampTz timeout = 0;
 			long		sleeptime = 10000;		/* 10 s */
@@ -1597,15 +2066,17 @@ retry:
 }
 
 /*
+ * Send out the WAL in its normal physical/stored form.
+ *
  * Read up to MAX_SEND_SIZE bytes of WAL that's been flushed to disk,
  * but not yet sent to the client, and buffer it in the libpq output
  * buffer.
  *
- * If there is no unsent WAL remaining, *caughtup is set to true, otherwise
- * *caughtup is set to false.
+ * If there is no unsent WAL remaining, WalSndCaughtUp is set to true,
+ * otherwise WalSndCaughtUp is set to false.
  */
 static void
-XLogSend(bool *caughtup)
+XLogSendPhysical(void)
 {
 	XLogRecPtr	SendRqstPtr;
 	XLogRecPtr	startptr;
@@ -1614,7 +2085,7 @@ XLogSend(bool *caughtup)
 
 	if (streamingDoneSending)
 	{
-		*caughtup = true;
+		WalSndCaughtUp = true;
 		return;
 	}
 
@@ -1731,7 +2202,7 @@ XLogSend(bool *caughtup)
 		pq_putmessage_noblock('c', NULL, 0);
 		streamingDoneSending = true;
 
-		*caughtup = true;
+		WalSndCaughtUp = true;
 
 		elog(DEBUG1, "walsender reached end of timeline at %X/%X (sent up to %X/%X)",
 			 (uint32) (sendTimeLineValidUpto >> 32), (uint32) sendTimeLineValidUpto,
@@ -1743,7 +2214,7 @@ XLogSend(bool *caughtup)
 	Assert(sentPtr <= SendRqstPtr);
 	if (SendRqstPtr <= sentPtr)
 	{
-		*caughtup = true;
+		WalSndCaughtUp = true;
 		return;
 	}
 
@@ -1767,15 +2238,15 @@ XLogSend(bool *caughtup)
 	{
 		endptr = SendRqstPtr;
 		if (sendTimeLineIsHistoric)
-			*caughtup = false;
+			WalSndCaughtUp = false;
 		else
-			*caughtup = true;
+			WalSndCaughtUp = true;
 	}
 	else
 	{
 		/* round down to page boundary. */
 		endptr -= (endptr % XLOG_BLCKSZ);
-		*caughtup = false;
+		WalSndCaughtUp = false;
 	}
 
 	nbytes = endptr - startptr;
@@ -1836,6 +2307,85 @@ XLogSend(bool *caughtup)
 }
 
 /*
+ * Send out the WAL after it being decoded into a logical format by the output
+ * plugin specified in INIT_LOGICAL_DECODING
+ */
+static void
+XLogSendLogical(void)
+{
+	XLogRecord *record;
+	char	   *errm;
+
+	/*
+	 * Don't know whether we've caught up yet. We'll set it to true in
+	 * WalSndWaitForWal, if we're actually waiting. We also set to true if
+	 * XLogReadRecord() had to stop reading but WalSndWaitForWal didn't wait -
+	 * i.e. when we're shutting down.
+	 */
+	WalSndCaughtUp = false;
+
+	record = XLogReadRecord(logical_decoding_ctx->reader, logical_startptr, &errm);
+	logical_startptr = InvalidXLogRecPtr;
+
+	/* xlog record was invalid */
+	if (errm != NULL)
+		elog(ERROR, "%s", errm);
+
+	if (record != NULL)
+	{
+		LogicalDecodingProcessRecord(logical_decoding_ctx, record);
+
+		sentPtr = logical_decoding_ctx->reader->EndRecPtr;
+	}
+	else
+	{
+		/*
+		 * If the record we just wanted read is at or beyond the flushed point,
+		 * then we're caught up.
+		 */
+		if (logical_decoding_ctx->reader->EndRecPtr >= GetFlushRecPtr())
+			WalSndCaughtUp = true;
+	}
+
+	/* Update shared memory status */
+	{
+		/* use volatile pointer to prevent code rearrangement */
+		volatile WalSnd *walsnd = MyWalSnd;
+
+		SpinLockAcquire(&walsnd->mutex);
+		walsnd->sentPtr = sentPtr;
+		SpinLockRelease(&walsnd->mutex);
+	}
+}
+
+/*
+ * The sender is caught up, so we can go away for shutdown processing
+ * to finish normally.  (This should only be called when the shutdown
+ * signal has been received from postmaster.)
+ *
+ * Note that if while doing this we determine that there's still more
+ * data to send, this function will return control to the caller.
+ */
+static void
+WalSndDone(WalSndSendData send_data)
+{
+	/* ... let's just be real sure we're caught up ... */
+	send_data();
+
+	if (WalSndCaughtUp && sentPtr == MyWalSnd->flush &&
+		!pq_is_send_pending())
+	{
+		/* Inform the standby that XLOG streaming is done */
+		EndCommand("COPY 0", DestRemote);
+		pq_flush();
+
+		proc_exit(0);
+	}
+	if (!ping_sent)
+		WalSndKeepalive(true);
+}
+
+/*
  * Returns the latest point in WAL that has been safely flushed to disk, and
  * can be sent to the standby. This should only be called when in recovery,
  * ie. we're streaming to a cascaded standby.
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 3ecc4d3..2a57ed3 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -742,7 +742,12 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 			ereport(FATAL,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 					 errmsg("must be superuser or replication role to start walsender")));
+	}
 
+	if (am_walsender &&
+		(in_dbname == NULL || in_dbname[0] == '\0') &&
+		dboid == InvalidOid)
+	{
 		/* process any options passed in the startup packet */
 		if (MyProcPort != NULL)
 			process_startup_options(MyProcPort, am_superuser);
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index 9d13d57..6100ed0 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -1367,11 +1367,11 @@ BaseBackup(void)
 				progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
 		disconnect_and_exit(1);
 	}
-	if (PQntuples(res) != 1 || PQnfields(res) != 3)
+	if (PQntuples(res) != 1 || PQnfields(res) < 3)
 	{
 		fprintf(stderr,
-				_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-				progname, PQntuples(res), PQnfields(res), 1, 3);
+				_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+				progname, PQntuples(res), PQnfields(res));
 		disconnect_and_exit(1);
 	}
 	sysidentifier = pg_strdup(PQgetvalue(res, 0, 0));
diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c
index 8a702e3..26d0e23 100644
--- a/src/bin/pg_basebackup/pg_receivexlog.c
+++ b/src/bin/pg_basebackup/pg_receivexlog.c
@@ -268,11 +268,11 @@ StreamLog(void)
 				progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
 		disconnect_and_exit(1);
 	}
-	if (PQntuples(res) != 1 || PQnfields(res) != 3)
+	if (PQntuples(res) != 1 || PQnfields(res) < 3)
 	{
 		fprintf(stderr,
-				_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-				progname, PQntuples(res), PQnfields(res), 1, 3);
+				_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+				progname, PQntuples(res), PQnfields(res));
 		disconnect_and_exit(1);
 	}
 	servertli = atoi(PQgetvalue(res, 0, 1));
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index ef73b4b..64730d9 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -563,11 +563,11 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 			PQclear(res);
 			return false;
 		}
-		if (PQnfields(res) != 3 || PQntuples(res) != 1)
+		if (PQntuples(res) != 1 || PQnfields(res) < 3)
 		{
 			fprintf(stderr,
-					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-					progname, PQntuples(res), PQnfields(res), 1, 3);
+					_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+					progname, PQntuples(res), PQnfields(res));
 			PQclear(res);
 			return false;
 		}
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
index b67cf63..cff2be6 100644
--- a/src/include/replication/walsender.h
+++ b/src/include/replication/walsender.h
@@ -19,6 +19,7 @@
 /* global state */
 extern bool am_walsender;
 extern bool am_cascading_walsender;
+extern bool am_db_walsender;
 extern bool wake_wal_senders;
 
 /* user-settable parameters */
diff --git a/src/include/replication/walsender_private.h b/src/include/replication/walsender_private.h
index dff3354..c38d08d 100644
--- a/src/include/replication/walsender_private.h
+++ b/src/include/replication/walsender_private.h
@@ -108,4 +108,7 @@ extern void replication_scanner_finish(void);
 
 extern Node *replication_parse_result;
 
+/* logical wal sender data gathering functions */
+extern XLogRecPtr WalSndWaitForWal(XLogRecPtr loc);
+
 #endif   /* _WALSENDER_PRIVATE_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index f960454..69eeac5 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1909,6 +1909,7 @@ WalRcvData
 WalRcvState
 WalSnd
 WalSndCtlData
+WalSndSendData
 WalSndState
 WholeRowVarExprState
 WindowAgg
-- 
1.8.5.rc2.dirty

0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patchtext/x-patch; charset=us-asciiDownload
>From 1835a84720d568a948085dfb348f615d326ffcf3 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 27 Jan 2014 17:13:49 +0100
Subject: [PATCH 3/5] wal_decoding: pg_recvlogical: Introduce pg_receivexlog
 equivalent for logical changes

---
 src/bin/pg_basebackup/.gitignore       |   2 +
 src/bin/pg_basebackup/Makefile         |  11 +-
 src/bin/pg_basebackup/pg_recvlogical.c | 871 +++++++++++++++++++++++++++++++++
 src/bin/pg_basebackup/receivelog.c     | 139 +-----
 src/bin/pg_basebackup/receivelog.h     |   2 +
 src/bin/pg_basebackup/streamutil.c     | 123 ++++-
 src/bin/pg_basebackup/streamutil.h     |  10 +
 7 files changed, 1033 insertions(+), 125 deletions(-)
 create mode 100644 src/bin/pg_basebackup/pg_recvlogical.c

diff --git a/src/bin/pg_basebackup/.gitignore b/src/bin/pg_basebackup/.gitignore
index 1334a1f..3bd45f4 100644
--- a/src/bin/pg_basebackup/.gitignore
+++ b/src/bin/pg_basebackup/.gitignore
@@ -1,2 +1,4 @@
 /pg_basebackup
 /pg_receivexlog
+/pg_receivellog
+/pg_recvlogical
diff --git a/src/bin/pg_basebackup/Makefile b/src/bin/pg_basebackup/Makefile
index 17c91af..346560e 100644
--- a/src/bin/pg_basebackup/Makefile
+++ b/src/bin/pg_basebackup/Makefile
@@ -20,7 +20,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
 
 OBJS=receivelog.o streamutil.o $(WIN32RES)
 
-all: pg_basebackup pg_receivexlog
+all: pg_basebackup pg_receivexlog pg_recvlogical
 
 pg_basebackup: pg_basebackup.o $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_basebackup.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
@@ -28,9 +28,13 @@ pg_basebackup: pg_basebackup.o $(OBJS) | submake-libpq submake-libpgport
 pg_receivexlog: pg_receivexlog.o $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_receivexlog.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
+pg_recvlogical: pg_recvlogical.o $(OBJS) | submake-libpq submake-libpgport
+	$(CC) $(CFLAGS) pg_recvlogical.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+
 install: all installdirs
 	$(INSTALL_PROGRAM) pg_basebackup$(X) '$(DESTDIR)$(bindir)/pg_basebackup$(X)'
 	$(INSTALL_PROGRAM) pg_receivexlog$(X) '$(DESTDIR)$(bindir)/pg_receivexlog$(X)'
+	$(INSTALL_PROGRAM) pg_recvlogical$(X) '$(DESTDIR)$(bindir)/pg_recvlogical$(X)'
 
 installdirs:
 	$(MKDIR_P) '$(DESTDIR)$(bindir)'
@@ -38,6 +42,9 @@ installdirs:
 uninstall:
 	rm -f '$(DESTDIR)$(bindir)/pg_basebackup$(X)'
 	rm -f '$(DESTDIR)$(bindir)/pg_receivexlog$(X)'
+	rm -f '$(DESTDIR)$(bindir)/pg_recvlogical$(X)'
 
 clean distclean maintainer-clean:
-	rm -f pg_basebackup$(X) pg_receivexlog$(X) $(OBJS) pg_basebackup.o pg_receivexlog.o
+	rm -f pg_basebackup$(X) pg_receivexlog$(X) pg_recvlogical$(X) \
+		pg_basebackup.o pg_receivexlog.o pg_recvlogical.o \
+		$(OBJS)
diff --git a/src/bin/pg_basebackup/pg_recvlogical.c b/src/bin/pg_basebackup/pg_recvlogical.c
new file mode 100644
index 0000000..76a8960
--- /dev/null
+++ b/src/bin/pg_basebackup/pg_recvlogical.c
@@ -0,0 +1,871 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_recvlogical.c - receive streaming logical log data and write it
+ *					  to a local file.
+ *
+ * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		  src/bin/pg_basebackup/pg_recvlogical.c
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include "streamutil.h"
+
+#include "getopt_long.h"
+
+#include "libpq-fe.h"
+#include "libpq/pqsignal.h"
+
+#include "access/xlog_internal.h"
+#include "common/fe_memutils.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Time to sleep between reconnection attempts */
+#define RECONNECT_SLEEP_TIME 5
+
+/* Global Options */
+static char    *outfile = NULL;
+static int		verbose = 0;
+static int		noloop = 0;
+static int		standby_message_timeout = 10 * 1000;		/* 10 sec = default */
+static XLogRecPtr startpos = InvalidXLogRecPtr;
+static bool		do_create_slot = false;
+static bool		do_start_slot = false;
+static bool		do_drop_slot = false;
+
+/* filled pairwise with option, value. value may be NULL */
+static char	  **options;
+static size_t	noptions = 0;
+static const char *plugin = "test_decoding";
+
+/* Global State */
+static int		outfd = -1;
+static volatile bool time_to_abort = false;
+
+static void usage(void);
+static void StreamLog();
+
+static void
+usage(void)
+{
+	printf(_("%s receives PostgreSQL logical change stream.\n\n"),
+		   progname);
+	printf(_("Usage:\n"));
+	printf(_("  %s [OPTION]...\n"), progname);
+	printf(_("\nOptions:\n"));
+	printf(_("  -f, --file=FILE        receive log into this file. - for stdout\n"));
+	printf(_("  -n, --no-loop          do not loop on connection lost\n"));
+	printf(_("  -v, --verbose          output verbose messages\n"));
+	printf(_("  -V, --version          output version information, then exit\n"));
+	printf(_("  -?, --help             show this help, then exit\n"));
+	printf(_("\nConnection options:\n"));
+	printf(_("  -d, --dbname=DBNAME    database to connect to\n"));
+	printf(_("  -h, --host=HOSTNAME    database server host or socket directory\n"));
+	printf(_("  -p, --port=PORT        database server port number\n"));
+	printf(_("  -U, --username=NAME    connect as specified database user\n"));
+	printf(_("  -w, --no-password      never prompt for password\n"));
+	printf(_("  -W, --password         force password prompt (should happen automatically)\n"));
+	printf(_("\nReplication options:\n"));
+	printf(_("  -o, --option=NAME[=VALUE]\n"
+			 "                         Specify option NAME with optional value VAL, to be passed\n"
+			 "                         to the output plugin\n"));
+	printf(_("  -P, --plugin=PLUGIN    use output plugin PLUGIN (defaults to test_decoding)\n"));
+	printf(_("  -s, --status-interval=INTERVAL\n"
+			 "                         time between status packets sent to server (in seconds)\n"));
+	printf(_("  -S, --slot=SLOT        use existing replication slot SLOT instead of starting a new one\n"));
+	printf(_("  -I, --startpos=PTR     Where in an existing slot should the streaming start"));
+	printf(_("\nAction to be performed:\n"));
+	printf(_("      --create           create a new replication slot (for the slotname see --slot)\n"));
+	printf(_("      --start            start streaming in a replication slot (for the slotname see --slot)\n"));
+	printf(_("      --drop             drop the replication slot (for the slotname see --slot)\n"));
+	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
+}
+
+/*
+ * Send a Standby Status Update message to server.
+ */
+static bool
+sendFeedback(PGconn *conn, XLogRecPtr blockpos, int64 now, bool force, bool replyRequested)
+{
+	char		replybuf[1 + 8 + 8 + 8 + 8 + 1];
+	int			len = 0;
+
+	/*
+	 * we normally don't want to send superflous feedbacks, but if
+	 * it's because of a timeout we need to, otherwise
+	 * replication_timeout will kill us.
+	 */
+	if (blockpos == startpos && !force)
+		return true;
+
+	if (verbose)
+		fprintf(stderr,
+				_("%s: confirming flush up to %X/%X (slot %s)\n"),
+				progname, (uint32) (blockpos >> 32), (uint32) blockpos,
+				replication_slot);
+
+	replybuf[len] = 'r';
+	len += 1;
+	fe_sendint64(blockpos, &replybuf[len]);		/* write */
+	len += 8;
+	fe_sendint64(blockpos, &replybuf[len]);		/* flush */
+	len += 8;
+	fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
+	len += 8;
+	fe_sendint64(now, &replybuf[len]);		/* sendTime */
+	len += 8;
+	replybuf[len] = replyRequested ? 1 : 0;		/* replyRequested */
+	len += 1;
+
+	startpos = blockpos;
+
+	if (PQputCopyData(conn, replybuf, len) <= 0 || PQflush(conn))
+	{
+		fprintf(stderr, _("%s: could not send feedback packet: %s"),
+				progname, PQerrorMessage(conn));
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * Start the log streaming
+ */
+static void
+StreamLog(void)
+{
+	PGresult   *res;
+	char		query[512];
+	char	   *copybuf = NULL;
+	int64		last_status = -1;
+	XLogRecPtr	logoff = InvalidXLogRecPtr;
+	int			written;
+	int			i;
+
+	/*
+	 * Connect in replication mode to the server
+	 */
+	if (!conn)
+		conn = GetConnection();
+	if (!conn)
+		/* Error message already written in GetConnection() */
+		return;
+
+	/*
+	 * Start the replication
+	 */
+	if (verbose)
+		fprintf(stderr,
+				_("%s: starting log streaming at %X/%X (slot %s)\n"),
+				progname, (uint32) (startpos >> 32), (uint32) startpos,
+				replication_slot);
+
+	/* Initiate the replication stream at specified location */
+	written = snprintf(query, sizeof(query), "START_REPLICATION SLOT \"%s\" LOGICAL %X/%X",
+			 replication_slot, (uint32) (startpos >> 32), (uint32) startpos);
+
+	/*
+	 * add options to string, if present
+	 * Oh, if we just had stringinfo in src/common...
+	 */
+	if (noptions)
+		written += snprintf(query + written, sizeof(query) - written, " (");
+
+	for (i = 0; i < noptions; i++)
+	{
+		/* separator */
+		if (i > 0)
+			written += snprintf(query + written, sizeof(query) - written, ", ");
+
+		/* write option name */
+		written += snprintf(query + written, sizeof(query) - written, "\"%s\"",
+							options[(i * 2)]);
+
+		if (written >= sizeof(query) - 1)
+		{
+			fprintf(stderr, _("%s: option string too long\n"), progname);
+			exit(1); /* no point in retrying, fatal error */
+		}
+
+		/* write option name if specified */
+		if (options[(i * 2) + 1] != NULL)
+		{
+			written += snprintf(query + written, sizeof(query) - written, " '%s'",
+								options[(i * 2) + 1]);
+
+			if (written >= sizeof(query) - 1)
+			{
+				fprintf(stderr, _("%s: option string too long\n"), progname);
+				exit(1); /* no point in retrying, fatal error */
+			}
+		}
+	}
+
+	if (noptions)
+	{
+		written += snprintf(query + written, sizeof(query) - written, ")");
+		if (written >= sizeof(query) - 1)
+		{
+			fprintf(stderr, _("%s: option string too long\n"), progname);
+			exit(1); /* no point in retrying, fatal error */
+		}
+	}
+
+	res = PQexec(conn, query);
+	if (PQresultStatus(res) != PGRES_COPY_BOTH)
+	{
+		fprintf(stderr, _("%s: could not send replication command \"%s\": %s\n"),
+				progname, query, PQresultErrorMessage(res));
+		PQclear(res);
+		goto error;
+	}
+	PQclear(res);
+
+	if (verbose)
+		fprintf(stderr,
+				_("%s: initiated streaming\n"),
+				progname);
+
+	while (!time_to_abort)
+	{
+		int			r;
+		int			bytes_left;
+		int			bytes_written;
+		int64		now;
+		int			hdr_len;
+
+		if (copybuf != NULL)
+		{
+			PQfreemem(copybuf);
+			copybuf = NULL;
+		}
+
+		/*
+		 * Potentially send a status message to the master
+		 */
+		now = feGetCurrentTimestamp();
+		if (standby_message_timeout > 0 &&
+			feTimestampDifferenceExceeds(last_status, now,
+										 standby_message_timeout))
+		{
+			/* Time to send feedback! */
+			if (!sendFeedback(conn, logoff, now, true, false))
+				goto error;
+
+			last_status = now;
+		}
+
+		r = PQgetCopyData(conn, &copybuf, 1);
+		if (r == 0)
+		{
+			/*
+			 * In async mode, and no data available. We block on reading but
+			 * not more than the specified timeout, so that we can send a
+			 * response back to the client.
+			 */
+			fd_set		input_mask;
+			struct timeval timeout;
+			struct timeval *timeoutptr;
+
+
+			{
+				now = feGetCurrentTimestamp();
+				if (!sendFeedback(conn, logoff, now, false, false))
+					goto error;
+			}
+
+			FD_ZERO(&input_mask);
+			FD_SET(PQsocket(conn), &input_mask);
+			if (standby_message_timeout)
+			{
+				int64		targettime;
+				long		secs;
+				int			usecs;
+
+				targettime = last_status + (standby_message_timeout - 1) *
+					((int64) 1000);
+				feTimestampDifference(now,
+									  targettime,
+									  &secs,
+									  &usecs);
+				if (secs <= 0)
+					timeout.tv_sec = 1; /* Always sleep at least 1 sec */
+				else
+					timeout.tv_sec = secs;
+				timeout.tv_usec = usecs;
+				timeoutptr = &timeout;
+			}
+			else
+				timeoutptr = NULL;
+
+			r = select(PQsocket(conn) + 1, &input_mask, NULL, NULL, timeoutptr);
+			if (r == 0 || (r < 0 && errno == EINTR))
+			{
+				/*
+				 * Got a timeout or signal. Continue the loop and either
+				 * deliver a status packet to the server or just go back into
+				 * blocking.
+				 */
+				continue;
+			}
+			else if (r < 0)
+			{
+				fprintf(stderr, _("%s: select() failed: %s\n"),
+						progname, strerror(errno));
+				goto error;
+			}
+			/* Else there is actually data on the socket */
+			if (PQconsumeInput(conn) == 0)
+			{
+				fprintf(stderr,
+						_("%s: could not receive data from WAL stream: %s"),
+						progname, PQerrorMessage(conn));
+				goto error;
+			}
+			continue;
+		}
+		if (r == -1)
+			/* End of copy stream */
+			break;
+		if (r == -2)
+		{
+			fprintf(stderr, _("%s: could not read COPY data: %s"),
+					progname, PQerrorMessage(conn));
+			goto error;
+		}
+
+		/* Check the message type. */
+		if (copybuf[0] == 'k')
+		{
+			int			pos;
+			bool		replyRequested;
+			XLogRecPtr	walEnd;
+
+			/*
+			 * Parse the keepalive message, enclosed in the CopyData message.
+			 * We just check if the server requested a reply, and ignore the
+			 * rest.
+			 */
+			pos = 1;			/* skip msgtype 'k' */
+			walEnd = fe_recvint64(&copybuf[pos]);
+			logoff = Max(walEnd, logoff);
+
+			pos += 8;			/* read walEnd */
+
+			pos += 8;			/* skip sendTime */
+
+			if (r < pos + 1)
+			{
+				fprintf(stderr, _("%s: streaming header too small: %d\n"),
+						progname, r);
+				goto error;
+			}
+			replyRequested = copybuf[pos];
+
+			/* If the server requested an immediate reply, send one. */
+			if (replyRequested)
+			{
+				now = feGetCurrentTimestamp();
+				if (!sendFeedback(conn, logoff, now, false, false))
+					goto error;
+				last_status = now;
+			}
+			continue;
+		}
+		else if (copybuf[0] != 'w')
+		{
+			fprintf(stderr, _("%s: unrecognized streaming header: \"%c\"\n"),
+					progname, copybuf[0]);
+			goto error;
+		}
+
+
+		/*
+		 * Read the header of the XLogData message, enclosed in the CopyData
+		 * message. We only need the WAL location field (dataStart), the rest
+		 * of the header is ignored.
+		 */
+		hdr_len = 1;			/* msgtype 'w' */
+		hdr_len += 8;			/* dataStart */
+		hdr_len += 8;			/* walEnd */
+		hdr_len += 8;			/* sendTime */
+		if (r < hdr_len + 1)
+		{
+			fprintf(stderr, _("%s: streaming header too small: %d\n"),
+					progname, r);
+			goto error;
+		}
+
+		/* Extract WAL location for this block */
+		{
+			XLogRecPtr	temp = fe_recvint64(&copybuf[1]);
+
+			logoff = Max(temp, logoff);
+		}
+
+		if (outfd == -1 && strcmp(outfile, "-") == 0)
+		{
+			outfd = fileno(stdout);
+		}
+		else if (outfd == -1)
+		{
+			outfd = open(outfile, O_CREAT | O_APPEND | O_WRONLY | PG_BINARY,
+						 S_IRUSR | S_IWUSR);
+			if (outfd == -1)
+			{
+				fprintf(stderr,
+						_("%s: could not open log file \"%s\": %s\n"),
+						progname, outfile, strerror(errno));
+				goto error;
+			}
+		}
+
+		bytes_left = r - hdr_len;
+		bytes_written = 0;
+
+
+		while (bytes_left)
+		{
+			int			ret;
+
+			ret = write(outfd,
+						copybuf + hdr_len + bytes_written,
+						bytes_left);
+
+			if (ret < 0)
+			{
+				fprintf(stderr,
+				  _("%s: could not write %u bytes to log file \"%s\": %s\n"),
+						progname, bytes_left, outfile,
+						strerror(errno));
+				goto error;
+			}
+
+			/* Write was successful, advance our position */
+			bytes_written += ret;
+			bytes_left -= ret;
+		}
+
+		if (write(outfd, "\n", 1) != 1)
+		{
+			fprintf(stderr,
+				  _("%s: could not write %u bytes to log file \"%s\": %s\n"),
+					progname, 1, outfile,
+					strerror(errno));
+			goto error;
+		}
+	}
+
+	res = PQgetResult(conn);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
+	{
+		fprintf(stderr,
+				_("%s: unexpected termination of replication stream: %s"),
+				progname, PQresultErrorMessage(res));
+		goto error;
+	}
+	PQclear(res);
+
+	if (copybuf != NULL)
+		PQfreemem(copybuf);
+
+	if (outfd != -1 && close(outfd) != 0)
+		fprintf(stderr, _("%s: could not close file \"%s\": %s\n"),
+				progname, outfile, strerror(errno));
+	outfd = -1;
+error:
+	PQfinish(conn);
+	conn = NULL;
+}
+
+/*
+ * When sigint is called, just tell the system to exit at the next possible
+ * moment.
+ */
+#ifndef WIN32
+
+static void
+sigint_handler(int signum)
+{
+	time_to_abort = true;
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+	PGresult   *res;
+	static struct option long_options[] = {
+/* general options */
+		{"file", required_argument, NULL, 'f'},
+		{"no-loop", no_argument, NULL, 'n'},
+		{"verbose", no_argument, NULL, 'v'},
+		{"version", no_argument, NULL, 'V'},
+		{"help", no_argument, NULL, '?'},
+/* connnection options */
+		{"dbname", required_argument, NULL, 'd'},
+		{"host", required_argument, NULL, 'h'},
+		{"port", required_argument, NULL, 'p'},
+		{"username", required_argument, NULL, 'U'},
+		{"no-password", no_argument, NULL, 'w'},
+		{"password", no_argument, NULL, 'W'},
+/* replication options */
+		{"option", required_argument, NULL, 'o'},
+		{"plugin", required_argument, NULL, 'P'},
+		{"status-interval", required_argument, NULL, 's'},
+		{"slot", required_argument, NULL, 'S'},
+		{"startpos", required_argument, NULL, 'I'},
+/* action */
+		{"create", no_argument, NULL, 1},
+		{"start", no_argument, NULL, 2},
+		{"drop", no_argument, NULL, 3},
+		{NULL, 0, NULL, 0}
+	};
+	int			c;
+	int			option_index;
+	uint32		hi,
+				lo;
+
+	progname = get_progname(argv[0]);
+	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_recvlogical"));
+
+	if (argc > 1)
+	{
+		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
+		{
+			usage();
+			exit(0);
+		}
+		else if (strcmp(argv[1], "-V") == 0 ||
+				 strcmp(argv[1], "--version") == 0)
+		{
+			puts("pg_recvlogical (PostgreSQL) " PG_VERSION);
+			exit(0);
+		}
+	}
+
+	while ((c = getopt_long(argc, argv, "f:nvd:h:o:p:U:wWP:s:S:",
+							long_options, &option_index)) != -1)
+	{
+		switch (c)
+		{
+/* general options */
+			case 'f':
+				outfile = pg_strdup(optarg);
+				break;
+			case 'n':
+				noloop = 1;
+				break;
+			case 'v':
+				verbose++;
+				break;
+/* connnection options */
+			case 'd':
+				dbname = pg_strdup(optarg);
+				break;
+			case 'h':
+				dbhost = pg_strdup(optarg);
+				break;
+			case 'p':
+				if (atoi(optarg) <= 0)
+				{
+					fprintf(stderr, _("%s: invalid port number \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				dbport = pg_strdup(optarg);
+				break;
+			case 'U':
+				dbuser = pg_strdup(optarg);
+				break;
+			case 'w':
+				dbgetpassword = -1;
+				break;
+			case 'W':
+				dbgetpassword = 1;
+				break;
+/* replication options */
+			case 'o':
+				{
+					char *data = pg_strdup(optarg);
+					char *val = strchr(data, '=');
+
+					if (val != NULL)
+					{
+						/* remove =; separate data from val */
+						*val = '\0';
+						val++;
+					}
+
+					noptions += 1;
+					options = pg_realloc(options, sizeof(char*) * noptions * 2);
+
+					options[(noptions - 1) * 2] = data;
+					options[(noptions - 1) * 2 + 1] = val;
+				}
+
+				break;
+			case 'P':
+				plugin = pg_strdup(optarg);
+				break;
+			case 's':
+				standby_message_timeout = atoi(optarg) * 1000;
+				if (standby_message_timeout < 0)
+				{
+					fprintf(stderr, _("%s: invalid status interval \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				break;
+			case 'S':
+				replication_slot = pg_strdup(optarg);
+				break;
+			case 'I':
+				if (sscanf(optarg, "%X/%X", &hi, &lo) != 2)
+				{
+					fprintf(stderr,
+							_("%s: could not parse start position \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				startpos = ((uint64) hi) << 32 | lo;
+				break;
+/* action */
+			case 1:
+				do_create_slot = true;
+				break;
+			case 2:
+				do_start_slot = true;
+				break;
+			case 3:
+				do_drop_slot = true;
+				break;
+
+			default:
+
+				/*
+				 * getopt_long already emitted a complaint
+				 */
+				fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+						progname);
+				exit(1);
+		}
+	}
+
+	/*
+	 * Any non-option arguments?
+	 */
+	if (optind < argc)
+	{
+		fprintf(stderr,
+				_("%s: too many command-line arguments (first is \"%s\")\n"),
+				progname, argv[optind]);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	/*
+	 * Required arguments
+	 */
+	if (replication_slot == NULL)
+	{
+		fprintf(stderr, _("%s: no slot specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (do_start_slot && outfile == NULL)
+	{
+		fprintf(stderr, _("%s: no target file specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (!do_drop_slot && dbname == NULL)
+	{
+		fprintf(stderr, _("%s: no database specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (!do_drop_slot && !do_create_slot && !do_start_slot)
+	{
+		fprintf(stderr, _("%s: at least one action needs to be specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (do_drop_slot && (do_create_slot || do_start_slot))
+	{
+		fprintf(stderr, _("%s: --stop cannot be combined with --init or --start\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (startpos && (do_create_slot || do_drop_slot))
+	{
+		fprintf(stderr, _("%s: --startpos cannot be combined with --init or --stop\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+#ifndef WIN32
+	pqsignal(SIGINT, sigint_handler);
+#endif
+
+	/*
+	 * don't really need this but it actually helps to get more precise error
+	 * messages about authentication, required GUCs and such without starting
+	 * to loop around connection attempts lateron.
+	 */
+	{
+		conn = GetConnection();
+		if (!conn)
+			/* Error message already written in GetConnection() */
+			exit(1);
+
+		/*
+		 * Run IDENTIFY_SYSTEM so we can get the timeline and current xlog
+		 * position.
+		 */
+		res = PQexec(conn, "IDENTIFY_SYSTEM");
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 1 || PQnfields(res) != 4)
+		{
+			fprintf(stderr,
+					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 4);
+			disconnect_and_exit(1);
+		}
+		PQclear(res);
+	}
+
+
+	/*
+	 * stop a replication slot
+	 */
+	if (do_drop_slot)
+	{
+		char		query[256];
+
+		if (verbose)
+			fprintf(stderr,
+					_("%s: freeing replication slot \"%s\"\n"),
+					progname, replication_slot);
+
+		snprintf(query, sizeof(query), "DROP_REPLICATION_SLOT \"%s\"",
+				 replication_slot);
+		res = PQexec(conn, query);
+		if (PQresultStatus(res) != PGRES_COMMAND_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, query, PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 0 || PQnfields(res) != 0)
+		{
+			fprintf(stderr,
+					_("%s: could not stop logical rep: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 0, 0);
+			disconnect_and_exit(1);
+		}
+
+		PQclear(res);
+		disconnect_and_exit(0);
+	}
+
+	/*
+	 * init a replication slot
+	 */
+	if (do_create_slot)
+	{
+		char		query[256];
+
+		if (verbose)
+			fprintf(stderr,
+					_("%s: initializing replication slot \"%s\"\n"),
+					progname, replication_slot);
+
+		snprintf(query, sizeof(query), "CREATE_REPLICATION_SLOT \"%s\" LOGICAL \"%s\"",
+				 replication_slot, plugin);
+
+		res = PQexec(conn, query);
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, query, PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 1 || PQnfields(res) != 4)
+		{
+			fprintf(stderr,
+					_("%s: could not init logical rep: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 4);
+			disconnect_and_exit(1);
+		}
+
+		if (sscanf(PQgetvalue(res, 0, 1), "%X/%X", &hi, &lo) != 2)
+		{
+			fprintf(stderr,
+					_("%s: could not parse log location \"%s\"\n"),
+					progname, PQgetvalue(res, 0, 1));
+			disconnect_and_exit(1);
+		}
+		startpos = ((uint64) hi) << 32 | lo;
+
+		replication_slot = strdup(PQgetvalue(res, 0, 0));
+		PQclear(res);
+	}
+
+
+	if (!do_start_slot)
+		disconnect_and_exit(0);
+
+	while (true)
+	{
+		StreamLog();
+		if (time_to_abort)
+		{
+			/*
+			 * We've been Ctrl-C'ed. That's not an error, so exit without an
+			 * errorcode.
+			 */
+			disconnect_and_exit(0);
+		}
+		else if (noloop)
+		{
+			fprintf(stderr, _("%s: disconnected.\n"), progname);
+			exit(1);
+		}
+		else
+		{
+			fprintf(stderr,
+			/* translator: check source for value for %d */
+					_("%s: disconnected. Waiting %d seconds to try again.\n"),
+					progname, RECONNECT_SLEEP_TIME);
+			pg_usleep(RECONNECT_SLEEP_TIME * 1000000);
+		}
+	}
+}
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index 64730d9..26343c9 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -11,21 +11,18 @@
  *		  src/bin/pg_basebackup/receivelog.c
  *-------------------------------------------------------------------------
  */
+
 #include "postgres_fe.h"
 
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-/* for ntohl/htonl */
-#include <netinet/in.h>
-#include <arpa/inet.h>
+/* local includes */
+#include "receivelog.h"
+#include "streamutil.h"
 
 #include "libpq-fe.h"
 #include "access/xlog_internal.h"
 
-#include "receivelog.h"
-#include "streamutil.h"
+#include <sys/stat.h>
+#include <unistd.h>
 
 
 /* fd and filename for currently open WAL file */
@@ -195,63 +192,6 @@ close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos)
 
 
 /*
- * Local version of GetCurrentTimestamp(), since we are not linked with
- * backend code. The protocol always uses integer timestamps, regardless of
- * server setting.
- */
-static int64
-localGetCurrentTimestamp(void)
-{
-	int64		result;
-	struct timeval tp;
-
-	gettimeofday(&tp, NULL);
-
-	result = (int64) tp.tv_sec -
-		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-
-	result = (result * USECS_PER_SEC) + tp.tv_usec;
-
-	return result;
-}
-
-/*
- * Local version of TimestampDifference(), since we are not linked with
- * backend code.
- */
-static void
-localTimestampDifference(int64 start_time, int64 stop_time,
-						 long *secs, int *microsecs)
-{
-	int64		diff = stop_time - start_time;
-
-	if (diff <= 0)
-	{
-		*secs = 0;
-		*microsecs = 0;
-	}
-	else
-	{
-		*secs = (long) (diff / USECS_PER_SEC);
-		*microsecs = (int) (diff % USECS_PER_SEC);
-	}
-}
-
-/*
- * Local version of TimestampDifferenceExceeds(), since we are not
- * linked with backend code.
- */
-static bool
-localTimestampDifferenceExceeds(int64 start_time,
-								int64 stop_time,
-								int msec)
-{
-	int64		diff = stop_time - start_time;
-
-	return (diff >= msec * INT64CONST(1000));
-}
-
-/*
  * Check if a timeline history file exists.
  */
 static bool
@@ -371,47 +311,6 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
 }
 
 /*
- * Converts an int64 to network byte order.
- */
-static void
-sendint64(int64 i, char *buf)
-{
-	uint32		n32;
-
-	/* High order half first, since we're doing MSB-first */
-	n32 = (uint32) (i >> 32);
-	n32 = htonl(n32);
-	memcpy(&buf[0], &n32, 4);
-
-	/* Now the low order half */
-	n32 = (uint32) i;
-	n32 = htonl(n32);
-	memcpy(&buf[4], &n32, 4);
-}
-
-/*
- * Converts an int64 from network byte order to native format.
- */
-static int64
-recvint64(char *buf)
-{
-	int64		result;
-	uint32		h32;
-	uint32		l32;
-
-	memcpy(&h32, buf, 4);
-	memcpy(&l32, buf + 4, 4);
-	h32 = ntohl(h32);
-	l32 = ntohl(l32);
-
-	result = h32;
-	result <<= 32;
-	result |= l32;
-
-	return result;
-}
-
-/*
  * Send a Standby Status Update message to server.
  */
 static bool
@@ -422,16 +321,16 @@ sendFeedback(PGconn *conn, XLogRecPtr blockpos, int64 now, bool replyRequested)
 
 	replybuf[len] = 'r';
 	len += 1;
-	sendint64(blockpos, &replybuf[len]);		/* write */
+	fe_sendint64(blockpos, &replybuf[len]);		/* write */
 	len += 8;
 	if (reportFlushPosition)
-		sendint64(lastFlushPosition, &replybuf[len]);		/* flush */
+		fe_sendint64(lastFlushPosition, &replybuf[len]);		/* flush */
 	else
-		sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
+		fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
 	len += 8;
-	sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
+	fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
 	len += 8;
-	sendint64(now, &replybuf[len]);		/* sendTime */
+	fe_sendint64(now, &replybuf[len]);		/* sendTime */
 	len += 8;
 	replybuf[len] = replyRequested ? 1 : 0;		/* replyRequested */
 	len += 1;
@@ -864,9 +763,9 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 		/*
 		 * Potentially send a status message to the master
 		 */
-		now = localGetCurrentTimestamp();
+		now = feGetCurrentTimestamp();
 		if (still_sending && standby_message_timeout > 0 &&
-			localTimestampDifferenceExceeds(last_status, now,
+			feTimestampDifferenceExceeds(last_status, now,
 											standby_message_timeout))
 		{
 			/* Time to send feedback! */
@@ -895,10 +794,10 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 				int			usecs;
 
 				targettime = last_status + (standby_message_timeout - 1) * ((int64) 1000);
-				localTimestampDifference(now,
-										 targettime,
-										 &secs,
-										 &usecs);
+				feTimestampDifference(now,
+									  targettime,
+									  &secs,
+									  &usecs);
 				if (secs <= 0)
 					timeout.tv_sec = 1; /* Always sleep at least 1 sec */
 				else
@@ -1002,7 +901,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 			/* If the server requested an immediate reply, send one. */
 			if (replyRequested && still_sending)
 			{
-				now = localGetCurrentTimestamp();
+				now = feGetCurrentTimestamp();
 				if (!sendFeedback(conn, blockpos, now, false))
 					goto error;
 				last_status = now;
@@ -1032,7 +931,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 						progname, r);
 				goto error;
 			}
-			blockpos = recvint64(&copybuf[1]);
+			blockpos = fe_recvint64(&copybuf[1]);
 
 			/* Extract WAL location for this block */
 			xlogoff = blockpos % XLOG_SEG_SIZE;
diff --git a/src/bin/pg_basebackup/receivelog.h b/src/bin/pg_basebackup/receivelog.h
index 7c983cd..f4789a5 100644
--- a/src/bin/pg_basebackup/receivelog.h
+++ b/src/bin/pg_basebackup/receivelog.h
@@ -1,3 +1,5 @@
+#include "libpq-fe.h"
+
 #include "access/xlogdefs.h"
 
 /*
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 041076f..441abbf 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -11,11 +11,28 @@
  *-------------------------------------------------------------------------
  */
 
-#include "postgres_fe.h"
+/*
+ * We have to use postgres.h not postgres_fe.h here, because there's
+ * backend-only stuff in the datetime include files we need.  But we need a
+ * frontend-ish environment otherwise. Hence this ugly hack.
+ */
+#define FRONTEND 1
+#include "postgres.h"
+
 #include "streamutil.h"
 
+#include "common/fe_memutils.h"
+#include "utils/datetime.h"
+
 #include <stdio.h>
 #include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* for ntohl/htonl */
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 const char *progname;
 char	   *connection_string = NULL;
@@ -23,6 +40,7 @@ char	   *dbhost = NULL;
 char	   *dbuser = NULL;
 char	   *dbport = NULL;
 char	   *replication_slot = NULL;
+char	   *dbname = NULL;
 int			dbgetpassword = 0;	/* 0=auto, -1=never, 1=always */
 static char *dbpassword = NULL;
 PGconn	   *conn = NULL;
@@ -87,10 +105,10 @@ GetConnection(void)
 	}
 
 	keywords[i] = "dbname";
-	values[i] = "replication";
+	values[i] = dbname == NULL ? "replication" : dbname;
 	i++;
 	keywords[i] = "replication";
-	values[i] = "true";
+	values[i] = dbname == NULL ? "true" : "database";
 	i++;
 	keywords[i] = "fallback_application_name";
 	values[i] = progname;
@@ -212,3 +230,102 @@ GetConnection(void)
 
 	return tmpconn;
 }
+
+
+/*
+ * Frontend version of GetCurrentTimestamp(), since we are not linked with
+ * backend code. The protocol always uses integer timestamps, regardless of
+ * server setting.
+ */
+int64
+feGetCurrentTimestamp(void)
+{
+	int64		result;
+	struct timeval tp;
+
+	gettimeofday(&tp, NULL);
+
+	result = (int64) tp.tv_sec -
+		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
+
+	result = (result * USECS_PER_SEC) + tp.tv_usec;
+
+	return result;
+}
+
+/*
+ * Frontend version of TimestampDifference(), since we are not linked with
+ * backend code.
+ */
+void
+feTimestampDifference(int64 start_time, int64 stop_time,
+						 long *secs, int *microsecs)
+{
+	int64		diff = stop_time - start_time;
+
+	if (diff <= 0)
+	{
+		*secs = 0;
+		*microsecs = 0;
+	}
+	else
+	{
+		*secs = (long) (diff / USECS_PER_SEC);
+		*microsecs = (int) (diff % USECS_PER_SEC);
+	}
+}
+
+/*
+ * Frontend version of TimestampDifferenceExceeds(), since we are not
+ * linked with backend code.
+ */
+bool
+feTimestampDifferenceExceeds(int64 start_time,
+								int64 stop_time,
+								int msec)
+{
+	int64		diff = stop_time - start_time;
+
+	return (diff >= msec * INT64CONST(1000));
+}
+
+/*
+ * Converts an int64 to network byte order.
+ */
+void
+fe_sendint64(int64 i, char *buf)
+{
+	uint32		n32;
+
+	/* High order half first, since we're doing MSB-first */
+	n32 = (uint32) (i >> 32);
+	n32 = htonl(n32);
+	memcpy(&buf[0], &n32, 4);
+
+	/* Now the low order half */
+	n32 = (uint32) i;
+	n32 = htonl(n32);
+	memcpy(&buf[4], &n32, 4);
+}
+
+/*
+ * Converts an int64 from network byte order to native format.
+ */
+int64
+fe_recvint64(char *buf)
+{
+	int64		result;
+	uint32		h32;
+	uint32		l32;
+
+	memcpy(&h32, buf, 4);
+	memcpy(&l32, buf + 4, 4);
+	h32 = ntohl(h32);
+	l32 = ntohl(l32);
+
+	result = h32;
+	result <<= 32;
+	result |= l32;
+
+	return result;
+}
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index bb3c34d..01c384c 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -5,6 +5,7 @@ extern char *connection_string;
 extern char *dbhost;
 extern char *dbuser;
 extern char *dbport;
+extern char *dbname;
 extern int	dbgetpassword;
 extern char *replication_slot;
 
@@ -18,3 +19,12 @@ extern PGconn *conn;
 	}
 
 extern PGconn *GetConnection(void);
+
+extern int64 feGetCurrentTimestamp(void);
+extern void feTimestampDifference(int64 start_time, int64 stop_time,
+									 long *secs, int *microsecs);
+
+extern bool feTimestampDifferenceExceeds(int64 start_time, int64 stop_time,
+											int msec);
+extern void fe_sendint64(int64 i, char *buf);
+extern int64 fe_recvint64(char *buf);
-- 
1.8.5.rc2.dirty

0004-wal_decoding-Documentation-for-replication-slots-and.patchtext/x-patch; charset=us-asciiDownload
>From 46e3496b4477cb133674ba8d0c349871f6127baa Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 27 Jan 2014 17:13:49 +0100
Subject: [PATCH 4/5] wal_decoding: Documentation for replication slots and
 changeset extraction

Andres, Craig
---
 doc/src/sgml/catalogs.sgml            |  27 +-
 doc/src/sgml/changesetextraction.sgml | 527 ++++++++++++++++++++++++++++++++++
 doc/src/sgml/filelist.sgml            |   2 +
 doc/src/sgml/func.sgml                |  94 +++++-
 doc/src/sgml/postgres.sgml            |   1 +
 doc/src/sgml/protocol.sgml            |  95 ++++--
 doc/src/sgml/ref/allfiles.sgml        |   1 +
 doc/src/sgml/ref/create_table.sgml    |   4 +-
 doc/src/sgml/ref/pg_recvlogical.sgml  | 295 +++++++++++++++++++
 doc/src/sgml/reference.sgml           |   1 +
 10 files changed, 1026 insertions(+), 21 deletions(-)
 create mode 100644 doc/src/sgml/changesetextraction.sgml
 create mode 100644 doc/src/sgml/ref/pg_recvlogical.sgml

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index dca24fc..5e680cf 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -5177,7 +5177,7 @@
 
   <para>
    For more on replication slots,
-   see <xref linkend="streaming-replication-slots">.
+   see <xref linkend="streaming-replication-slots"> and <xref linkend="changesetextraction">.
   </para>
 
   <table>
@@ -5210,6 +5210,13 @@
      </row>
 
      <row>
+      <entry><structfield>plugin</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>The basename of the shared object containing the output plugin this logical slot is using, or null for physical slots.</entry>
+     </row>
+
+     <row>
       <entry><structfield>datoid</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry>
@@ -5243,6 +5250,24 @@
      </row>
 
      <row>
+      <entry><structfield>xmin</structfield></entry>
+      <entry><type>xid</type></entry>
+      <entry></entry>
+      <entry>The oldest transaction that this slot needs the database to
+      retain.  <literal>VACUUM</literal> cannot remove catalog tuples deleted
+      by any later transaction.
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>catalog_xmin</structfield></entry>
+      <entry><type>xid</type></entry>
+      <entry></entry>
+      <entry>The <literal>xmin</literal>, or oldest transaction ID, that this
+      slot forces to be retained in the system catalogs. </entry>
+     </row>
+
+     <row>
       <entry><structfield>restart_lsn</structfield></entry>
       <entry><type>text</type></entry>
       <entry></entry>
diff --git a/doc/src/sgml/changesetextraction.sgml b/doc/src/sgml/changesetextraction.sgml
new file mode 100644
index 0000000..38ac4ea
--- /dev/null
+++ b/doc/src/sgml/changesetextraction.sgml
@@ -0,0 +1,527 @@
+<!-- doc/src/sgml/changesetextraction.sgml -->
+ <chapter id="changesetextraction">
+  <title>Changeset Extraction</title>
+  <indexterm zone="changesetextraction">
+   <primary>Changeset Extraction</primary>
+  </indexterm>
+  <para>
+   PostgreSQL provides infrastructure to stream the modifications performed
+   via SQL to external consumers which can be used to implement replication
+   solutions, perform auditing and similar tasks.
+  </para>
+
+  <para>
+   <indexterm><primary>Changeset Extraction Slot</primary></indexterm>
+   A changeset extraction slot ("logical replication slot") is a persistent
+   server-side record of the replay progress of a stream of changes. A stream of
+   changes is read from the slot to a receiving client program.
+  </para>
+  <para>
+   The format in which those changes are streamed is determined by the output
+   plugin used. While an example plugin is provided, additional plugins can be
+   written to extend the choice of available formats without modifying any
+   core code.
+  </para>
+  <para>
+   Changes can be consumed either using one streaming replication protocol
+   (see <xref linkend="protocol-replication"> and
+   <xref linkend="changesetextraction-walsender">), or by calling functions
+   via SQL (see <xref linkend="changesetextraction-sql">). It is also possible
+   to write additional methods of consuming the output of a replication slot
+   without modifying core code
+   (see <xref linkend="changesetextraction-writer">).
+  </para>
+
+  <sect1 id="changesetextraction-example">
+   <title>Changeset Extraction Example</title>
+   <para>
+    The following example shows usage of the SQL interface.
+   </para>
+   <para>
+    Before you can use changeset extraction you must edit
+    <literal>postgresql.conf</literal> and ensure the following parameters are
+    set to at least:
+    <programlisting>
+wal_level = logical
+max_replication_slots = 1
+    </programlisting>
+    and restart PostgreSQL. Then connect to the target database (in the example
+    below, <literal>postgres</literal>) as a superuser.
+   </para>
+   <programlisting>
+postgres=# -- max_replication_slots must be nonzero and wal_level must be logical
+postgres=# SHOW max_replication_slots;
+ max_replication_slots
+-----------------------
+ 1
+(1 row)
+
+postgres=# SHOW wal_level;
+ wal_level
+-----------
+ logical
+(1 row)
+
+postgres=# -- The decoding plugin you want must be installed. If no rows are returned,
+postgres=# -- then cd contrib/test_decoding && make install then re-check.
+postgres=#
+postgres=# select * from pg_available_extensions WHERE name = 'test_decoding';
+     name      | default_version | installed_version |                              comment
+---------------+-----------------+-------------------+-------------------------------------------------------------------
+ test_decoding | 1.0             | 1.0               | test output plugin for changeset extraction / logical replication
+(1 row)
+
+postgres=# SELECT * FROM pg_replication_slots;
+ slot_name | plugin | slottype | datoid | database | active | catalog_xmin | data_xmin | restart_decoding_lsn
+-----------+--------+----------+--------+----------+--------+--------------+-----------+----------------------
+(0 rows)
+
+postgres=# -- Create a slot named 'regression_slot' using the output plugin 'test_decoding'
+postgres=# SELECT * FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+    slotname     | xlog_position
+-----------------+---------------
+ regression_slot | 0/16B1970
+
+postgres=# SELECT * FROM pg_replication_slots;
+    slot_name    |    plugin     | slottype | datoid | database | active | catalog_xmin | data_xmin | restart_decoding_lsn
+-----------------+---------------+----------+--------+----------+--------+--------------+-----------+----------------------
+ regression_slot | test_decoding | logical  |  12054 | postgres | f      |          690 |         0 | 0/16B1938
+(1 row)
+
+postgres=# -- There are no changes to see yet
+postgres=# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ location | xid | data
+----------+-----+------
+(0 rows)
+
+postgres=# CREATE TABLE data(id serial primary key, data text);
+CREATE TABLE
+
+postgres=# -- DDL isn't replicated, so all you'll see is the transaction
+postgres=# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ location  | xid |  data
+-----------+-----+--------
+ 0/16E1558 | 716 | BEGIN
+ 0/16EBAC8 | 716 | COMMIT
+(2 rows)
+
+postgres=# -- Once changes are read once, they're consumed and not emitted
+postgres=# -- in a subsequent call:
+postgres=# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ location | xid | data
+----------+-----+------
+(0 rows)
+
+postgres=# BEGIN;
+postgres=# INSERT INTO data(data) VALUES('1');
+postgres=# INSERT INTO data(data) VALUES('1');
+postgres=# COMMIT;
+
+postgres=# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16EBD10 | 718 | BEGIN
+ 0/16EBE60 | 718 | table "data": INSERT: id[int4]:2 data[text]:1
+ 0/16EBE60 | 718 | table "data": INSERT: id[int4]:3 data[text]:1
+ 0/16EBE60 | 718 | COMMIT
+(4 rows)
+
+postgres=# INSERT INTO data(data) VALUES('1');
+
+postgres=# -- You can also peek ahead in the change stream without consuming changes
+postgres=# SELECT * FROM pg_decoding_slot_peek_changes('regression_slot', 'now', 'include-xids', '0');
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16EBE98 | 719 | BEGIN
+ 0/16EBF58 | 719 | table "data": INSERT: id[int4]:4 data[text]:1
+ 0/16EBF58 | 719 | COMMIT
+(3 rows)
+
+postgres=# SELECT * FROM pg_decoding_slot_peek_changes('regression_slot', 'now', 'include-xids', '0');
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16EBE98 | 719 | BEGIN
+ 0/16EBF58 | 719 | table "data": INSERT: id[int4]:4 data[text]:1
+ 0/16EBF58 | 719 | COMMIT
+
+postgres=# -- Remember to destroy a slot you no longer need to stop it consuming
+postgres=# -- server resources:
+postgres=# SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot
+-----------------------
+
+(1 row)
+    </programlisting>
+   <para>
+    The following example shows usage of the walsender interface using
+    the <link linkend="app-pgrecvlogical"><command>pg_recvlogical</command></link>
+    shell command. It requires the replication configurations to be allowed
+    (see <xref linkend="streaming-replication-authentication">)
+    and <varname>max_wal_senders</varname> to be set sufficiently high for
+    another connection.
+   </para>
+   <programlisting>
+# pg_recvlogical --slot test --init -d testdb
+# pg_recvlogical --slot test -f - --start -d testdb
+CTRL-Z
+# psql -c "INSERT INTO data(data) VALUES('1');"
+# fg
+BEGIN 721
+table "data": INSERT: id[int4]:5 data[text]:1
+COMMIT 721
+   </programlisting>
+  </sect1>
+  <sect1 id="changesetextraction-explanation">
+   <title>Changeset Extraction Concepts</title>
+   <sect2>
+    <indexterm>
+     <primary>Changeset Extraction</primary>
+    </indexterm>
+    <indexterm>
+     <primary>Changeset Generation</primary>
+    </indexterm>
+    <title>Changeset Extraction</title>
+    <para>
+     Changeset Extraction is the the process of extracting all persistent
+     changes to a database's tables into a coherent, easy to understand format
+     which is easy to interpret independent of the way the changes were made.
+    </para>
+    <para>
+     In <productname>PostgreSQL</productname> changeset extraction is
+     implemented by decoding the <link linkend="wal">WAL's</link> contents,
+     which describe changes on a storage level, into an easier to interpret
+     format. That process is called logical decoding.
+    </para>
+   </sect2>
+   <sect2>
+    <indexterm>
+     <primary>Logical Replication Slot</primary>
+    </indexterm>
+    <indexterm>
+     <primary>Replication Slot</primary>
+    </indexterm>
+    <title>Replication Slots</title>
+    <para>
+     In the context of changeset extraction a replication slot represents a
+     stream of changes which can be replayed to a client in the order they
+     were made on the origin server. Each slot streams a sequence of changes
+     from a single database, sending each change exactly once (unless peeking
+     forward in the stream).
+    </para>
+    <note>
+     <para>PostgreSQL also has streaming replication slots
+     (see <xref linkend="streaming-replication">), but they are used somewhat
+     differently there.
+     </para>
+    </note>
+    <para>
+     Replication slots have an identifier which is unique across all databases
+     in a <productname>PostgreSQL</productname> cluster. Slots persist
+     independently of the connection using them and are crash-safe.  They can
+     be allocated in primary servers and hot-standby servers (streaming
+     replicas or archive-replaying hot standbys), so it's possible to
+     replicate changes over physical replication then read a logical change
+     stream from a physical replica server.
+    </para>
+    <para>
+     Multiple independent slots may exist for a single database. Each slot has
+     its own state, allowing different consumers to receive changes from
+     different points in the database change stream. For most applications a
+     separate slot is required for each changeset consumer.
+    </para>
+    <para>
+     A changeset extraction slot knows nothing about the state of the
+     receiver(s).  It's even possible to have multiple different receivers use
+     the same slot at different times; they'll just get the changes following
+     on from when the last receiver stopped consuming them. Only one receiver
+     may consume changes from a slot at any given time.
+    </para>
+    <sect3 id="changesetextraction-abandoned-slots">
+     <title>Unused/abandoned slots</title>
+     <para>
+      Changeset extraction slots persist across crashes and know nothing about
+      the state of their consumer(s). They will prevent removal of required
+      resources even when there is no connection using them. This consumes
+      storage because neither required WAL nor required rows from the system
+      catalogs can be removed by VACUUM as long as they are required by a
+      replication slot, so if a slot is no longer required it should be
+      dropped.
+     </para>
+     <para>
+      Slots may be created manually, or using a client like a replication
+      tool. Keep this in mind when you retire a client that uses a changeset
+      extraction slot, like a logical replica - you may need to give it a
+      specific command to remove its changeset extraction slot, or drop the
+      slot yourself, even if you did not initially create the slot by hand.
+     </para>
+    </sect3>
+   </sect2>
+   <sect2>
+    <title>Exported Snapshots</title>
+    <para>
+     When a new replication slot is created over the walsender interface a
+     snapshot is exported
+     (see <xref linkend="functions-snapshot-synchronization">) which will show
+     exactly the state of the database after which all changes will be
+     included in the changestream. This can be used to create a new replica by
+     using <link linkend="sql-set-transaction"><literal>SET TRANSACTION
+     SNAPSHOT</literal></link> to read the state of the database at the moment
+     the slot was created. This transaction can then be used to dump the
+     database's state at that point in time which afterwards can be updated
+     using the slot's contents without loosing any changes.
+    </para>
+   </sect2>
+  </sect1>
+  <sect1 id="changesetextraction-walsender">
+   <title>Streaming Replication Protocol Interface</title>
+   <para>
+    The <literal>CREATE_REPLICATION_SLOT SLOT slotname LOGICAL
+    options</literal>, <literal>DROP_REPLICATION_SLOT SLOT slotname</literal>
+    and <literal>START_REPLICATION SLOT slotname LOGICAL options</literal>
+    commands can be used to create, drop and stream changes from a replication
+    slot respectively. These commands are only available over a replication
+    connection; the won't work from the SQL
+    level. See <xref linkend="protocol-replication">.
+   </para>
+   <para>
+    The <command>pg_recvlogical</command> command
+    (see <xref linkend="app-pgrecvlogical">) can be used to control changeset
+    extraction over a walsender connection.
+   </para>
+  </sect1>
+  <sect1 id="changesetextraction-sql">
+   <title>Changeset Extraction <acronym>SQL</acronym> Interface</title>
+   <para>
+     See <xref linkend="functions-replication"> for detailed
+     documentation on the SQL-level API for interacting with changeset
+     extraction.
+   </para>
+   <para>
+    Only replications slots which are consumed over the walsender interface
+    support being used for synchronous replication
+    (see <xref linkend="synchronous-replication">).
+   </para>
+  </sect1>
+  <sect1 id="changesetextraction-catalogs">
+   <title>System catalogs related to changeset extraction</title>
+   <para>
+    The <xref linkend="catalog-pg-replication-slots"> view and the
+    <literal>pg_stat_replication</literal> view
+    in <xref linkend="monitoring-stats-views-table"> provide information about
+    the current state of replication slots and walsender connections
+    respectively. These views apply to both physical and logical replication.
+   </para>
+  </sect1>
+  <sect1 id="changesetextraction-output-plugin">
+   <title>Changeset Extraction Output Plugins</title>
+   <para>
+    An example output plugin can be found in the
+    <link linkend="test-decoding">
+     <filename>contrib/test_decoding</filename>
+    </link>
+    subdirectory of the PostgreSQL source tree.
+   </para>
+   <sect2 id="changesetextraction-output-init">
+    <title>Initialization Function</title>
+    <indexterm zone="changesetextraction">
+     <primary>_PG_output_plugin_init</primary>
+    </indexterm>
+    <para>
+     An output plugin is loaded by dynamically loading a shared library with
+     the output plugin's name as the library basename. To provide the required
+     output plugin callbacks and to indicate that the library is actually an
+     output plugin it needs to provide a function named
+     <function>_PG_output_plugin_init</function>. This function is passed a
+     struct that needs to be filled with the callback function pointers for
+     individual actions.
+     <programlisting>
+typedef struct OutputPluginCallbacks
+{
+    LogicalDecodeStartupCB startup_cb;
+    LogicalDecodeBeginCB begin_cb;
+    LogicalDecodeChangeCB change_cb;
+    LogicalDecodeCommitCB commit_cb;
+    LogicalDecodeShutdownCB shutdown_cb;
+} OutputPluginCallbacks;
+typedef void (*LogicalOutputPluginInit)(struct OutputPluginCallbacks *cb);
+     </programlisting>
+     The <function>begin_cb</function>, <function>change_cb</function>
+     and <function>commit_cb</function> callbacks are required,
+     while <function>startup_cb</function>
+     and <function>shutdown_cb</function> are optional.
+    </para>
+   </sect2>
+   <sect2 id="changesetextraction-output-plugin-callbacks">
+    <title>Output Plugin Callbacks</title>
+    <para>
+     An output plugin gets notified about changes that are happening via
+     various callbacks it needs to provide.
+    </para>
+    <para>
+     Concurrent transactions are decoded in commit order and only changes
+     belonging to a specific transaction are decoded inbetween
+     the <literal>begin</literal> and <literal>commit</literal>
+     callbacks. Transaction that were rolled back explicitly or implicitly
+     will never be
+     decoded. Successfull <link linkend="SQL-SAVEPOINT">SAVEPOINTs</link> are
+     folded into the transaction containing them in the order they were
+     exectuded within that transaction.
+    </para>
+    <sect3 id="changesetextraction-output-plugin-callback-startup">
+     <title>Startup Callback</title>
+     <para>
+      The optional startup callback is called whenever an replication slot
+      is created or asked to stream changes, independent of the number of
+      changes that are ready to be output.
+      <programlisting>
+typedef void (*LogicalDecodeStartupCB) (
+    struct LogicalDecodingContext *ctx,
+    bool is_init
+);
+      </programlisting>
+      The is_init paramter will be true when the replication slot is being
+      created and false otherwise.
+     </para>
+     <para>
+      The startup callback should validate the options present in
+      <literal>ctx-&gt;output_plugin_options</literal>. If the output plugin needs
+      to have state, it can use <literal>ctx-&gt;output_plugin_private</literal> to
+      store it.
+     </para>
+    </sect3>
+    <sect3 id="changesetextraction-output-plugin-shutdown">
+     <title>Shutdown Callback</title>
+     <para>
+      The optional shutdown callback is called whenever a formerly active
+      replication slot is not used anymore and can be used to deallocate
+      resources private to the output plugin. The slot isn't necessarily being
+      dropped, streaming is just being stopped.
+      <programlisting>
+typedef void (*LogicalDecodeShutdownCB) (
+    struct LogicalDecodingContext *ctx
+);
+      </programlisting>
+     </para>
+   </sect3>
+    <sect3 id="changesetextraction-output-plugin-begin">
+     <title>Transaction Begin Callback</title>
+     <para>
+      The required <function>begin_cb</function> callback is called whenever a
+      transaction start has been decoded, but only if we know that the
+      transaction has committed. Aborted transactions and their contents are
+      never decoded.
+      <programlisting>
+typedef void (*LogicalDecodeBeginCB) (
+    struct LogicalDecodingContext *,
+    ReorderBufferTXN *txn
+);
+      </programlisting>
+      The txn parameter contains meta information about the transaction,
+      like the timestamp at which it committed and its xid.
+     </para>
+   </sect3>
+    <sect3 id="changesetextraction-output-plugin-commit">
+     <title>Transaction End Callback</title>
+     <para>
+      The required <function>commit_cb</function> callback is called whenever
+      a transaction commit has been
+      decoded. The <function>change_cb</function> callbacks for all modified
+      rows will have been called before this, if there are have been any
+      modified rows.
+      <programlisting>
+typedef void (*LogicalDecodeCommitCB) (
+    struct LogicalDecodingContext *,
+    ReorderBufferTXN *txn
+);
+      </programlisting>
+     </para>
+    </sect3>
+    <sect3 id="changesetextraction-output-plugin-change">
+     <title>Callback called for each individual change in a
+     transaction</title>
+     <para>
+      The required <function>change_cb</function> callback is called for every
+      individual row modification inside a transaction, be it
+      an <command>INSERT</command>, <command>UPDATE</command>
+      or <command>DELETE</command>. Even if the original command modified
+      several rows at once, the callback will be called indvidually for each
+      row.
+      <programlisting>
+typedef void (*LogicalDecodeChangeCB) (
+    struct LogicalDecodingContext *ctx,
+    ReorderBufferTXN *txn,
+    Relation relation,
+    ReorderBufferChange *change
+);
+      </programlisting>
+      The <parameter>ctx</parameter> and <parameter>txn</parameter> parameters
+      have the same contents as for the <function>begin_cb</function>
+      and <function>commit_cb</function> callbacks, but additionally the
+      relation descriptor <parameter>relation</parameter>for the relation the
+      row belongs to and a struct <parameter>change</parameter> describing the
+      row modification are passed in.
+     </para>
+     <note>
+      <para>
+       Only changes in user defined tables, that are not unlogged
+       (see <xref linkend="SQL-CREATETABLE-UNLOGGED">) or temporary
+       (see <xref linkend="SQL-CREATETABLE-TEMPORARY">)can be extracted using
+       changeset extraction.
+      </para>
+     </note>
+    </sect3>
+   </sect2>
+   <sect2 id="changesetextraction-output-plugin-output">
+    <title>Functions for producing output from an output plugin</title>
+    <para>
+     To actually produce output output plugins can write data to
+     the <literal>StringInfo</literal> output buffer
+     in <literal>ctx-&gt;out</literal> when inside
+     the <function>begin_cb</function>, <function>commit_cb</function>, <function>change_cb</function>
+     callbacks. Before writing to the output
+     buffer <function>OutputPluginPrepareWrite(ctx, last_write)</function> has
+     to be called, and after finishing writing to the
+     buffer <function>OutputPluginWrite(ctx, last_write)</function> has to be
+     called to perform the write. The <parameter>last_write</parameter>
+     indicates whether a particular write was the callback's last write.
+    </para>
+    <para>
+     The following example shows how to output data to the consumer of an
+     output plugin:
+     <programlisting>
+OutputPluginPrepareWrite(ctx, true);
+appendStringInfo(ctx->out, "BEGIN %u", txn->xid);
+OutputPluginWrite(ctx, true);
+     </programlisting>
+    </para>
+   </sect2>
+  </sect1>
+  <sect1 id="changesetextraction-writer">
+   <title>Changeset Extraction Output Writers</title>
+   <para>
+    It is possible to add additional output methods, in addition to the SQL
+    and replication protocol variants, of consuming changeset extraction
+    data. For details look at the implementation of the SQL interface
+    functions
+    in <filename>src/backend/replication/logical/logicalfuncs.c</filename>.
+    Essentially three functions need to be provided, one to read WAL, one to
+    prepare writing output and one to write the output
+    (see <xref linkend="changesetextraction-output-plugin-output">).
+   </para>
+  </sect1>
+  <sect1 id="changesetextraction-synchronous">
+   <title>Synchronous replication support for Changeset Extraction</title>
+   <para>
+    The Changeset Extraction support in <productname>PostgreSQL</productname>
+    supports being used to to
+    build <link linkend="synchronous-replication">synchronous
+    replication</link> solutions, with the same user interface as synchronous
+    replication for <link linkend="streaming-replication">streaming
+    replication</link> if the walsender interface
+    (see <xref linkend="changesetextraction-walsender">) is used to stream out
+    data. Clients have to send <literal>Standby status update (F)</literal>
+    (see <xref linkend="protocol-replication">), just like streaming
+    replication clients do.
+   </para>
+  </sect1>
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 09de4bd..05bed2b 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -91,6 +91,7 @@
 <!ENTITY nls        SYSTEM "nls.sgml">
 <!ENTITY plhandler  SYSTEM "plhandler.sgml">
 <!ENTITY fdwhandler SYSTEM "fdwhandler.sgml">
+<!ENTITY changesetextraction SYSTEM "changesetextraction.sgml">
 <!ENTITY protocol   SYSTEM "protocol.sgml">
 <!ENTITY sources    SYSTEM "sources.sgml">
 <!ENTITY storage    SYSTEM "storage.sgml">
@@ -145,6 +146,7 @@
 <!ENTITY tcn             SYSTEM "tcn.sgml">
 <!ENTITY test-parser     SYSTEM "test-parser.sgml">
 <!ENTITY test-shm-mq     SYSTEM "test-shm-mq.sgml">
+<!ENTITY test-decoding   SYSTEM "test-decoding.sgml">
 <!ENTITY tsearch2        SYSTEM "tsearch2.sgml">
 <!ENTITY unaccent      SYSTEM "unaccent.sgml">
 <!ENTITY uuid-ossp       SYSTEM "uuid-ossp.sgml">
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index be548d7..d4e84ad 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -16301,8 +16301,9 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
 
    <para>
     PostgreSQL exposes a number of functions for controlling and interacting
-    with replication features. See <xref linkend="streaming-replication">
-    and <xref linkend="streaming-replication-slots">.
+    with replication features. See <xref linkend="streaming-replication">,
+    <xref linkend="streaming-replication-slots">
+    and <xref linkend="changesetextraction">.
    </para>
 
    <para>
@@ -16361,9 +16362,98 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
         command <literal>DROP_REPLICATION_SLOT</>.
        </entry>
       </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_create_decoding_replication_slot</primary>
+        </indexterm>
+        <literal><function>pg_create_decoding_replication_slot(<parameter>slotname</parameter> <type>text</type>, <parameter>plugin</parameter> <type>text</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>slotname</parameter> <type>text</type>, <parameter>xlog_position</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Creates a new logical (decoding) replication slot named
+        <parameter>slotname</parameter> using the output plugin
+        <parameter>plugin</parameter>. Output plugins are listed amongst the
+        extensions in <literal>pg_catalog.pg_available_extensions</literal>,
+        but there is no specific listing of only output plugins. Same as
+        walsender protocol command <literal>CREATE REPLICATION SLOT ... LOGICAL</literal>.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_decoding_slot_get_changes</primary>
+        </indexterm>
+        <literal><function>pg_decoding_slot_get_changes(<parameter>slotname</parameter> <type>text</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>text</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Returns all changes in the slot <parameter>slotname</parameter> since
+        changes have been consumed last, up until the changes visible at the
+        time this call starts. Changes will be consumed.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_decoding_slot_peek_changes</primary>
+        </indexterm>
+        <literal><function>pg_decoding_slot_peek_changes(<parameter>slotname</parameter> <type>text</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>text</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Returns all changes in the slot <parameter>slotname</parameter> since
+        changes have been consumed last, up to the changes visible at the start
+        of this call. Changes will not be consumed.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_decoding_slot_get_binary_changes</primary>
+        </indexterm>
+        <literal><function>pg_decoding_slot_get_binary_changes(<parameter>slotname</parameter> <type>text</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>text</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>bytea</type>)
+       </entry>
+       <entry>
+        Returns all changes in the slot <parameter>slotname</parameter> since
+        changes have been consumed last in binary format. Changes will be
+        consumed.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_decoding_slot_peek_binary_changes</primary>
+        </indexterm>
+        <literal><function>pg_decoding_slot_peek_binary_changes(<parameter>slotname</parameter> <type>text</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>text</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>binary</type>)
+       </entry>
+       <entry>
+        Returns all changes in the slot <parameter>slotname</parameter> since
+        changes have been consumed last in binary format. Changes will not
+        be consumed.
+       </entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
+
   </sect2>
 
   <sect2 id="functions-admin-dbobject">
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index b47bf52..dd1709f 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -219,6 +219,7 @@
 
   &spi;
   &bgworker;
+  &changesetextraction;
 
  </part>
 
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 8d890ba..e53cc38 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1301,24 +1301,48 @@
 <title>Streaming Replication Protocol</title>
 
 <para>
-To initiate streaming replication, the frontend sends the
-<literal>replication</> parameter in the startup message. A boolean value
-of <literal>true</> tells the backend to go into walsender mode, wherein a
-small set of replication commands can be issued instead of SQL statements. Only
-the simple query protocol can be used in walsender mode.
-Passing a <literal>database</> as the value instructs walsender to connect to
-the database specified in the <literal>dbname</> paramter which will in future
-allow some additional commands to the ones specified below to be run.
+ To initiate streaming replication, the frontend sends the
+ <literal>replication</> parameter in the startup message. This accepts the
+ values <literal>true</literal>, <literal>false</literal> (and their 1/0
+ numeric equivalents) or in 9.4 and above, <literal>database</literal>.
+</para>
+<para>
+ Any valid non-false value tells the backend to go into walsender mode, wherein
+ the small set of replication commands documented below can be issued instead
+ of SQL statements.  Only the simple query protocol can be used in walsender
+ mode.
+</para>
+<para>
+ If <literal>replication</literal> is <literal>true</literal>, no specific
+ database is connected to. In this mode only a subset of walsender subcommands
+ are available. To use database-specific walsender commands like the logical
+ replication commands, <literal>replication</> must be set to
+ <literal>database</> and the name of a database to connect to must be
+ specified in the <literal>database</> startup packet field.
+</para>
+<para>
+ For the purpose of testing replication commands, you can make a replication
+ connection via <application>psql</application> or any other <literal>libpq</literal>-using
+ tool with a connection string including the <literal>replication</literal> option,
+ e.g.:
+ <programlisting>
+  psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
+ </programlisting>
+ However it is usually more useful to use
+ <application>pg_receivexlog</application> (for physical replication) or
+ <application>pg_recvlogical</application> (for logical replication).
+</para>
 
+<para>
 The commands accepted in walsender mode are:
-
 <variablelist>
   <varlistentry>
     <term>IDENTIFY_SYSTEM</term>
     <listitem>
      <para>
-      Requests the server to identify itself. Server replies with a result
-      set of a single row, containing four fields:
+      Requests the server to identify itself. Does not require a database name
+      to be specified for the connection. Server replies with a result set of a
+      single row, containing four fields:
      </para>
 
      <para>
@@ -1381,7 +1405,8 @@ The commands accepted in walsender mode are:
     <listitem>
      <para>
       Requests the server to send over the timeline history file for timeline
-      <replaceable class="parameter">tli</replaceable>.  Server replies with a
+      <replaceable class="parameter">tli</replaceable>. Does not require a database
+      name to be specified for the connection. Server replies with a
       result set of a single row, containing two fields:
      </para>
 
@@ -1764,17 +1789,55 @@ The commands accepted in walsender mode are:
      </para>
     </listitem>
   </varlistentry>
+  <varlistentry>
+    <term><literal>START_REPLICATION</literal> <literal>SLOT</literal> <replaceable class="parameter">slotname</> <literal>LOGICAL</literal> <replaceable class="parameter">XXX/XXX</></term>
+    <listitem>
+     <para>
+      Instructs server to start streaming WAL for logical replication, starting
+      at WAL position <replaceable class="parameter">XXX/XXX</>. The server can
+      reply with an error, e.g. if the requested section of WAL has already
+      been recycled. On success, server responds with a CopyBothResponse
+      message, and then starts to stream WAL to the frontend.
+     </para>
+     <para>
+      The output plugin associated with the selected slot is used
+      to process the output for streaming.
+     </para>
+     <variablelist>
+      <varlistentry>
+       <term><literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
+       <listitem>
+         <para>
+          The name of the slot to stream changes from. This parameter is required,
+          and must correspond to an existing logical replication slot created
+          with <literal>CREATE_REPLICATION_SLOT</literal> in
+          <literal>LOGICAL</literal> mode.
+         </para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><replaceable class="parameter">XXX/XXX</></term>
+       <listitem>
+        <para>
+         The WAL position to begin streaming at.
+        </para>
+       </listitem>
+      </varlistentry>
+     </variablelist>
+    </listitem>
+  </varlistentry>
 
   <varlistentry>
-    <term><literal>DROP_REPLICATION_SLOT</literal> <replaceable class="parameter">slotname</></term>
+    <term><literal>DROP_REPLICATION_SLOT</literal> <literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
     <listitem>
      <para>
-      Drops a replication slot, freeing any reserved server-side resources. If
-      the slot is currently in use by an active connection, this command fails.
+     Drops a physical or logical replication slot, freeing any reserved server-side
+     resources. If the slot is currently in use by an active connection this command
+     fails.
      </para>
      <variablelist>
       <varlistentry>
-       <term><replaceable class="parameter">slotname</></term>
+       <term><literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
        <listitem>
          <para>
           The name of the slot to drop.
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index ce7a5e3..1b0962c 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -183,6 +183,7 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY pgDumpall          SYSTEM "pg_dumpall.sgml">
 <!ENTITY pgIsready          SYSTEM "pg_isready.sgml">
 <!ENTITY pgReceivexlog      SYSTEM "pg_receivexlog.sgml">
+<!ENTITY pgRecvlogical      SYSTEM "pg_recvlogical.sgml">
 <!ENTITY pgResetxlog        SYSTEM "pg_resetxlog.sgml">
 <!ENTITY pgRestore          SYSTEM "pg_restore.sgml">
 <!ENTITY postgres           SYSTEM "postgres-ref.sgml">
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index e0b8a4e..04e8b92 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -137,7 +137,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
 
   <variablelist>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-TEMPORARY">
     <term><literal>TEMPORARY</> or <literal>TEMP</></term>
     <listitem>
      <para>
@@ -171,7 +171,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-UNLOGGED">
     <term><literal>UNLOGGED</></term>
     <listitem>
      <para>
diff --git a/doc/src/sgml/ref/pg_recvlogical.sgml b/doc/src/sgml/ref/pg_recvlogical.sgml
new file mode 100644
index 0000000..8fbb698
--- /dev/null
+++ b/doc/src/sgml/ref/pg_recvlogical.sgml
@@ -0,0 +1,295 @@
+<!--
+doc/src/sgml/ref/pg_recvlogical.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="app-pgrecvlogical">
+ <refmeta>
+  <refentrytitle><application>pg_recvlogical</application></refentrytitle>
+  <manvolnum>1</manvolnum>
+  <refmiscinfo>Application</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>pg_recvlogical</refname>
+  <refpurpose>Control changeset extraction
+  (see <xref linkend="changesetextraction">) replication streams over a
+  walsender connection.</refpurpose>
+ </refnamediv>
+
+ <indexterm zone="app-pgrecvlogical">
+  <primary>pg_recvlogical</primary>
+ </indexterm>
+
+ <refsynopsisdiv>
+  <cmdsynopsis>
+   <command>pg_recvlogical</command>
+   <arg rep="repeat" choice="opt"><option>option</option></arg>
+  </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="R1-APP-PGRECVLOGICAL-1">
+  <title>Description</title>
+  <para>
+   <command>pg_recvlogical</command> controls changeset extraction replication
+   slots and streams data from such replication slots.
+  </para>
+  <para>
+   It makes a replication-mode connection, so it is subject to the same
+   constraints as <link
+   linkend="app-pgreceivexlog"><application>pg_receivexlog</application></link>,
+   plus those for logical replication (see <xref
+   linkend="changesetextraction">).
+  </para>
+
+ </refsect1>
+
+ <refsect1>
+  <title>Options</title>
+
+   <para>
+    <application>pg_recvlogical</application> runs in one of three modes, which
+    control its primary action:
+
+    <variablelist>
+
+     <varlistentry>
+      <term><option>--create</option></term>
+      <listitem>
+       <para>
+       Create a new logical replication slot with the name specified in
+       <option>--slot</option>, using the output plugin
+       <option>--plugin</option>, then exit. The slot is created for the
+       database given in <option>--dbname</option>.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--start</option></term>
+      <listitem>
+       <para>
+       Begin streaming changes from the logical replication slot with the name
+       specified in <option>--slot</option>, continuing until terminated with a
+       signal. If the server side change stream ends with a server
+       shutdown / disconnect, retry in a loop unless <option>--no-loop</option>
+       is specified. The stream format is determined by the output plugin
+       specified when the slot was created.
+       </para>
+       <para>
+       You must connect to the same <option>--dbname</option> as the slot was
+       created with to stream changes from a logical replication slot.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--drop</option></term>
+      <listitem>
+       <para>
+       Drop the replication slot with the name specified in <option>--slot</option>, then exit.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
+
+   </para>
+
+   <para>
+    <application>pg_recvlogical</application> supports all the usual
+    <literal>libpq</literal>-based options. These are explained in detail in the
+    documentation for <application>psql</application> and for <literal>libpq</literal>.
+
+    <variablelist>
+ 
+      <varlistentry>
+       <term><option>-U <replaceable>user</replaceable></option></term>
+       <term><option>--username <replaceable>user</replaceable></option></term>
+       <listitem>
+        <para>
+         Username to connect as. Must have a suitable <literal>pg_hba.conf</literal>
+         entry allowing <literal>replication</literal> connections. Defaults to
+         current operating system user name.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>-d <replaceable>database</replaceable></option></term>
+       <term><option>--dbname <replaceable>database</replaceable></option></term>
+       <listitem>
+        <para>
+         The database to connect to in <literal>replication</literal> mode; see
+         mode descriptions for details. May be a libpq connstring instead. Defaults
+         to user name.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>-h <replaceable>hostname-or-ip</replaceable></option></term>
+       <term><option>--host <replaceable>hostname-or-ip</replaceable></option></term>
+       <listitem>
+        <para>
+         Host or socket to connect to. See psql and libpq documentation.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>-p <replaceable>port</replaceable></option></term>
+       <term><option>--port <replaceable>port</replaceable></option></term>
+       <listitem>
+        <para>
+         Port number to connect to. See <application>libpq</application> for an explanation
+         of default port choices when this is not specified.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>-w</option></term>
+       <term><option>--no-password</option></term>
+       <listitem>
+        <para>
+         Prevent prompting for a password. Will exit with an error code if a password is
+         required but not available.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>-W</option></term>
+       <term><option>--password</option></term>
+       <listitem>
+        <para>
+         Provide a password for this connection. Please use the pgservice file
+         (see <xref linkend="libpq-pgservice">) or an environment variable
+         instead of this option.
+        </para>
+       </listitem>
+      </varlistentry>
+
+     </variablelist>
+
+   </para>
+
+   <para>
+    The following command-line options control the location and format of the
+    output and other replication behaviour:
+
+    <variablelist>
+
+     <varlistentry>
+      <term><option>-f <replaceable>filename</replaceable></option></term>
+      <term><option>--file=<replaceable>filename</replaceable></option></term>
+      <listitem>
+       <para>
+        Receive decoded transaction data into this file. Use <literal>-</> for stdout.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
+     <varlistentry>
+      <term><option>-n</option></term>
+      <term><option>--no-loop=</option></term>
+      <listitem>
+       <para>
+        When the connection to the server is lost, do not retry in a loop, just exit.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-P <replaceable>plugin</replaceable></option></term>
+      <term><option>--plugin=<replaceable>plugin</replaceable></option></term>
+      <listitem>
+       <para>
+        When creating a slot, use the specified changeset decoding output
+        plugin. See <xref linkend="changesetextraction">. This option has no
+        effect if the slot already exists.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-s <replaceable>interval_seconds</replaceable></option></term>
+      <term><option>--status-interval=<replaceable>interval_seconds</replaceable></option></term>
+      <listitem>
+       <para>
+        This option has the same effect as the option of the same name in <link
+        linkend="app-pgreceivexlog"><application>pg_receivexlog</application></link>.
+        See the description there.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-S <replaceable>slot_name</replaceable></option></term>
+      <term><option>--slot=<replaceable>slot_name</replaceable></option></term>
+      <listitem>
+       <para>
+        In <option>--start</option> mode, use the existing logical replication slot named
+        <replaceable>slot_name</replaceable>. In <option>--create</option> mode, create the
+        slot with this name. In <option>--drop</option> mode, delete the slot with this name.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-I <replaceable>lsn</replaceable></option></term>
+      <term><option>--startpos=<replaceable>lsn</replaceable></option></term>
+      <listitem>
+       <para>
+        In <option>--start</option> mode, start replication from the given LSN.
+        For details on the effect of this, see the documentation in <xref linkend="changesetextraction">
+        and <xref linkend="protocol-replication">. Ignored in other modes.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
+
+   </para>
+
+   <para>
+
+    The following additional options are available:
+
+    <variablelist>
+
+     <varlistentry>
+       <term><option>-v</></term>
+       <term><option>--verbose</></term>
+       <listitem>
+       <para>
+        Output verbose (detailed) error messages suitable for debugging and fault diagnosis.
+       </para>
+       </listitem>
+     </varlistentry>
+
+     <varlistentry>
+       <term><option>-V</></term>
+       <term><option>--version</></term>
+       <listitem>
+       <para>
+       Print the <application>pg_recvlogical</application> version and exit.
+       </para>
+       </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-?</></term>
+      <term><option>--help</></term>
+       <listitem>
+        <para>
+         Show help about <application>pg_recvlogical</application> command line
+         arguments, and exit.
+        </para>
+       </listitem>
+      </varlistentry>
+
+    </variablelist>
+   </para>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 87e8e9e..a6575f5 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -231,6 +231,7 @@
    &pgDumpall;
    &pgIsready;
    &pgReceivexlog;
+   &pgRecvlogical;
    &pgRestore;
    &psqlRef;
    &reindexdb;
-- 
1.8.5.rc2.dirty

0005-wal_decoding-Temporarily-add-logical-decoding-regres.patchtext/x-patch; charset=us-asciiDownload
>From 6c8c7c8a902bf8d38bd8137d67b6fe4ea14f376d Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 27 Jan 2014 17:13:49 +0100
Subject: [PATCH 5/5] wal_decoding: Temporarily add logical decoding regression
 tests to everything

---
 src/test/regress/expected/end_logical.out    |  7 +++++++
 src/test/regress/expected/end_logical_1.out  |  4 ++++
 src/test/regress/expected/init_logical.out   | 10 ++++++++++
 src/test/regress/expected/init_logical_1.out |  7 +++++++
 src/test/regress/parallel_schedule           |  4 ++++
 src/test/regress/serial_schedule             |  2 ++
 src/test/regress/sql/end_logical.sql         |  2 ++
 src/test/regress/sql/init_logical.sql        |  4 ++++
 8 files changed, 40 insertions(+)
 create mode 100644 src/test/regress/expected/end_logical.out
 create mode 100644 src/test/regress/expected/end_logical_1.out
 create mode 100644 src/test/regress/expected/init_logical.out
 create mode 100644 src/test/regress/expected/init_logical_1.out
 create mode 100644 src/test/regress/sql/end_logical.sql
 create mode 100644 src/test/regress/sql/init_logical.sql

diff --git a/src/test/regress/expected/end_logical.out b/src/test/regress/expected/end_logical.out
new file mode 100644
index 0000000..44ad6d2
--- /dev/null
+++ b/src/test/regress/expected/end_logical.out
@@ -0,0 +1,7 @@
+\copy (SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0')) TO '/tmp/testresult';
+SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot 
+--------------------------
+ 
+(1 row)
+
diff --git a/src/test/regress/expected/end_logical_1.out b/src/test/regress/expected/end_logical_1.out
new file mode 100644
index 0000000..84b00ac
--- /dev/null
+++ b/src/test/regress/expected/end_logical_1.out
@@ -0,0 +1,4 @@
+\copy (SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0')) TO '/tmp/testresult';
+ERROR:  replication slots can only be used if max_replication_slots > 0
+SELECT pg_drop_replication_slot('regression_slot');
+ERROR:  replication slots can only be used if max_replication_slots > 0
diff --git a/src/test/regress/expected/init_logical.out b/src/test/regress/expected/init_logical.out
new file mode 100644
index 0000000..98ded04
--- /dev/null
+++ b/src/test/regress/expected/init_logical.out
@@ -0,0 +1,10 @@
+-- will fail if wal_level < logical, separate expected file
+SELECT 'stop' FROM pg_drop_replication_slot('regression_slot');
+ERROR:  replication slot "regression_slot" does not exist
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ ?column? 
+----------
+ init
+(1 row)
+
+COPY (SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0')) TO STDOUT;
diff --git a/src/test/regress/expected/init_logical_1.out b/src/test/regress/expected/init_logical_1.out
new file mode 100644
index 0000000..54930e3
--- /dev/null
+++ b/src/test/regress/expected/init_logical_1.out
@@ -0,0 +1,7 @@
+-- will fail if wal_level < logical, separate expected file
+SELECT 'stop' FROM pg_drop_replication_slot('regression_slot');
+ERROR:  replication slots can only be used if max_replication_slots > 0
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+ERROR:  replication slots can only be used if max_replication_slots > 0
+COPY (SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0')) TO STDOUT;
+ERROR:  replication slots can only be used if max_replication_slots > 0
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 5758b07..66901d6 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -8,6 +8,8 @@
 # run tablespace by itself, and first, because it forces a checkpoint;
 # we'd prefer not to have checkpoints later in the tests because that
 # interferes with crash-recovery testing.
+test: init_logical
+
 test: tablespace
 
 # ----------
@@ -109,3 +111,5 @@ test: plancache limit plpgsql copy2 temp domain rangefuncs prepare without_oid c
 
 # run stats by itself because its delay may be insufficient under heavy load
 test: stats
+
+test: end_logical
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 78348f5..af9b293 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -1,5 +1,6 @@
 # src/test/regress/serial_schedule
 # This should probably be in an order similar to parallel_schedule.
+test: init_logical
 test: tablespace
 test: boolean
 test: char
@@ -142,3 +143,4 @@ test: largeobject
 test: with
 test: xml
 test: stats
+test: end_logical
diff --git a/src/test/regress/sql/end_logical.sql b/src/test/regress/sql/end_logical.sql
new file mode 100644
index 0000000..c730aad
--- /dev/null
+++ b/src/test/regress/sql/end_logical.sql
@@ -0,0 +1,2 @@
+\copy (SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0')) TO '/tmp/testresult';
+SELECT pg_drop_replication_slot('regression_slot');
diff --git a/src/test/regress/sql/init_logical.sql b/src/test/regress/sql/init_logical.sql
new file mode 100644
index 0000000..2a7913f
--- /dev/null
+++ b/src/test/regress/sql/init_logical.sql
@@ -0,0 +1,4 @@
+-- will fail if wal_level < logical, separate expected file
+SELECT 'stop' FROM pg_drop_replication_slot('regression_slot');
+SELECT 'init' FROM pg_create_decoding_replication_slot('regression_slot', 'test_decoding');
+COPY (SELECT data FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0')) TO STDOUT;
-- 
1.8.5.rc2.dirty

#46Thom Brown
thom@linux.com
In reply to: Andres Freund (#45)
Re: Changeset Extraction v7.5

On 7 February 2014 19:35, Andres Freund <andres@2ndquadrant.com> wrote:

0004: wal_decoding: Documentation for replication slots and changeset extraction

The usage of pg_create_decoding_replication_slot does show the "(1 row)" line.

The output of "SELECT * FROM pg_replication_slots;" is out-of-date.

There appears to be a column named "slot_name" and "slottype". Could
one of these have or not have the underscore for consistency?

The example also shows output from pg_decoding_slot_get_changes after
inserting 2 rows, but when I run the same example, there are no rows
returned:

# BEGIN;
BEGIN

*# INSERT INTO data(data) VALUES('1');
INSERT 0 1

*# INSERT INTO data(data) VALUES('1');
INSERT 0 1

*# COMMIT;
COMMIT

# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now',
'include-xids', '0');
location | xid | data
----------+-----+------
(0 rows)

I inserted a single row outside of a transaction, and got the expected
output. Then I ran the above again, and got an output, but an
unexpected one:

SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now',
'include-xids', '0');
location | xid | data
-----------+-----+-----------------------------------------------
0/16C8B90 | 769 | BEGIN
0/16C8D50 | 769 | table "data": INSERT: id[int4]:3 data[text]:1
0/16C8D50 | 769 | COMMIT
(3 rows)

And running the transaction with inserts again, there's no output from
that same function command. I always get an output from isolated
INSERT statements. I should point out that in my .psqlrc file I have
"\set ON_ERROR_ROLLBACK". If I use psql -X, this symptom no longer
occurs, so I think the automatic savepoints are interfering, and the
effect appears to be inconsistent.

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#47Thom Brown
thom@linux.com
In reply to: Thom Brown (#46)
Re: Changeset Extraction v7.5

On 7 February 2014 20:58, Thom Brown <thom@linux.com> wrote:

On 7 February 2014 19:35, Andres Freund <andres@2ndquadrant.com> wrote:

0004: wal_decoding: Documentation for replication slots and changeset extraction

The usage of pg_create_decoding_replication_slot does show the "(1 row)" line.

I mean "doesn't show" of course. :)

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#48Andres Freund
andres@2ndquadrant.com
In reply to: Thom Brown (#46)
Re: Changeset Extraction v7.5

On February 7, 2014 9:58:14 PM CET, Thom Brown <thom@linux.com> wrote:

On 7 February 2014 19:35, Andres Freund <andres@2ndquadrant.com> wrote:

0004: wal_decoding: Documentation for replication slots and changeset

extraction

The usage of pg_create_decoding_replication_slot does show the "(1
row)" line.

The output of "SELECT * FROM pg_replication_slots;" is out-of-date.

There appears to be a column named "slot_name" and "slottype". Could
one of these have or not have the underscore for consistency?

The example also shows output from pg_decoding_slot_get_changes after
inserting 2 rows, but when I run the same example, there are no rows
returned:

# BEGIN;
BEGIN

*# INSERT INTO data(data) VALUES('1');
INSERT 0 1

*# INSERT INTO data(data) VALUES('1');
INSERT 0 1

*# COMMIT;
COMMIT

# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now',
'include-xids', '0');
location | xid | data
----------+-----+------
(0 rows)

I inserted a single row outside of a transaction, and got the expected
output. Then I ran the above again, and got an output, but an
unexpected one:

SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now',
'include-xids', '0');
location | xid | data
-----------+-----+-----------------------------------------------
0/16C8B90 | 769 | BEGIN
0/16C8D50 | 769 | table "data": INSERT: id[int4]:3 data[text]:1
0/16C8D50 | 769 | COMMIT
(3 rows)

And running the transaction with inserts again, there's no output from
that same function command. I always get an output from isolated
INSERT statements. I should point out that in my .psqlrc file I have
"\set ON_ERROR_ROLLBACK". If I use psql -X, this symptom no longer
occurs, so I think the automatic savepoints are interfering, and the
effect appears to be inconsistent.

More complete answer later, but any chance you're using synchronous commit = off?

Thanks for looking,

Andres

--
Please excuse brevity and formatting - I am writing this on my mobile phone.

Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#49Thom Brown
thom@linux.com
In reply to: Andres Freund (#48)
Re: Changeset Extraction v7.5

On 7 February 2014 21:04, Andres Freund <andres@2ndquadrant.com> wrote:

On February 7, 2014 9:58:14 PM CET, Thom Brown <thom@linux.com> wrote:

On 7 February 2014 19:35, Andres Freund <andres@2ndquadrant.com> wrote:

0004: wal_decoding: Documentation for replication slots and changeset

extraction

The usage of pg_create_decoding_replication_slot does show the "(1
row)" line.

The output of "SELECT * FROM pg_replication_slots;" is out-of-date.

There appears to be a column named "slot_name" and "slottype". Could
one of these have or not have the underscore for consistency?

The example also shows output from pg_decoding_slot_get_changes after
inserting 2 rows, but when I run the same example, there are no rows
returned:

# BEGIN;
BEGIN

*# INSERT INTO data(data) VALUES('1');
INSERT 0 1

*# INSERT INTO data(data) VALUES('1');
INSERT 0 1

*# COMMIT;
COMMIT

# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now',
'include-xids', '0');
location | xid | data
----------+-----+------
(0 rows)

I inserted a single row outside of a transaction, and got the expected
output. Then I ran the above again, and got an output, but an
unexpected one:

SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now',
'include-xids', '0');
location | xid | data
-----------+-----+-----------------------------------------------
0/16C8B90 | 769 | BEGIN
0/16C8D50 | 769 | table "data": INSERT: id[int4]:3 data[text]:1
0/16C8D50 | 769 | COMMIT
(3 rows)

And running the transaction with inserts again, there's no output from
that same function command. I always get an output from isolated
INSERT statements. I should point out that in my .psqlrc file I have
"\set ON_ERROR_ROLLBACK". If I use psql -X, this symptom no longer
occurs, so I think the automatic savepoints are interfering, and the
effect appears to be inconsistent.

More complete answer later, but any chance you're using synchronous commit = off?

No:

# show synchronous_commit ;
synchronous_commit
--------------------
on
(1 row)

My custom config is:

wal_level = 'logical'
max_replication_slots = '1'
shared_buffers = 3900MB
temp_buffers = 16MB
work_mem = 16MB
maintenance_work_mem = 256MB
checkpoint_segments = 32
random_page_cost = 1.1
effective_cache_size = 12GB
logging_collector = on
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,client=%h '

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#50Erik Rijkers
er@xs4all.nl
In reply to: Thom Brown (#49)
Re: Changeset Extraction v7.5

On Fri, February 7, 2014 22:09, Thom Brown wrote:

The example also shows output from pg_decoding_slot_get_changes after
inserting 2 rows, but when I run the same example, there are no rows

FWIW, works for me:

testdb=# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
location | xid | data
----------+-----+------
(0 rows)

testdb=# BEGIN; INSERT INTO data(data) VALUES('1'); INSERT INTO data(data) VALUES('1'); COMMIT;
testdb=# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
location | xid | data
-----------+------+------------------------------------------------
0/2B81ED0 | 1973 | BEGIN
0/2B823A8 | 1973 | table "data": INSERT: id[int4]:14 data[text]:1
0/2B823A8 | 1973 | table "data": INSERT: id[int4]:15 data[text]:1
0/2B823A8 | 1973 | COMMIT
(4 rows)

testdb=# SELECT * FROM pg_decoding_slot_get_changes('regression_slot', 'now', 'include-xids', '0');
location | xid | data
----------+-----+------
(0 rows)

( output of "SELECT * FROM pg_replication_slots;" is, indeed, out-of-date.)

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#51Thom Brown
thom@linux.com
In reply to: Erik Rijkers (#50)
Re: Changeset Extraction v7.5

On 7 February 2014 21:28, Erik Rijkers <er@xs4all.nl> wrote:

On Fri, February 7, 2014 22:09, Thom Brown wrote:

The example also shows output from pg_decoding_slot_get_changes after
inserting 2 rows, but when I run the same example, there are no rows

FWIW, works for me:

Can you confirm you're running it with ON_ERROR_ROLLBACK set?

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#52Erik Rijkers
er@xs4all.nl
In reply to: Thom Brown (#51)
Re: Changeset Extraction v7.5

On Fri, February 7, 2014 22:29, Thom Brown wrote:

On 7 February 2014 21:28, Erik Rijkers <er@xs4all.nl> wrote:

On Fri, February 7, 2014 22:09, Thom Brown wrote:

The example also shows output from pg_decoding_slot_get_changes after
inserting 2 rows, but when I run the same example, there are no rows

FWIW, works for me:

Can you confirm you're running it with ON_ERROR_ROLLBACK set?

Ah, no, I missed that. You're right: with that, behaviour is the same here as you described.

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#53Andres Freund
andres@2ndquadrant.com
In reply to: Thom Brown (#46)
Re: Changeset Extraction v7.5

On 2014-02-07 20:58:14 +0000, Thom Brown wrote:

On 7 February 2014 19:35, Andres Freund <andres@2ndquadrant.com> wrote:

0004: wal_decoding: Documentation for replication slots and changeset extraction

The usage of pg_create_decoding_replication_slot does show the "(1 row)" line.

The output of "SELECT * FROM pg_replication_slots;" is out-of-date.

Thanks, refreshed.

There appears to be a column named "slot_name" and "slottype". Could
one of these have or not have the underscore for consistency?

That's luckily already fixed...

The example also shows output from pg_decoding_slot_get_changes after
inserting 2 rows, but when I run the same example, there are no rows
returned:

And running the transaction with inserts again, there's no output from
that same function command. I always get an output from isolated
INSERT statements. I should point out that in my .psqlrc file I have
"\set ON_ERROR_ROLLBACK". If I use psql -X, this symptom no longer
occurs, so I think the automatic savepoints are interfering, and the
effect appears to be inconsistent.

Thanks, that's a bug indeed. I have experimentally fixed the bug, not
sure whether I like the fix yet, or not.

I've already fixed two issues caused by the rebase onto
858ec11858a914d4c380971985709b6d6b7dd6fc.

Is pushing to git sufficient for you, or shall I rebase and resend the
series?

Thanks!

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#54Thom Brown
thom@linux.com
In reply to: Andres Freund (#53)
Re: Changeset Extraction v7.5

On 7 February 2014 23:43, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-07 20:58:14 +0000, Thom Brown wrote:

On 7 February 2014 19:35, Andres Freund <andres@2ndquadrant.com> wrote:

0004: wal_decoding: Documentation for replication slots and changeset extraction

The usage of pg_create_decoding_replication_slot does show the "(1 row)" line.

The output of "SELECT * FROM pg_replication_slots;" is out-of-date.

Thanks, refreshed.

There appears to be a column named "slot_name" and "slottype". Could
one of these have or not have the underscore for consistency?

That's luckily already fixed...

The example also shows output from pg_decoding_slot_get_changes after
inserting 2 rows, but when I run the same example, there are no rows
returned:

And running the transaction with inserts again, there's no output from
that same function command. I always get an output from isolated
INSERT statements. I should point out that in my .psqlrc file I have
"\set ON_ERROR_ROLLBACK". If I use psql -X, this symptom no longer
occurs, so I think the automatic savepoints are interfering, and the
effect appears to be inconsistent.

Thanks, that's a bug indeed. I have experimentally fixed the bug, not
sure whether I like the fix yet, or not.

I've already fixed two issues caused by the rebase onto
858ec11858a914d4c380971985709b6d6b7dd6fc.

Is pushing to git sufficient for you, or shall I rebase and resend the
series?

Sure, push it to git, I'll add your remote repo and checkout that branch.

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#55Andres Freund
andres@2ndquadrant.com
In reply to: Thom Brown (#54)
Re: Changeset Extraction v7.5

Hi,

Only got to this now, was a bit too tired and needed to catch up on some
real-world stuff...

On 2014-02-08 00:16:07 +0000, Thom Brown wrote:

On 7 February 2014 23:43, Andres Freund <andres@2ndquadrant.com> wrote:

Thanks, that's a bug indeed. I have experimentally fixed the bug, not
sure whether I like the fix yet, or not.

I've already fixed two issues caused by the rebase onto
858ec11858a914d4c380971985709b6d6b7dd6fc.

Is pushing to git sufficient for you, or shall I rebase and resend the
series?

Sure, push it to git, I'll add your remote repo and checkout that branch.

Ok, I roughly went with my initial plan to fix this and I've added (and
fixed) a regression for this.

Pushed this and some other improvements to
http://git.postgresql.org/gitweb/?p=users/andresfreund/postgres.git;a=summary
branch xlog-decoding-rebasing-remapping

Thanks!

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#56Thom Brown
thom@linux.com
In reply to: Andres Freund (#55)
Re: Changeset Extraction v7.5

On 8 February 2014 17:52, Andres Freund <andres@2ndquadrant.com> wrote:

Hi,

Only got to this now, was a bit too tired and needed to catch up on some
real-world stuff...

On 2014-02-08 00:16:07 +0000, Thom Brown wrote:

On 7 February 2014 23:43, Andres Freund <andres@2ndquadrant.com> wrote:

Thanks, that's a bug indeed. I have experimentally fixed the bug, not
sure whether I like the fix yet, or not.

I've already fixed two issues caused by the rebase onto
858ec11858a914d4c380971985709b6d6b7dd6fc.

Is pushing to git sufficient for you, or shall I rebase and resend the
series?

Sure, push it to git, I'll add your remote repo and checkout that branch.

Ok, I roughly went with my initial plan to fix this and I've added (and
fixed) a regression for this.

Pushed this and some other improvements to
http://git.postgresql.org/gitweb/?p=users/andresfreund/postgres.git;a=summary
branch xlog-decoding-rebasing-remapping

This appears to be working now. Thanks.

I'll continue to play around with the feature.

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#57Thom Brown
thom@linux.com
In reply to: Thom Brown (#56)
Re: Changeset Extraction v7.5

On 8 February 2014 19:35, Thom Brown <thom@linux.com> wrote:

On 8 February 2014 17:52, Andres Freund <andres@2ndquadrant.com> wrote:

Hi,

Only got to this now, was a bit too tired and needed to catch up on some
real-world stuff...

On 2014-02-08 00:16:07 +0000, Thom Brown wrote:

On 7 February 2014 23:43, Andres Freund <andres@2ndquadrant.com> wrote:

Thanks, that's a bug indeed. I have experimentally fixed the bug, not
sure whether I like the fix yet, or not.

I've already fixed two issues caused by the rebase onto
858ec11858a914d4c380971985709b6d6b7dd6fc.

Is pushing to git sufficient for you, or shall I rebase and resend the
series?

Sure, push it to git, I'll add your remote repo and checkout that branch.

Ok, I roughly went with my initial plan to fix this and I've added (and
fixed) a regression for this.

Pushed this and some other improvements to
http://git.postgresql.org/gitweb/?p=users/andresfreund/postgres.git;a=summary
branch xlog-decoding-rebasing-remapping

This appears to be working now. Thanks.

I'll continue to play around with the feature.

Next issue. Firstly, an out-of-date example:

doc/src/sgml/changesetextraction.sgml

pg_recvlogical --slot test --init -d testdb

There's no option --init. I think this is supposed to be --create.

But also:

$ pg_recvlogical --slot test --create -d testdb
pg_recvlogical: could not send replication command
"CREATE_REPLICATION_SLOT "test" LOGICAL "test_decoding"": extraneous
data in "T" message

But this seems to have created it anyway:

# SELECT * FROM pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | active |
xmin | catalog_xmin | restart_lsn
-----------+---------------+-----------+--------+----------+--------+------+--------------+-------------
test | test_decoding | logical | 16396 | testdb | t |
| | 0/16E2030
(1 row)

If I drop it and run the same command, the same message is emitted.

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#58Andres Freund
andres@2ndquadrant.com
In reply to: Thom Brown (#57)
Re: Changeset Extraction v7.5

On 2014-02-08 21:07:03 +0000, Thom Brown wrote:

I'll continue to play around with the feature.

Next issue. Firstly, an out-of-date example:

doc/src/sgml/changesetextraction.sgml

pg_recvlogical --slot test --init -d testdb

There's no option --init. I think this is supposed to be --create.

Fixed. It used to be --init, but that has changed. Thanks.

$ pg_recvlogical --slot test --create -d testdb
pg_recvlogical: could not send replication command
"CREATE_REPLICATION_SLOT "test" LOGICAL "test_decoding"": extraneous
data in "T" message

Gah. Another merge issue. Fixed. We really need to have infrastructure
for testing binaries...

Thanks,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#59Thom Brown
thom@linux.com
In reply to: Andres Freund (#58)
Re: Changeset Extraction v7.5

On 8 February 2014 21:25, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-08 21:07:03 +0000, Thom Brown wrote:

I'll continue to play around with the feature.

Next issue. Firstly, an out-of-date example:

doc/src/sgml/changesetextraction.sgml

pg_recvlogical --slot test --init -d testdb

There's no option --init. I think this is supposed to be --create.

Fixed. It used to be --init, but that has changed. Thanks.

$ pg_recvlogical --slot test --create -d testdb
pg_recvlogical: could not send replication command
"CREATE_REPLICATION_SLOT "test" LOGICAL "test_decoding"": extraneous
data in "T" message

Gah. Another merge issue. Fixed. We really need to have infrastructure
for testing binaries...

Thanks, no issue with that now.

Got a question about ranges and arrays usage with timestamps... why
are quotes added to these?

timestamptz (no quotes with input or output):
table "a": INSERT: moo[timestamptz]:2014-02-08 22:09:33+00

tstzrange (no quotes with input, but quotes with output):
table "b": INSERT: moo[tstzrange]:["2014-02-08
13:45:22+00","2014-02-08 14:45:42+00")

timestamptz[] (no quotes with input, but quotes with output):
table "c": INSERT: moo[_timestamptz]:{"2010-01-01
13:45:22+00","2010-01-03 14:45:42+00"}

tstzrange[] (one set of quotes with input, two sets of quotes with
output, one set of which are escaped):
table "d": INSERT: moo[_tstzrange]:{"(\"2014-02-08
13:45:22+00\",\"2014-02-08 13:45:42+00\"]","[\"2014-02-07
10:12:19+00\",\"2014-02-07 13:51:16+00\"]"}

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#60Andres Freund
andres@2ndquadrant.com
In reply to: Thom Brown (#59)
Re: Changeset Extraction v7.5

Hi Thom,

On 2014-02-08 22:26:59 +0000, Thom Brown wrote:

Got a question about ranges and arrays usage with timestamps... why
are quotes added to these?

timestamptz (no quotes with input or output):
table "a": INSERT: moo[timestamptz]:2014-02-08 22:09:33+00

tstzrange (no quotes with input, but quotes with output):
table "b": INSERT: moo[tstzrange]:["2014-02-08
13:45:22+00","2014-02-08 14:45:42+00")

timestamptz[] (no quotes with input, but quotes with output):
table "c": INSERT: moo[_timestamptz]:{"2010-01-01
13:45:22+00","2010-01-03 14:45:42+00"}

tstzrange[] (one set of quotes with input, two sets of quotes with
output, one set of which are escaped):
table "d": INSERT: moo[_tstzrange]:{"(\"2014-02-08
13:45:22+00\",\"2014-02-08 13:45:42+00\"]","[\"2014-02-07
10:12:19+00\",\"2014-02-07 13:51:16+00\"]"}

The test_decoding output plugin just uses the default text output
functions for all types, other plugins could do differently. I.e. in all
these cases a SELECT, COPY, pg_dump will also include those quotes.
E.g.
postgres=# SELECT ARRAY[tstzrange(NOW(), NOW() + interval '1 day')];
will format it's output similarly:
{"[\"2014-02-08 23:44:19.82007+01\",\"2014-02-09 23:44:19.82007+01\")"}
(1 row)

Does that answer make sense?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#61Thom Brown
thom@linux.com
In reply to: Andres Freund (#60)
Re: Changeset Extraction v7.5

On 8 February 2014 22:47, Andres Freund <andres@2ndquadrant.com> wrote:

Hi Thom,

On 2014-02-08 22:26:59 +0000, Thom Brown wrote:

Got a question about ranges and arrays usage with timestamps... why
are quotes added to these?

timestamptz (no quotes with input or output):
table "a": INSERT: moo[timestamptz]:2014-02-08 22:09:33+00

tstzrange (no quotes with input, but quotes with output):
table "b": INSERT: moo[tstzrange]:["2014-02-08
13:45:22+00","2014-02-08 14:45:42+00")

timestamptz[] (no quotes with input, but quotes with output):
table "c": INSERT: moo[_timestamptz]:{"2010-01-01
13:45:22+00","2010-01-03 14:45:42+00"}

tstzrange[] (one set of quotes with input, two sets of quotes with
output, one set of which are escaped):
table "d": INSERT: moo[_tstzrange]:{"(\"2014-02-08
13:45:22+00\",\"2014-02-08 13:45:42+00\"]","[\"2014-02-07
10:12:19+00\",\"2014-02-07 13:51:16+00\"]"}

The test_decoding output plugin just uses the default text output
functions for all types, other plugins could do differently. I.e. in all
these cases a SELECT, COPY, pg_dump will also include those quotes.
E.g.
postgres=# SELECT ARRAY[tstzrange(NOW(), NOW() + interval '1 day')];
will format it's output similarly:
{"[\"2014-02-08 23:44:19.82007+01\",\"2014-02-09 23:44:19.82007+01\")"}
(1 row)

Does that answer make sense?

Ah, okay. Thanks.

Another question: in order for logical decoding/replication to be
useful, presumably one would need a primary key on every table? It's
just I haven't seen this mentioned on the changeset extraction page in
the docs.

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#62Andres Freund
andres@2ndquadrant.com
In reply to: Thom Brown (#61)
Re: Changeset Extraction v7.5

On 2014-02-08 22:58:35 +0000, Thom Brown wrote:

Another question: in order for logical decoding/replication to be
useful, presumably one would need a primary key on every table? It's
just I haven't seen this mentioned on the changeset extraction page in
the docs.

Hm, that's a good point. 07cacba983ef79be4a84fcd0e0ca3b5fcb85dd65 added
configurability for that, but there at least should be a link to
http://www.postgresql.org/docs/devel/static/sql-altertable.html with
some additional words.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#63Thom Brown
thom@linux.com
In reply to: Andres Freund (#62)
Re: Changeset Extraction v7.5

On 8 February 2014 23:08, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-08 22:58:35 +0000, Thom Brown wrote:

Another question: in order for logical decoding/replication to be
useful, presumably one would need a primary key on every table? It's
just I haven't seen this mentioned on the changeset extraction page in
the docs.

Hm, that's a good point. 07cacba983ef79be4a84fcd0e0ca3b5fcb85dd65 added
configurability for that, but there at least should be a link to
http://www.postgresql.org/docs/devel/static/sql-altertable.html with
some additional words.

# CREATE TABLE test (id serial primary key, val int);
CREATE TABLE

# INSERT INTO test (val) SELECT generate_series(1,3);
INSERT 0 3

# ALTER TABLE test ADD COLUMN a decimal DEFAULT 2.22;
ALTER TABLE

# ALTER TABLE test ADD COLUMN b json DEFAULT '{"a":[1,2,3],"b":[4,5,6]}';
ALTER TABLE

The output generated by those last 2 statements is:

BEGIN 891
table "pg_temp_16552": INSERT: id[int4]:1 val[int4]:1 a[numeric]:2.22
table "pg_temp_16552": INSERT: id[int4]:2 val[int4]:2 a[numeric]:2.22
table "pg_temp_16552": INSERT: id[int4]:3 val[int4]:3 a[numeric]:2.22
COMMIT 891
BEGIN 892
table "pg_temp_16552": INSERT: id[int4]:1 val[int4]:1 a[numeric]:2.22
b[json]:{"a":[1,2,3],"b":[4,5,6]}
table "pg_temp_16552": INSERT: id[int4]:2 val[int4]:2 a[numeric]:2.22
b[json]:{"a":[1,2,3],"b":[4,5,6]}
table "pg_temp_16552": INSERT: id[int4]:3 val[int4]:3 a[numeric]:2.22
b[json]:{"a":[1,2,3],"b":[4,5,6]}
COMMIT 892

This is showing inserts into the temp table as part of the operation.
Is that sufficient?

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#64Andres Freund
andres@2ndquadrant.com
In reply to: Thom Brown (#63)
Re: Changeset Extraction v7.5

On 2014-02-09 00:49:31 +0000, Thom Brown wrote:

# ALTER TABLE test ADD COLUMN a decimal DEFAULT 2.22;
ALTER TABLE

# ALTER TABLE test ADD COLUMN b json DEFAULT '{"a":[1,2,3],"b":[4,5,6]}';
ALTER TABLE

The output generated by those last 2 statements is:

BEGIN 891
table "pg_temp_16552": INSERT: id[int4]:1 val[int4]:1 a[numeric]:2.22
table "pg_temp_16552": INSERT: id[int4]:2 val[int4]:2 a[numeric]:2.22
table "pg_temp_16552": INSERT: id[int4]:3 val[int4]:3 a[numeric]:2.22
COMMIT 891
BEGIN 892
table "pg_temp_16552": INSERT: id[int4]:1 val[int4]:1 a[numeric]:2.22
b[json]:{"a":[1,2,3],"b":[4,5,6]}
table "pg_temp_16552": INSERT: id[int4]:2 val[int4]:2 a[numeric]:2.22
b[json]:{"a":[1,2,3],"b":[4,5,6]}
table "pg_temp_16552": INSERT: id[int4]:3 val[int4]:3 a[numeric]:2.22
b[json]:{"a":[1,2,3],"b":[4,5,6]}
COMMIT 892

This is showing inserts into the temp table as part of the operation.
Is that sufficient?

I think it's a good thing for now. We don't have support for DDL
replication so it's not yet that interesting, but having the new values
allows to safely handle things like DEFAULTs that produce
nondeterministic data.
What do you think?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#65Thom Brown
thom@linux.com
In reply to: Andres Freund (#64)
Re: Changeset Extraction v7.5

On 9 February 2014 01:06, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-09 00:49:31 +0000, Thom Brown wrote:

# ALTER TABLE test ADD COLUMN a decimal DEFAULT 2.22;
ALTER TABLE

# ALTER TABLE test ADD COLUMN b json DEFAULT '{"a":[1,2,3],"b":[4,5,6]}';
ALTER TABLE

The output generated by those last 2 statements is:

BEGIN 891
table "pg_temp_16552": INSERT: id[int4]:1 val[int4]:1 a[numeric]:2.22
table "pg_temp_16552": INSERT: id[int4]:2 val[int4]:2 a[numeric]:2.22
table "pg_temp_16552": INSERT: id[int4]:3 val[int4]:3 a[numeric]:2.22
COMMIT 891
BEGIN 892
table "pg_temp_16552": INSERT: id[int4]:1 val[int4]:1 a[numeric]:2.22
b[json]:{"a":[1,2,3],"b":[4,5,6]}
table "pg_temp_16552": INSERT: id[int4]:2 val[int4]:2 a[numeric]:2.22
b[json]:{"a":[1,2,3],"b":[4,5,6]}
table "pg_temp_16552": INSERT: id[int4]:3 val[int4]:3 a[numeric]:2.22
b[json]:{"a":[1,2,3],"b":[4,5,6]}
COMMIT 892

This is showing inserts into the temp table as part of the operation.
Is that sufficient?

I think it's a good thing for now. We don't have support for DDL
replication so it's not yet that interesting, but having the new values
allows to safely handle things like DEFAULTs that produce
nondeterministic data.
What do you think?

Okay, I'm just checking. If it's expected behaviour to you, it's good
enough for me.

--
Thom

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#66Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#45)
Re: Changeset Extraction v7.5

On Fri, Feb 7, 2014 at 2:35 PM, Andres Freund <andres@2ndquadrant.com> wrote:

attached you can find the next version of the patchset.

As usual, I'm going to be reviewing patch 1. The definition of "patch
1" has changed quite a few times over the past year, but that's
usually the one I'm reviewing.

+ * contents of records in here xexcept turning them into a more usable

Typo.

+                       /*
+                        * XXX: There doesn't seem to be a usecase for decoding
+                        * HEAP_NEWPAGE's. Its only used in various
indexam's and CLUSTER,
+                        * neither of which should be relevant for the logical
+                        * changestream.
+                        */

There's a level of uncertainty here that doesn't seem consistent with
calling this a finished patch. It's also not a complete list of
places where log_newpage() is called, but frankly I don't think that
should be the aim of this comment. The only relevant question is
whether we ever use XLOG_HEAP_NEWPAGE to log heap changes that are
relevant to logical replication. I think we don't.

+ /* FIXME: skip if wrong db? */

It's time to fish or cut bait.

+                       /*
+                        * XXX: As a future feature, we could replay
the transaction and
+                        * prepare it as well, allowing for 2PC via
logical decoding.
+                        */

Let's try to avoid using XXX (or FIXME) for things that really mean TODO.

I think this comment deserves to be expanded a bit, too. Maybe
something like: "Right now, logical decoding ignores PREPARE
TRANSACTION and simply decodes the subsequent COMMIT TRANSACTION or
ROLLBACK TRANSACTION just as it would a regular COMMIT or ROLLBACK.
In the future, we might want to change this. Decoding PREPARE might
enable future code to prepare each locally prepared transaction on the
remote side before doing a COMMIT TRANSACTION locally, allowing for
logical synchronous replication."

+                       /*
+                        * If the record wasn't part of a transaction,
it will not have
+                        * caused invalidations and thus isn't
important when building
+                        * snapshots. If it was part of a transaction,
that transaction
+                        * just performed DDL because those are the
only codepaths using
+                        * inplace updates.
+                        */

Under what circumstances do we issue in-place updates not associated
with a transaction? And under what circumstances do we issue in-place
updates that ARE associated with a transaction?

+ * XXX: At some point we might want to execute the transaction's

The XXX again seems needless; the comment is fine as it stands.

+                               /*
+                                * Abort all transactions that we keep
track of that are older
+                                * than ->oldestRunningXid. This is
the most convenient spot

I think writing ->membername is poor commenting style. Just leave out
the arrow, or write "the WAL record's oldestRunningXid."

+/*
+ * Get the data from the various forms of commit records and pass it
+ * on to snapbuild.c and reorderbuffer.c
+ */

This is a lousy comment. I suggest something like: "Currently, each
transaction is decoded only once it commit, so the arrival of a commit
record means that we can now decode the changes made by this toplevel
transaction and all of its committed subtransactions, unless we have
to skip it because the replication system isn't fully initialized yet.
Whether decoding the transaction or not, we must take note of any
invalidations it issues, as those will affect the snapshot used for
decoding of *other* transactions."

+/*
+ * Get the data from the various forms of abort records and pass it on to
+ * snapbuild.c and reorderbuffer.c
+ */

Suggest: "When a transaction abort is detected, we throw away any data
we've stashed away for possible future decoding of that transaction.
Knowledge of the abort may also help us establish our initial snapshot
when logical decoding is first initiated."

+/*
+ * Set the xmin required for decoding snapshots for the specific decoding
+ * slot.
+ */
+void
+IncreaseLogicalXminForSlot(XLogRecPtr lsn, TransactionId xmin)

I'm thinking this and everything that follows, up through
LogicalDecodingCountDBSlots, probably should be moved to slot.c.

+ /* XXX: Add the current LSN? */

+1.

+ /* shorter lines... */
+ slot = MyReplicationSlot;

If you're going to do this, which seems like it's probably a good
idea, do it at the top of the function and use it all the way through
instead of doing it in the middle.

+       if (MyReplicationSlot == NULL)
+               elog(ERROR, "need a current slot");
+
+       if (is_init && start_lsn != InvalidXLogRecPtr)
+               elog(ERROR, "Cannot INIT_LOGICAL_REPLICATION at a
specified LSN");
+
+       if (is_init && plugin == NULL)
+               elog(ERROR, "Cannot INIT_LOGICAL_REPLICATION without a
specified plugin");

One of these error messages is not like the others.

+       context = AllocSetContextCreate(CurrentMemoryContext,
+
 "Changeset Extraction Context",
+
 ALLOCSET_DEFAULT_MINSIZE,
+
 ALLOCSET_DEFAULT_INITSIZE,
+
 ALLOCSET_DEFAULT_MAXSIZE);

I have my doubts about whether it's wise to make this the child of
CurrentMemoryContext. Certainly, if we do that, then expectations
around what that context is need to be documented. Short-lived
contexts are presumably unsuitable.

+                * Lets start with enough information if we can, so
log a standby
+                * snapshot and start decoding at exactl that position.

Let's. Exactly.

+ * the xlog records didn't result in anyting
relevant for

anything.

+ elog(LOG, "cannot stream from %X/%X, minimum
is %X/%X, forwarding",

This isn't very clear, and I don't think it follows style guidelines either.

+               /* register output plugin name with slot */
+               strncpy(NameStr(MyReplicationSlot->data.plugin), plugin,
+                               NAMEDATALEN);
+               NameStr(MyReplicationSlot->data.plugin)[NAMEDATALEN - 1] = '\0';

Hmm. Shouldn't this be delegated to something in slot.c? Why don't
we need the lock? Why don't we need to fsync() the change?

+               /*
+                * Acquire the current global xmin value and directly
set the logical
+                * xmin before releasing the lock if necessary. We do
this so wal
+                * decoding is guaranteed to have all catalog rows
produced by xacts
+                * with an xid > walsnd->xmin available.
+                *
+                * We can't let ReplicationSlotsComputeRequiredXmin() lock the
+                * procarray as that acquires ProcArrayLock separately
which would
+                * open a short window for the global xmin to advance
above our xmin.
+                */
+               LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+               slot->effective_catalog_xmin =
GetOldestSafeDecodingTransactionId();
+               slot->data.catalog_xmin = slot->effective_catalog_xmin;
+
+               ReplicationSlotsComputeRequiredXmin(true);
+
+               LWLockRelease(ProcArrayLock);

I don't understand this.

+ (errmsg("changeset extraction started,
extracting changes after %X/%X, reading from %X/%X",

Needs some style work. What does "extracting changes after %X/%X"
really mean? Also, how about including the slot name in there?

+ * Performoutput plugin write into tuplestore.

Space.

+       /*
+        * XXX: maybe we ought to assert ctx->out is in database encoding when
+        * we're writing textual output.
+        */

Good idea.

+               /*
+                * FIXME: we're going to have to do something more
intelligent about
+                * timelines on standby's. Use readTimeLineHistory() and
+                * tliOfPointInHistory() to get the proper LSN?
+                */

So what's the plan for that?

+               /*
+                * XXX: It'd be way nicer to be able to use the
walsender waiting logic
+                * here, but that's not available in all environments.
+                */

I don't understand this.

pg_create_decoding_replication_slot() should go in slotfuncs.c.

+/* number of changes kept in memory, per transaction */
+const Size     max_memtries = 4096;
+
+/* Size of the slab caches used for frequently allocated objects */
+const Size     max_cached_changes = 4096 * 2;
+const Size     max_cached_tuplebufs = 4096 * 2;                /* ~8MB */
+const Size     max_cached_transactions = 512;

Hmm. Is max_memtries the number of "tries" you keep in "mem"? Or is
"tries" an inadvertent abbreviation for "entries" or something? Also,
there's no real discussion here of the logic behind these values, or
the performance or memory impact of changing them.

+ * Free an ReorderBufferTXN. Deallocation might be delayed for efficiency
+ * purposes.

Wow, so we have a bespoke dllist for caching these objects, and that's
actually material to performance? What is the allocation/deallocation
rate here?

+/*
+ * FIXME: better comment and/or name
+ */

If not now, then when?

+               ReorderBufferChange *next_change =
+               dlist_container(ReorderBufferChange, node, next);

Formatting.

+ * ->subxip contains all txids that belong to our transaction which we

snap->subxip

+        * XXX: ->nsubxcnt can be out of date when subtransactions abort, count
+        * manually.

Why is this an XXX?

+                       if (GetTopTransactionIdIfAny() != InvalidTransactionId)
+                               elog(ERROR, "cannot replay using sub,
already allocated xid %u",
+                                        GetTopTransactionIdIfAny());

Message style. "cannot replay using top", too. Also, what makes this
elog() material? If decoding can be performed from a user session
this seems likely to be (blech!) user-facing.

+ /* XXX: we could skip
snapshots in non toplevel txns */

TODO. Or fix it.

+               /*
+                * don't do a ReorderBufferCleanupTXN here, with the
vague idea of
+                * allowing to retry decoding.
+                */

It's a bit late in the cycle for such vagueness.

+ * Rejigger change->newtuple to point to in-memory toast tuples instead to
+ * on-disk toast tuples that may not longer exist (think DROP TABLE or VACUUM).
+ *
+ * We cannot replace unchanged toast tuples though, so those will still point
+ * to on-disk toast data.

Why is that OK?

+ * location indicated by 'lsn'. Returns true if successfull, false otherwise.

Extra "l".

My eyes are glazing over, so I'm stopping here for now.

Generally, I think there's a lot of good stuff in here, but I think
you need to make a serious pass through here and try to get rid of all
the things marked XXX and FIXME, either by changing them to say TODO
(or nothing), or by deciding that they're OK and removing the comment,
or by fixing them. It's fine to have some XXX comments on points
where you're hoping for reviewer feedback, but the time to have notes
in there for yourself is long past. Also, you need to either go
through and make a studious attempt to fix all the typographical
errors and message style issues, or you need to find someone else who
can help you with that. Preferably not me, because I'd rather focus
on things of somewhat greater significance.

Generally, I find decode.c to be relatively straightforward, and it's
even got a nice long header comment explaining what it does.
logical.c, on the other hand, has a one-line header comment. As I
mentioned above, I think a lot of the stuff in this file properly
belongs elsewhere, so maybe that's not so bad. But it could probably
use at least a little more work.

To the extent that it's possible, the documentation should be
incorporated into the patches that introduce the corresponding
facilities rather than being a separate patch all of its own.

The meat of the patch seems to be reorderbuffer.c. That file needs
more and better explanations of what is being done and why it is being
done. For example:

+/*
+ * Abort a transaction that possibly has previous changes. Needs to be done
+ * independently for toplevel and subtransactions.
+ */
+void
+ReorderBufferAbort(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn)

It's already clear from the name of the function and how it's used
elsewhere that it gets called when a transaction aborts. Mentioning
that the function gets invoked for both toplevel and subtransactions
is, surely, worthwhile. But the function has no comments explaining
what it's doing in response to that abort, or why it's doing those
things, or why it's doing those things in that order rather than some
other order. Here is an example of a better comment:

+/*
+ * Setup the base snapshot of a transaction. That is the snapshot that is used
+ * to decode all changes until either this transaction modifies the catalog or
+ * another catalog modifying transaction commits.
+ */

Now, the grammar there might need a tad of work, but there's a lot of
useful information in that comment. It would be even better if there
were a comment explaining, either here or in the caller, how we decide
*when* to call this function.

Both reorderbuffer.c and snapbuild.c contain a significant number of
functions that are quite short. I can't decide whether this is
excellent attention to abstraction boundaries or a sign that the
abstraction boundary is too permeable in the first place.

This email is a bit down in the trenches; I will try to write another
with some higher-level considerations. But I think there is plenty of
stuff here for you to get started fixing.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#67Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#66)
Re: Changeset Extraction v7.5

Hi!

On 2014-02-11 11:22:24 -0500, Robert Haas wrote:

+ * contents of records in here xexcept turning them into a more usable

Typo.

+                       /*
+                        * XXX: There doesn't seem to be a usecase for decoding
+                        * HEAP_NEWPAGE's. Its only used in various
indexam's and CLUSTER,
+                        * neither of which should be relevant for the logical
+                        * changestream.
+                        */

There's a level of uncertainty here that doesn't seem consistent with
calling this a finished patch. It's also not a complete list of
places where log_newpage() is called, but frankly I don't think that
should be the aim of this comment. The only relevant question is
whether we ever use XLOG_HEAP_NEWPAGE to log heap changes that are
relevant to logical replication. I think we don't.

You're right, we currently don't. I guess we should add a comment to
log_newpage()/buffer to make sure that's not violated in future code,
that seems like the only place that's somewhat likely to be read?

Decoding PREPARE might
enable future code to prepare each locally prepared transaction on the
remote side before doing a COMMIT TRANSACTION locally, allowing for
logical synchronous replication."

We do support logical synchronous replication over the walsender
interface, what it would allow us to do would be some form of 2pc...

I'll adapt your version.

+                       /*
+                        * If the record wasn't part of a transaction,
it will not have
+                        * caused invalidations and thus isn't
important when building
+                        * snapshots. If it was part of a transaction,
that transaction
+                        * just performed DDL because those are the
only codepaths using
+                        * inplace updates.
+                        */

Under what circumstances do we issue in-place updates not associated
with a transaction? And under what circumstances do we issue in-place
updates that ARE associated with a transaction?

vacuum updates relfrozenxid outside a transaction, e.g. create/drop
index, analyze inside one.

+/*
+ * Get the data from the various forms of commit records and pass it
+ * on to snapbuild.c and reorderbuffer.c
+ */

This is a lousy comment. I suggest something like: "Currently, each
transaction is decoded only once it commit, so the arrival of a commit
record means that we can now decode the changes made by this toplevel
transaction and all of its committed subtransactions, unless we have
to skip it because the replication system isn't fully initialized yet.
Whether decoding the transaction or not, we must take note of any
invalidations it issues, as those will affect the snapshot used for
decoding of *other* transactions."

+/*
+ * Get the data from the various forms of abort records and pass it on to
+ * snapbuild.c and reorderbuffer.c
+ */

Suggest: "When a transaction abort is detected, we throw away any data
we've stashed away for possible future decoding of that transaction.
Knowledge of the abort may also help us establish our initial snapshot
when logical decoding is first initiated."

Hm, those should go into reorderbuffer.c instead, the interesting part
of DecodeCommit/DecodeAbort is just to centralize the handling of the
various forms of commit/abort records. decode.c really shouldn't need to
be changed much when we start to optionally support streaming out changes
immediately.

+               /* register output plugin name with slot */
+               strncpy(NameStr(MyReplicationSlot->data.plugin), plugin,
+                               NAMEDATALEN);
+               NameStr(MyReplicationSlot->data.plugin)[NAMEDATALEN - 1] = '\0';

Hmm. Shouldn't this be delegated to something in slot.c? Why don't
we need the lock?

I wasn't sure, we can place it there, but it doesn't really need to know
about these details either. Lockingwise I don't see it needing more,
nobody but the slot that has it acquired is interested in it.

Why don't we need to fsync() the change?

I've since pushed a patch that does the fsyncing. Not doing so was part
of a rebase screwup.

+               /*
+                * FIXME: we're going to have to do something more
intelligent about
+                * timelines on standby's. Use readTimeLineHistory() and
+                * tliOfPointInHistory() to get the proper LSN?
+                */

So what's the plan for that?

Prohibit decoding on the standby for now. Not sure how to deal with the
relevant code, leave it there, #ifdef it out, remove it?

+               /*
+                * XXX: It'd be way nicer to be able to use the
walsender waiting logic
+                * here, but that's not available in all environments.
+                */

I don't understand this.

The walsender get's notified when flushing WAL, which allows the
walsender specific read_page callback to wait on the walsender
latch. For normal backends that's not available, so we have to do a
check/sleep/repeat logic.

pg_create_decoding_replication_slot() should go in slotfuncs.c.

I wasn't sure about where to place it.

+ * Free an ReorderBufferTXN. Deallocation might be delayed for efficiency
+ * purposes.

Wow, so we have a bespoke dllist for caching these objects, and that's
actually material to performance? What is the allocation/deallocation
rate here?

It's absolutely massively relevant for performance, I was really
surprised. reorderbuffer.c was the original reason for developing
ilist.h...
Before doing this, memory allocation was by far the top profile,
afterwards it has left the top ten.

I've tried my memory manager rewrite on it, but it didn't fix things
sufficiently. I don't think there's anything as good as a per-type slab
allocation (which this essentially boils down to, even if it has a
higher memory overhead) for frequently allocated types.

+        * XXX: ->nsubxcnt can be out of date when subtransactions abort, count
+        * manually.

Why is this an XXX?

For me XXX really is "watch out", that's the only reason.

+               /*
+                * don't do a ReorderBufferCleanupTXN here, with the
vague idea of
+                * allowing to retry decoding.
+                */

It's a bit late in the cycle for such vagueness.

Well, I sure think people (including me) will continue to work on
this. There's not much downside to not doing a cleanup here, it will be
cleaned up later.

+ * Rejigger change->newtuple to point to in-memory toast tuples instead to
+ * on-disk toast tuples that may not longer exist (think DROP TABLE or VACUUM).
+ *
+ * We cannot replace unchanged toast tuples though, so those will still point
+ * to on-disk toast data.

Why is that OK?

Because we currently only allow accessing changed toast tuples. We'd
discussed that a long time back and it seemed people agree that that's
fair enough initially. In fact, more people were interested in that
behaviour than in doing it differently.
Alternatively we can vacuum toast tables less agressively or WAL log
more.

This email is a bit down in the trenches; I will try to write another
with some higher-level considerations. But I think there is plenty of
stuff here for you to get started fixing.

Yes, working on it. I'll push the smaller increments to git, ok?

Working on all the issues now, thanks!

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#68Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#66)
Re: Changeset Extraction v7.5

On 2014-02-11 11:22:24 -0500, Robert Haas wrote:

+       context = AllocSetContextCreate(CurrentMemoryContext,
+
"Changeset Extraction Context",
+
ALLOCSET_DEFAULT_MINSIZE,
+
ALLOCSET_DEFAULT_INITSIZE,
+
ALLOCSET_DEFAULT_MAXSIZE);

I have my doubts about whether it's wise to make this the child of
CurrentMemoryContext. Certainly, if we do that, then expectations
around what that context is need to be documented. Short-lived
contexts are presumably unsuitable.

Well, it depends on the type of usage. In the walsender, yes, it needs
to be a longliving context. Not so much in the SQL case, inside the SRF
we spill all the data into a tuplestore after which we are done. I don't
see which context would be more suitable as a default parent; it used to
be TopMemoryContext but that requires pointless cleanup routines to
handle errors...

So I think documenting the requirement is the best way?

I'm working on the other comments, pushing individual changes to
git. Will send a new version onlist once I'm through.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#69Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#1)
5 attachment(s)
Re: Changeset Extraction v7.6

Hi,

On 2014-02-11 11:22:24 -0500, Robert Haas wrote:

[loads of comments]

I tried to address all the points you mentioned.

Except:
* I ended up only moving some functions from logical.c to slot.c, not sure
if it's the right split now.
* I couldn't merge the docs entirely to the commits, that'd be a
horrible mess right now, since the the new sgml file refers to all the
tools and output methods. I think that'd make changing things too hard.

News:
* loads of comment, error reporting, documentation improvements
* output plugins now have to specify whether they output data textually
or in binary so the text SQL interface functions can refuse if it's binary.
* changeset extraction while in recovery is disallowed for now
* some more tests were added
Bugs fixed:
* pg_recvlogical could accidently close stdout if -f - was specified and
the connection died.
* the WAL reservation wasn't working when initially creation a slot,
only a bit later.
* typo in pg_replication_slots lead to catalog_xmin not being displayed.
* 8de3e410faa06ab20ec1aa6d0abb0a2c040261ba required some minor changes

Thanks to Christian Kruse for helping me!

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-wal_decoding-Introduce-logical-changeset-extraction.patch.gzapplication/x-patch-gzipDownload
����R0001-wal_decoding-Introduce-logical-changeset-extraction.patch�]ys�F��;�Sz��d� ��96�L���������b
���h�������1R�D��D&��c��MOc ���)�:��������#��F��������^���f-eLUv����e�����Z=�i�ZJ�=���cS��C���35�#�o�&����hh���;�������'5�^�����uI���Z��7���n�������G�4��C��1��ji�y�#��k[��2bX7�J
�N�y�����������T�'�C�����5��!��	���j�k��#��k:2��nZQ-����.*��A�ek���A�s�M`�X��l$&c��R������dB5�i��c��Q�A�'�X�;��`0(�1��S�����Xfg0�����n:5r?��	|h���0T2������(�7*�&����J����7��j�������B��W*6�w";���N��hf��C�����1�Y&���U���n��m�����&Sp"�$�b3�8l�
14���Vq\3%�4����|/��m�����rl�[,�R�#���:h[wFw���R�����V�8�ei��fB�����������MAgO���#a��sD�[�B����
����
������Tw����j��Y��X�oz�X��u�	}�	���+k�l�|���w���Gf�����h��������Y0�rbS��\��`"�Z�F�\��q�W�N����'Q�a��vC�����I>����@������:9�M������{�]'����D�spe�D�x:0�S�+����\.2:���
&N�yNo�X�HZ���RHuN��|VH|�C|�?~w�����&f_g{Lk�t��S���%7�,B��z�a>�/��`���?�e\����w0�� �2���W������-0w���iC?18=��a�iTd�p���g����+���6���g1�H�:*@�VRkN|s^L�Z�1�I�e��W�.X�8m�C
 Wudq����%I/��H�^H,���������2^J����&cb�)q�sDr���'S#�5O�l�hp�t����'�3����Db��is�91��"6%�H��#9��^W��y� n�)���\g%�q�eD'9���B����e�
?��6G�R��
��L�����o������Q`=�6��7W	�5�qcX#�X��~��Fb�]��5��BA��Rv��i��!q����~|�k���a�����P�}���y^w����(����/iH!����u���,�y���E���Y���*V�Xj�9u�������:'���b
A�	[:��O�!=H����� ���VZ���(x�i��L����y�(-���6��y����b`u����Rn�(��`���I!�(�*~aW�CX7�9�Js{��8��R�}l���K�N+<��b~��q>���rx����/������*I5E������%�����t:�O�0���eK���6�aM}�6g��R���d��k:���P���(3��9�Z���``��C0�x5��63����b/�����G���s#��/Kq�nc���	��]m��������&�;8�E�N�|��di������Y��V���I)������jv3�@��N�<�N~5ISGs�G�L�%�@������p����)�E�Ej(�Pqj.�0�8��I���BB@��s@�[�GJ���p�b������!�@A3s�\_g��X@���;J-�P��SeR;�r���T\�J>e@���(�$����3�d$��+nR�~9�4���zM$��e���
���tfLcc�a�N����p�!\�Xr���V����u�a6o��Twk�� 3��P��������;��m�w���%HD����-���7�'�A���=��T�p6�UtH��a�.C�
��
��%��]�d�=��|d���L�-�2��bIB�yX�J�3,�"�9,Ii����%���a	:y�pY�21!�.KkJ�,��Ii���"Z
K�x�
��}^�E����H!�>okQ�(�R,C��%J�&v�h�R��}@����1��ot���Y>���R�*�;J�������CM����L�s,�S�]���/���^��?�> �v����������B������}�_�C#he��j�Ux�r�C�4�6���d:�~�/8����
����m=Z0��'3���|���O����r��rSA��5M�0�`��j�Z���0W��?���j�z~���YmC���R��v���^^$i*����LqjX��V�����8I2_I�8�/��J=��{`ln�@b��0z��a#��| ��35��z��������0�3\�����|�W�����1N�n��wf|
�z�Y9�.���a{D>��O~T��>O./��~Z ����o��	x9���;��]����Wd�g'���\`�.s�����P��J��fC��bT��l4�����6%7���a�����������	�"��Nw0��_���3�tp�*3�3~�!r�?W�,`��O��f����N�z��y9�ybZ�p�(�������?u<���g;��� {�]Hc<adZ&��k�6�c�����g``��1Bgf3�U��q����ceM�k���,�X5P����c>W`�����P�>�lB�'q� >#�c	a�q^b�1	13'��a=���w���C��Hc"�7�iF�����		��b���[F�W�W�W����c����OX����_@^��H1N��={��c�%����Ty�{��.�E;#�:v��2�*��H��?5��t&DE��#��)�p��;1��&m�������#�z:�<;����w>�]��F��7��cY�t�<ds'{r��3U�0��	'=�H�O���������\�TT�s"��9@�c������&1�p���E�BMe��]�*��Gj�/	�,p�t�ie<�L�	Z�*����&���7"E�o����,�����A���dJ�)�Q{S�I����`y�����x��}E��j3x����'��1�Fo�yfYO��-����������LR�i��?w^�����1��uuy�#g&���k�=^�8�*h�����w�
���o��&�D�m��P�AC
i�?��g��k��wE�����s^���e��Cb�K������kd;���.0'�P-���� �Y��QZ������0z;��2�A��0_*E�K��� ��Pk|� �9T��0w��TY���x�����}K��:��-T�	4S�5�sh�p-�������	T����
����
B>����>���dO����	?|su�E�����#��&�vTx�;�-oR�=��X�>Q�h	�!��1z�Mac�������zO,!P(C���?�!.�
��;2�������w��������>���H��H6$���`8/���0�B��K7���g�
�g���8��!�d8�9�������K���sG
�F�w{����������e7d��T��]�������>��N.�>�_pn���O}��K�i��iQ&�Id���^G���(t
�#�7>@�f�3l���U������xPq�~�S�o�����3G$�6��J��(zI�%r!5�w5a!�m�����2w��S���7Q�v.��!'Ii!�>6-������&&����J~����}�h4~�6����G�G4,?���}��	
c�M������7�^`�EC_lq4l��
����,�������W��s���\,��Js1s�M��3��B����K���}"���&�'+��h�T�����Vq�e{��o��	���
��*�Fi�"�����f�_�f���x}���z`-�����M��n��M=��!(�6y�E�l
��NY�.�A�7A6�~quq���������.\X��d�*g�R��R/�*�u#���4�u���`��Uq$�	"������������W�K��ZS��*�L��O5�����Y�!���}�4���A��}��+�x��$��*eH(4U�0��l|���x�<�a7��R��j|��O
;���d@�LT��E2��2��W���p>�����R�B���7�����B?$����?��jZo ����+���G�T����lP&�J�<w�H��g�����_�*��-R'lrx*�
ll*��B�TK��m`&�T����H����6����/�jx1O�)6��U�A6�L�JY�K	T#�lk6���k�>��\b����f������ST��^&e�=S=r�p�/2�3���	�M��A��?�Q=����2h������R�,Jk����|Q9\D����G���
R�Ro��Z�e�h�����������L�#������.��d@���X��q��_��G$.n����^���
��2��8�J<n�S��Ey�y�'��_��@V�(y�2U ����:������,���D�|qk��C�&���_�}������k�o�9[���^d��Z���vL/��^��
��D`�m���/�Q�������#�����1��g�����������0�5�}�����#��Q�eU��^�nPu���w��k�r5#�u?��.5�c���
��x.��� �2XP��5��W�}G������R_���|)���A�/`_��S�/)'#�R�a�j��,aE=�������s�d+A.�.{�$t�Y��I�ly�O}.����(�lEl����P1�.�J�# #����q��>@�b0��1��^��5�N� #lG�l6���[���U�a��2��.�r�-���I���vD��U�3�e0�~�P�l�C����#JnEYn!b]����#�������Qon��1����$���6����,Q��QmbZ&�bj�uk�>�����l�)�S���[`o��=^M�@�9,FL��U��4XN-FI�Y�c���:�/�C	`�,*t�P.X�0��E]r��?��+*_T(q\��)����C��I��,��b f��&�iA��fF���U�L��a�?���2���0B�@�����sp`�G��R�4��qv?a��h7�z{&7Z��]@FX.�"
lK�T��b!�!o�����q���@P��V�����@��������n�_�Y�t@.>���&#z}��I"�lF� ���@��W�7,�~X`���p��cbh5[�(ac�3i!?����=����t����N���e
���I�k1kx��\JMi}%d!��R���D�,8����-�#Z�TG�����{�%��<����A.x����K��L�R�������b�%��;��^w'6���3��:�1�������`�vz|F>]��_�N~��^���@�k��[I;J�������p����`����@�F�p�#HE� ����JK�!�\�6o�v��F�_���*��#���8��2t��V�q���Uc����
��R&��_��#����6W��i��t}�`-d��_
v*K�EKgQq� ,�'��*��W0<���G�+���w�$��4�t-ls�
/��c���,��X�ej�8�NRh;9�f�������������[�����E����������I��(�p��vi�G�Xv��VJ+)����^;�f��V�{�>����������v����;!�����k�
�7�,��U�3]~#b�I����C�|��RWX���^�S��}V%��?�lbiJ����]��h/�G{U=�1=:���iu��5v�&�/��X���������$��j�����o+�g�*��)�3Ut$y���\^F��H��$d��:H���J���nBp;!3U7��W$������C0R��,�NwtT��10������������k=S��a/<�l�D\��(���H�H��Z,I@v�V����H�n�Cz$^��%��Wlf�Sj?A��kb+sM�g�0�X�9�j�`����5�9U��`J�>��}�o��;3�b���7�[|^���h�������m$���k�S`�'1eS2�%�q�(����,y%y�����A$$��"9iY���g����h� E�r���=�X$�T����Uf=2{��l�����RK_�����wW��6^�N��1�9g��� �F��G���1�YI(�)��ht5�~J���tK�w
4���+�\F�hB�:�b�W���e���rH����O�����J5��{�Q���� c{l��k����b����l���jOI�x6f���]�d�\��:S�~�?SC�}m��O������ ���S�� �"�p|�
d�)���ri��X����c��m�/j��}CK��M�h���t3�s�Lk7h�B�h����'���t!�X��j��/����[���������M�e������z[G!�Q+ztn����g���K����]������w�I8��x2vB�<�S�:e�Q�� m��F�q�����q�V�l����O��,��<,���k��]���z���&Z�����������;F� \���}}�j��	�r�t?���~;�|���Em�Q���k��M�������w�n���LtZ�d��Wl�����8;Wy�6�bu�W����Vy�1�jm�~�^^��V�����V+m-��bs��!��r�p�������aQh�b(L��K�4�p7�*g�������������!o	�)����*����tkkksuf�y�v������S��g��G`����c��vYO��������_{��������Y���p���#�I�_�6��)�$>�5���^����������6Wo �Z����3
�wm�l�?����g-�6#��]���wkE��*iV�=g������0���@��4FG��hJ��Kl������6��:n��s>
�}�~<�G�n�)S�����pZ���2�������x�,)G���O������x��<���l���[������ET�h�)��C{�!YTiEV�h���u[s*��T�;����k���Z�p5�;��5�Y���o2��q�3o.haLdR�e��X��t���m��W�4��.)H�MP�,1k�Our"���N��3�<|�I�tp�cP����u��!��Dfj����p@��������s4�U��#6�'�@l�gt������~���e����t4	������4�\����(�N�z�������6\��wz��M�^�ER�#^.�l�/���p��*�K�M���?~���;�f��6��P���_�]7��� u�Oz�s��W���*O��
������!��^xo7��+
?*\@9��z��D���?bc���c�>=�Y<���K��e�P���@�.
�I���h��{r����=I������(�'�<e+��~s���7����K�.���m�.���=��������|>��?No?e-Q��.��hv�����w�LW�hB����
�>��&�P��[��f��bB����b�E�"��J����Z�����@��(���� s�������~;�������G������[��_No�������_x��w�`������z�Xx��;���Pg-`��Q�����_�z�kY��|����[u^���B��5��}�x���^*Q�.-�iP����g|Xfc�,���[{����#�������X\��6��	�?H����a9o�"@�7����rv#^j�)p���u��:�'v�%��s/�������Kt���l���*.^�lHIj�)�V��K�5�8M����^��&�2������W���"�a����������+s
���;<��
^����5x
�}�~�	�����}R_oq��~�{=�N�2|��/E���A��inI��5�;}i�j���l�AY>����c��Oz���^����~<8z�eC�>E����"�/���^��z�J"��^;��O�XY<�|#Y�R���%�L<����h��k�P��l�=�
����H�xa6^�9�sYo��'1�e���e�R����r�w�Y}���2���Xo����y�{���*�������Qc���-��
��q�Jr��~sU���jY��6e4�D�Yv��"�D�Y����&����`Nw�W��w�������Fa��j�ZHj{�l�KT�0c���!�����.�Su���~�[����t���\�=~���N\�R�$W�$��������G���j:��������_���fe�0��Q�0�ksI�]u�Iq:��89��A������n�?�F��/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����������=_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_�����M_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|���������o�������g���|����u�a4�v>F7��G��'g��~�o������j�������5����Cy����<(
G���xm���5[y���.[)S�K[����no�.���M����`]�������\��/�����.jg|�����;�����k�~�"�V��^���fqg�	��0��u��#W!n���l���,�G��p6�q����]v�|�_�p
���M�B�w�P��p�X������`T�^1*��A�q�@�'+�b�����,��~��Gc-4��T�.&d�<�u��A�o���?���fk{�]�T��Z�^mT��Vu��Sm�*�j�V���f�U������J�Z����F�Yo���;�v���6j�z��h6Z���N���4��Z��l4��Vs���l�*�j�����f���n�������vm����nn����w��;���Nm����i��v�wvv��Jj��6j�Rc�p�%�1�K���>���8)�
���01�S����
��0�z������Z�Z���v��v�^�Ku,������z�Z���w��v�Qa{�Z�������F����6v��v�YaW�Z�Y�6��X�V��]m�T��j��Q�j�V��jT[Xm��v��Sm���p�V��W���fu���T����
��S����;��N�����VX/,O��"U��j�Qm7��V��]m��e�3��j�z���U��J�V��Uvj�S�bp90gL��1t���5bq�l:��v�^��I������z�V���wj�v�Q�����X��5Z��v��Sk�k�
�5��&�(��5�k��Z�]kUt���Z�ZX����vj�vm�Bpa���v����mI�L;��vm�BHb�;��N������j;�a`� c���Z�Qk7k�V��]k���������F���WZ��v��S�`q+D
�
�0����*���s��0z�h��b�.�[{������7*�5,!�4����F����7v��v�Y!bu�R���Uon��;�f���C��h�����;������z�]��yt���o7�����v;��v}�B��0��F}�Y�i�w�����*@y@������v���������+�
2�^i4*�F���l7*;�
�����
��a�`?���@_�{�{�(�I9�3`	���
��N��9cb=��n��*J�)Hh�O��hV�)�kXB<i����Fs��l7Z�W�!V/�@�@����F����p+C��ho���Q��il�;�r /`��v���Vc4�
����0
��F��ho7� �����< �V��J�Y�nVv�l�
�)Q�c'�u	�>�VHQ�����
���
�THl�mu����K�B:���s1��3&����G�;���\�`�b�d7��V�����%����v���l���6�W�!V/m�����4����
i�20��vZ���u��
�!v9�0AW ���v�
V^Q!�^\E���l�*;�
�Z�D�$�NH�����V� b'WH_I��2i
�Hp�B��mY'����U����V�T��X'jo������`s�����s���-�J�-�r�s`t�vk�B2��M	\���6��Nk�������a�
��xi<��������=p�V,<�B�r�]�L�Ue{���]��������dE�
8H^�����N�'��AFA+��+dD�_u����h]!����s�p�af�*�d���8Z�"Ja�@`�^!g#T��^\������WI��Y�%������N��d����%���

*`�� l��@C�.^�����lQ!s��V�b��^eg�NY!��P�.'�n�+�X��
y/�^��\��Q���V��I���
��-�d��B�M�V'� %jq�$��
�97s��{��iq���y�o���������U�"V'����\��'V%��8�y|�2���v��!�<�6%p
K�'����
e
�Jp6�W�!V/U(~�E�j�H���-bJ[���m��������b��,�����������T���B��B��B|�BF�B�B��B��Bn�B8�B�����-�����U���mA�� b[P�-��0�`mY��,b[��-k���Y[^k�,Z�<��)��H)�R$�LJ��B9[��*�O
�%)0R,��G���5
e�(`Q���D����
1U(�P��pA���2}�v2p�i2c�\2V�O2I�B2<�52/�(2"�2�2�{�tn�ga�ZT�MG�@:�3-�& ��nnrnenXnKn>n1n$nn
�>�hLd%J�pO����2O2;n�6+TT�E�q�����v��	�(P��hO�b:�q����R���z�y5yi+i�Ui�N���"�dT$�$,�0T"�+��R$�#r}r3RiR�*�2���&E(�dy$�$Q�zT,d���Q�Y��I�I��?�b��
��(d�y�)��qS����l)�Q!�%� E�N������A���u*�>�~`�`�*��T*�~�@�<����<j�3D}�F��b�=��3��������*T�P���x��T�(�����<@���������V�<��A=���������G�m�x�)��z����Q�kQ����z�("P���x����z�#>d��x�a)�`1������V�-����!/>�x�T��z��>�p+����(���H| S�f���B	:4�b!����`y���!(/:$��GY�2e�T�
�V��\SB=*6T_��P��x��< ��C�H"���IZ�������Q�������>|P�E��2$��A�����d|P����e(�< =�V<���A=�Z
(C�7Vd����z��>�x���C�BEI�]�*F��(>��E�B6dg
��@h��0O�����U�:
4����
�<�f)���/
-�Q�`M���<�<�(�lb����zT��0Q-��x<���C	�< ���z���:�B8>���%�=��� �%��P|P����Z�< �)�< |��z��%|h��@GA�"d"	>�x@����}|h��(�<����U�Q��d��C��)�[7�M�FS�h�A=�
����8�<�s��z�d?|P�2_��J�P8�A=���@EY�5�B�v�z��(�Sz�TF�����#�D1IQ�C=*oT����RhD��^��+jW�x@���(�<�
��z��w|�]���ZY�I�< ��Ck�kJ�a_��A=�>�x@��v���8�:!>�x�C���dd|�"E	�Q�]�h���	A�<�U��*��M�J|P��	VZQvZ����#�P��A=��&�mEY.�����x@�������ib���&Q�Q��U��T����Ra�Z*�B���Gu�J!�!���j��P�����z���%���E���P����a�< ^��z�b|h���(x@������Y�.�i[$Z7�{��Bm�� 4�����HEE��Q�<�������<����R����)�PL�A=��=����6��S|������<����x@S��fW*��x@����h���v,�g���z���P�E���3Ud*�b��R�zTP�������Z|�wR���8�	�<����z��|h���x@�����z�V�Fu�cG4Qr�s��h���h��x��W���z�4^|P��F��"�i���z��_|P��:���"$����x@����*f�������1�P`�A=�CDQ�z1>���E��2��� �VT\�1�FZiT��H� �G��f��T���S]�RN�[l�T���VD����P<�A=��b�gP�U4<�?��x@��x���h{�HS�"�&� ��� $���ZE��j�<�U��z�k�@��^�A�l�<�`��z�X������P�F=��6>�x@�Vq�����������<D�<�{��z-�APG=��2T�����p|P��"��s�<�����Z�i1�%�>Z��"C��B���9>�G�
4P����T�I8�U�v1���_�W�'�F������Y�'s�f�y��p`?-}`���t+�����>��n����c��V�N�=T~Z�iI����/Zt����5�*"{6��V����J34f�xx�zP�h��M��F��h��h��
���M�-
�4���$��Q�)OUxZ@+8���Z�G+����L<z��M�4��I�MQ2-W��y>�s��i'���v=��d�4������4���L#)�4j���H����`�2O�3-�����%�!�B��aAh�����X��
����ih��y���Eh�h+(�Q����QQ��UQu}G����T���R���Ju��&�H��m��mT��nQ���D��
U���]�	�
T(�S|�hN��"u[QC�\��O)zR���Hq��^[�G�/�V�(Q��(C1�"H[QL��|�s�j�a�X�O������+�"�nW��~�u�l�PV���D�����l�$��������^��x���Q<j������j��D'k��YygGh�l��|�x��M�[�t�g�<i����������Q<j�G
���E#�Q<j
���Q<j�G
��-HC �Q<j�G��c%�<j�G
��mJc!�Q<j�G
������![�E��x���Q<j�<V@=�C�;���G
��5��x�����b.�d��G
��5��x���!dCv���A�<��G���xJZ��W;E]����u�=w��
��T��Q�g�<k��Fh��-�$��R����,��t�g�<)�y(O=I�hL<��G��3N�<��G��B�hp<��8><�C=��x�!�4�u��x��z�g\�x�!�4�u��x��:�Q���BVi�<��G��u��x�wx�!�{1��:8�:�Q<��G��B��J�
��^��x4�F��$\��5�5�V�}�!z���:B�il�������<�G�h�
h��c���Hy��-�����Fk��tX��Q���<���,O`�Rh�<�G�h4y��z�G�h�vh�<�G�h�Q�h��h <�G�h
����7�<�}��x4���<�G�h���IR���<�G�4�G�h
��x�
z~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~������c�y0	����.�p������v{��@��V>
����=8�?��98����|���0���������=��{���_�Wy�:�����i�y�A�����R0#��}T�{�4 E� .��`\��m`!��4X�m����hbc4��Vs����\[`-l�V��jm�vZ��6��6~��������|��w@nv��;������Mj��6j�R����&���T)A��@��*���0-���05�2T<�Ad��M�T�TpT0T�d���eA�^�6�����"�D��X/��	�	�	�	�I6���� YXN,DL<,��h����a�`��*���`�d��6x�vV���B��n�=�_[WS���I���@����`���`�5a��Z$��N�)��o�n�,�+����11�C�8�Y[�1��d6�@P|��*����p�&�����H����U��:�1v(6��vYX��5A��f@����*`��Z ��!�B��6���-��Ql��ck4����������IpLt�	����E
���`�HMp*0*�)���0)N�"��)���x�l�(�I9�3`	�*m2.b���s��0z�h���eqaaaa�N��T��xrJ"���A�R����&�6W�������G{-�Q�N��mp0�8 /`���Aa��,`,�+`+d~�k����m���������-bC�~T�	.&�B �y�P�����^��I���j��
���
�m���j�1�0�X����[�bp90gL�����D(�;�< =�= >��$�U��O� C-0��2�W�!V/�@�@��A�A��V����Xx�������'��.�&�j�	ZRJBOV��01�v����Ek
( 50��l�
�)Q�c'�u	�>�VHQ�����
���
�THl�mu����K�B:���s1��3&����G�;���\�`�b�d7�`��^���5,!��@�����f�
�J���
4����m{����vL�4[��G{;��x�:�84:PDlt�/���Z��v�
VA����-e��J�/X+�Z�D�$�NH�����V� b'WH_I��2i
�Hp�B��mY'����U����V�T��X'jo������`s�����s���-�J�-�r�s`t�6��yP/lJ��O���vZ�m� l��@C�.^����V����$�����V,��'��z�N�	�a�)A�*d)�mu�5Y���W!�!5��I|1F�Q�Jl�
�W������uZW���c��(�`��
�Y!�"�����R�4���W���:��E�snos�U�rv� B�p@�`�
���d����%���

���[�	��a���x��trQj6�1��4�I�j��2X
u�r���"�o������I��Z�
�a�l���N�@���IF��+��$mu�
R��N�����s3�IQ��Z��
`\!�'��Il�m-����YU(`u�!�o����h�pbU2=������(SA��h
��d����%��Wb���vW�I4���Q�j� ���-�M[���m�"�����1�����Y�������������=�����d�������� �����H�����p���e3�e[�e��e������mA���T[��-`n����mY��,G[&��!������Y�RU[���1*M�i�^E[�Lm����v�lh����v�Hh�h�Il�hK���6���������$�2�`
'�_��R��NI}���(����Q^&s��D}�����Z����n�T�:� �H�I�I���"LRK�J�I�HHBGrF�%V/ ��nnrnenX��a�q�q#q�pS���Dc"+QR�{
��(d�y�)��q��ja���Uu�8yN�����Y�j�Q(�S��O1��8En
����J��2����A����b�c3u*�Q� �"&a����<(ER:"�'7#�&���� �xP��E��,���$�[O,�2�Ay�r��E�{�1�O�.rZ��V
c2�<�H�������l)�Q!�%� E�N������A���u*�>�~`��%S�51����q��d�k�@�&�h��#�"�{�1�g��3��Q5A=�T&�2P1��O!�VS��NU�b;�
�A=�$J-�)�����x�/��z��X_	v��>T)�����O[-�D
��>����I��PD��}�Y|P�c��l�����|P�S��z+�V[��DC^|P����7|�j1�sMlu1�@�<���<��,;������&>�x����V�3Q^tH	P��,e4����T��-D��2�zTl��PI�*B��ln��?>�!P��$��b���< ��Cu�24�`�����-x@���Z��)C����rnS�2>�x@J��2�bQ�V<���A=�Z
(C�����.���[���N�O[-�rPc�U���@p<��z/T�&�h��P��0��b�'i�Q���@���#A����$?T�E�E=* �)0R"���GE�M�T�P��&�ET~x�@2x@��*4�x@����'$u��p|P�EK
z�<���T��������@�z���\�d��A=��>��P�k���*D|P����`����Dejbxn�����H���������h
4�bE����r�B^��z�t.|P����O[O[H��4 Q�C=�
>�x@���Zkh����
Q���J��*'��G*�b����zT���Q��Y
���k�vE�
��Yz�C�x@�����P�@=�CN���H�����Z�(]�����!>�x@����`����I�jr��3V�FE�22>m=��]
���Ah���	A���X�U��*��M�J|P����Zd�u���8���< j��Y.�����x@���9#[����#�DD�G=�fT9(JS�%��*K��j�X�b��E*�<e#{<����z��)|����!'q�%���E�������b�u|P��x����i���V��@f[����uH�z�'�TM���P��@b[��z���R$�QE=��(>-��A=�CN)��i$�r�z�S|P��p�'�m���PUE=�%>�x�)$���*>4�RqE=��>m=���D�(�}�c�>#v���H���8�(��T��"SC.�Z����O�Z�tD|P��V�-��;�r*Jq�>�x@���h'����T�kr8�#�2�>�����9]��&�{G8FSv��@��k�	,E�U^�<����z�4J|�zJK��N�4`�<����z��)=��	x@���0����A=�CN{)f�������1�P`�i��0EQ�z1>���E��2�������*��4���H��EbA=*�4P���OE��:�r��bc����g��Pc�A=��'>�x@U��lBN����<��8��25D�E�R97�)w!Qe-9���]�Z�z��j|P��b�=
�^�A�l�<�`��z�X=1��x@���*7����A=�CN�)������p�<�v����w���to|P��3���x@_��y���p|P��"��s�<���O hY����PZ�h��r��S�@=h:���f*�r���=Z�:Gk��B#i�v�j���4�
s�r4��i��m8�r%�z�dto<|��������Ypptv��s%�$n#8�?��;���?�����������@9x�x#x}r�6����$�F�8����T-��FpY�o�x�ts3��{��.�8�����������?���[0v?�������:#�DPN��2k�J�0H��O?����Z������Q�&Qp=�a��I��n��S4���C�#2g��8�
1�W'������Y�e3\�G�#_v�u�>����h����K�'��$���h(cJ��5����Y/������^y��|��_|��_|��_|��*����/����/����/���/Ux���/����/����/����/����/����/����/�|�rK�R� ��)��0�>L�S����0�>L�S����0�>L�S����0�>L�S����0�>L�S����0�>L�S����0�>L���0�$sb����F�R��#���~s��@���t�NgWw��������?���{�|�����=�������?���{�|�����=�������?���{�|�����=�����������j��S�$��N�[ps3���Q9��DQ0]��� �D����G�����~*<i���+�M��p2w��I���I���/�����|�}K����Q�c0�N�[0�D����S?���3�\�&Q��O�%C}�,Q<
����zax�''�'�,�@W������(F� ����������<X���H��?��p���������`�S��^��"����O��Yw4�N���2u�E��Qw��%��v>����h6
�����at\���W��H���?�E�����������C�,@+��������O�������f�\	�V��F������{'�Lj�pqF���0f�<
��$
{7
�X��x���ix���7��� �v?LF��,�tGWWX���h�.d��i(��2��l��6P�B���&���^���"�&�����	�t1�i�����6lf����Rt�!�tM.F������;�`��H�a�����*��C���^p=����OO�������<��+��2�x���Z���C$��[Pn��%����U���h�b�:|k���e��{o����K���7Q�<r2��W�Os/����3]�r7�4�����;�����;�m1����A-�u1cBDZ@���W��,�� ���s�5�v��TM��|O���h��U�N�w��-���	��`���?�Y�ER��l����QGL�j�������/����O��2�D�Y���h�~/������/����}2��� ���H�C��z<�0����
!�����U�� �LfU
5?��"��l�\N2���ZE��{NZ���d\�<����,5����F�?z��_�~{����mvr���s��f�������p��Bu���_�W����D��j�����;�Hb~�e�\�o��v�?,~U�6�_�BW�[P���������;�A�x�|Tu��9������Ip�����F���.�*N��NeM����.������
4G��s��@������{~�I%L�������sk|�-�����+��G�x�<�=<�?	�(|�a���@[
�q0�_/����/�g��9*q'j�����6��oC���H��*��&x�^XI�����jt'�r�;G������6��8���I�'���Ig8�\��s��3�s�8�����0_�=�9�wx�'�NZQwjr%AV���0#J����@�m�9S�Y�
��c�r���������;2�������,�=~�lv�w��284�]��wsk��6��Gy'��I]_W����j�R���a��h�J����?��a� �`������&����)���?�*, M�c����)<��P��w��;��w��o'Z�  �2]���m��j3S������n�t�Or�Ou�_|���������Yr����-Te^Ee�
v��������/����D��/h%�Bh%�/�	��������L���A�s��DI\��V4���2��$�2
�z�_�H����N����z�U��u����]��x���tqg!^�����S��u��!��8, ������������������TW��U$�[8-��|
'��&�j���A�"dQ���
#X����F��V���}[)p�����[l��+������f�Too�J�������5��&������ou*�V�]k�Yv�MP/����������y2�/��������������ew����������;�U�o�������;��h,V����q4��P���9��0�%FC�c�9�������)�99'xzp�&���{Io��u|%�u�Q����Y��qP8pH?���Q]��x j����,�M��e�k����w]��v]=�v9h�7r~����'M\���:�����������?w�g�w[�j������i-�Nk���z������u�4u�R�q���8�f�����\��l�u~Xo�Z��k��t������8����Z����lT�
b'?��U�\8��[���C�X������/�r5���\I��u�����]T��W���q�������}��Pe0���X��\}��'%9��������i�	���������Q!�5�v����D������Ow����}���a@����`���
��\��p��/�l8�?��x��/P�pH����/�4w��xi������M��,1�����O�q�d��o�y?x��2�o�pOU�K�(9��Yj����*�<KT5�'P��?��Ng<��b��������w�.��i`�{X-?0���r�����X��Np�0$x�V,�U���b�����0���d;>6�m��J�����!�h����s�X(��I8]@�����&_�z���hu��'������m�~���5�C y�?/�m��-
�{"s�j�x������[���� h�����OQ��e��yi�u��-�{�0��oL�9����"�!�^������c\�"?�����&]�@�G�hx�fj,���6'�����[T[�/�Ih�4�'}'�����k�����m�5�v����Pl���f/�K���!+`1��+���b��%�<c����E����~T,_6������X#���?,uZ�����p����s��b05]I�1m�y7W���a^VF�����������2�������|�>�}�p������L"����~�~j��~j�����������h���/����WQ-���u�f��f5�YRu%�Y��=��������Y��[��|OGxvt|v��\5�_����`���8k�A�i�C[4���Ky�|s_��y��s
Jz���$M��k��
A>F7e}�&S���]2'.���GW���wk�wk��}�����
���i1��d�J�rr�=p����-g�����b�&�^^�.�����M����������6��
��hMn.X����m�����:�����1MGq~��0��o+����7+�G��p6�Q]����z�j6-�U�/����p�E��N�^��}*f�Y���h���_a4��#y'��h��y����t�������m�CV�5��m����9�+\��u��:&8���g�'41��������mAC..;
���3�0q�(�~��S�<,*�G���V�A��#��rQ$E��v@�%�;qo j�x��Lf�_f�y{O�������o��g���8��Y<��mv�
WR��Kl��EEg��������_V8������|*�?b��;��V��1M-�fu�f�6��1baVG�ES!��W������P������}���I�I*��� hJ���������s�����s[-���&��3=��r�.i`�����+q��M�O?W�X��Q!��?�_+�m	&�s[�5p�;RAb�����h���/���P��>7���SJ����L}��	����m,n��.>��/�+�5�8�.NM�7���3�>E�����W��ys*4V�7���|fB wz�A�w5���r�F����V�Ym\����V]��k����2U�[�b��\4�e�k����:9+�jfs*-#)}
r]&��&��j����wj����D]��Iot=,Z��X<����*8E)�	a<���L0"�)�	��5����t'�����{�<��h2�p�X#����@@� p���%�E�t����5&��g�\�j����FW[4����S�1�2�-��k)�k	�$�%���T�B[����_������<��{����a�A�>���������i��6v>��x���+va
{���`���������p�lk	hr��><�=[��b���Z lv�:�Z����p�hi{���k�s!(j��v��-Z�������E^����-����\������KjKvIm�]R[�K�[[�Kj�v�|S�x�.�oy�.�-�%��%���%��Q4[��inaK���[���a�+�a}�m�b`q{�n��������Gs�z��TP���*����������_������7������Y1����`�H�`6'��9���A�+���V�n-���'{�^���\�V�~����t��=�Q��Y��0�WfA�+�PI�=���4�����[�e+;_}-��X��
���������V��������yO+UH�xu�a�H%3X[8���%r�=��{�����i�u+�2�Q���jR�cRQ[K��,�*,{��2����6���p����� �] �k����������%����X6��-�z���|��N�^Y���{QmE��.��=�]������m�mo�B������:������2��Q�D\=O���g�s����t-J#����i���t�u~��N�/A�������B���#����u)��e+-{����Z��h��hNZq%Js��VZ�ur��u���F�,}Yu������i+��������v)��\33��Bk��/$��{C�7�nr3����y�.s����x&wZ��X�	�e��&�b3����)�^���V�H���K$�u�x��%���J���u�9n!�����34����M�iU,��8l(���KWynYuC�������[�~>�	<�ta������>xv��ml���2Sm%6\������:l8�I&�W�D������c��6#��\�w,F<����K_��b4�F����5(��w����1����b��`��/Z�tL����$��������]Sg���8�6/��4u�g���_+U�����(�y�
�^�7$���6o��2���S8���`w��i�����?��w�����;�Y/��\��������3�>����p8���H_��es�
��/w���m'��#���`~���Qx��'�^�[#����[��M�Da�/wK��n�������:�y�����������9����P��K=�@���C��&�����&U	�������4����(�����?:�V��a;����48bn��������T�KM+
�IZ�$�~#�.dm�I$�kg	�grUB?@+��=��\�����V\9��$�K1��AZ����\�������I�>�06���&��K^������/z��I��Vn�)�b������Fn+4���&�-�L�_�N���i�e����{-Z�X�
�|9��
�|���5��d�h��~��{	�����jM4oer�TSF7@$��_=��
���86H�����d��q����|-�S�t�P*���)xGJ2C�i���2�/S�x���il
r��p�a�[?����l��v�q��+7�Zf��9��i5�E�@��nS���^��88�RY���q�B�����n�?�c M:�a��32��=^�_DN"U/���1}�MV�V�"������c
���9�8F)N����}��^n�J�$�-EX����%�i������bn<L3���C!#K:���1�����%�����f9��������!(>�[�:�]��f��[��!���Z���A��g2�$��w�VI����hv���6������k�����
�=x5���}��=�M����=�(Pt��3����}����7'���?��kB�N��*����C��<"X���jp��3����s���0��.������m�S��=_�.���De��t4�pe�gq�~��y�vXb�)\�D+��V5[�t�/��{-�x�jX�
J��=�����8�~���Im�q���l��M����g7�o� 3v�K,� DS�C��i��hY�a�v��Tj�.0��h����*g������o�����W�����p�E�������������)p���]^�/���N����oL�%!j<�@G
�a�#�B�d�p
O�D�[�����i]N_���,G[���5��������A��R�.b��0��7�*3��M4e��K@�Jh�F���:��dC����\\J�ag?�7]�06S�bD�����ePy������.���6wm8����96�8���|#+�KlY@n}t�9�0��e�qE[�0Y/iE�hE��%Ys2��d�a���;���s5s��&�0�����ITP��\C�����*��2���'z���OL�PFc�����P�~:8�1(���M+��!��DfL+���W�i���m��Q�v�������t��d��{ru���������>����o|�!����C^0`��_w��2��g�y�M���!AW��c�2
\E�	��:oo�����H�}|���w��]\��f����s9�
�������XCo���m�<�b�$!4��X�%��nG�;4e�z�r5�\N�nD��M�i�`��w%{�~�m���i�\������������������VO���6��cN�g[����5	�����QO��\yaXv�ts�<>���s
���;<��
^����5x
|�m����V��\b��
5V�k����G�`F����r#�tG�-������/-[��Zs�"�����^�y��C�I��������7_6$������"�/���^��z$n3t�t�S�d��xB�F��Q\V���J��h��i���C]��efx�yc�7����P�G~.����$�6�<\����G��_�]ny�.3����_V������������������N�^I�$�-�8��|����/Y���3����
g�
nMlej%��z���f3��CR�_<����j�V���M�������K�O�:�o��j����g��\�'����L�1�
��W�AF�NO���g�C������������r4�2y��y�f������D���?�P����>�����Oc~��E�D�E���Cz����3k���=dQ�+8v�����e��VP�+]�i^�/��u�u���~��B�����e�~{�������S�Z�+3��x�V���>���
�����PL^r�u�c~M�<���C����V����-:o���ZwMZ���!C���F�����lZ�N�(��p�b�wh��V����������+���(�����)P�S�-�L���
��%>e���lnP_Y]q�������qH�����
=h����v���;���m��^�%�5<}���'����=�{,��&]�#k� ���Mf��n�/]E�tE���5��/��-E~+|�*�0E�j�������,E�]��n����_�/j�-���$qGeV4���e~u;� �R�=�P��eCsd�\��[I&�mW��(\S&t{q��V�������
�`}}��+�x^�~�sG�7�m�_)t���y}�������:�f������w����<��o$:�q��2Ws�+���������[9�%&��<�����~OF��_Gc��5�����2�3�t��#����C��P#q$f����\�$�������Q����N���e�`Lp��?�����
��H����>�s0YW�������~�K�
�L��;���}�@'��v9h�o@{��ci�_'�%s��q���x�[��D�Y����5�]�*��J��j������+��5q5]�����=	��m���[������^R[e���'G��'l\`�i��
������4�������Ow����}������������b���\�����{�l8�?�����{R�p�����0.i��a�h��+��Dq[�QhcI|{�T��<�w�7�S3��l��Lo�2�4Wui��Z����Ao�5��W�,�����	�<6kn)o%;��(p,�P[z�M��y
��G����M�^���������+�9�Y���<�2�/����s�uh��\�t�9�	�J>�%�������)���O�'G��;������L��v��V��|j�h�����:��4[�������r/y�����7�	-��NB����/��u��,�ao�0s�~���wGs�Ulm�e�j%���+��Z�K�&d����������`��_�V1�u�=}!Gk�
d�9|m.��`-NK�J�I��D���j7j�5E��G�n����������W�Y�@V�c��Qu/�E.������1Ug���z�.t�+����Im��;�������*�Z����d�W�0<����������5_�h�����#�>��9�f1����[fn;XT�\p���qpyN��O���f���X����
|{����wfw%����������<�o�-:?n�l���z�jeo����.����(�(�+y�����N�����[{*�����|��?~G����h	p�D��T�J�/��}�y-�ms��UY*W_I.hW�Q��N.����D>0$]R�A����� �&]`
~�M�x����S?�����E���}�����1�d��+�~+�������.����]�z���5v*;�d���:75���'��Ux�Y�K���o�5��>�����?iio4���/?L�Rw{�Z�����(�b����a�f0:��0�1#so&#*������������b��{]�g���!���N$����u�!��8~���t:�{l������T(|������@���8����9W�!T�6�M�#��q��kk6��g���O~��p�yv������Ut%>�D�E�/nqiwX��!���M����������o��B��)��:�A������sO3k�u���w��^����I�\Y���.(���SIN��-����P�BPW�E��S����G�,h��$	����W�_[^��g�5���y����@���*��PP�i��we�	��l���"�����Iw���S?6!S�����h	�^��+����)��-�o���H�3���u;��h4�E�f<c=��(x��������������I�}7���GL��S��+t����������&z�=)���Iv(�>3=
aW�q4�M��>x	B�jP��%�7Y��7�-���r��������/!4��A||q��V����r`��m��`%Z��o~o���=�T:�^�Z�n�:	�Z���j�kRGq!_'A9[�n�����_�U�u�d�s����c>��>������
�C(�{�`������4+x������T<�G�R�I�.J�D���\B��`���FS3�=1�0��RJ�d��,��M$����(Wo���xZK��[:o�����m���V��v�gVs&�r�h�a�l����p����'�j/�t���y�?{�����������$�����U_�~g������|_i��������AtE�I�?^�sj1��l��l~N.��/5)��x7}PN�v�a��NA+O�jl*�����#W�{��&+���T
��0��(�%��x2�����&y*C�
���������D�����7�K��A�q�?���&�l��&��;����t����������J�d������_���{x���n�d�-����6�7�q_�u%0���d��_�������=J�`����){*�y���$��~	��q��w�� i��(�)�� d_��,�f[.�)m�6�n��>Y�����[	�G�'M���*�����$kb��Y����A��Y�,��~&*�{0�J���Q����G.j��J����i���/F�x�x��r�K�h�	/��
Ng�P�����h�����|i���6�JJ�f�E������f��RT�@|�j���;`b8�~����
�(;�����x
{�������H����#4�y���gU���W��k�����`�v��=t��_Qc\����W�1���b��K�M<24r~)��m0A)���)ar��w��d�`}����Z�X\:i3���6����cz*���tlA���f(}��`
����5^Eq���o9�1
����YV�+��Kp�����9����i�z0� OJ�t�4;0q����>V�,w�QN�!�p)���0
�2�����$�m~?�k���`=��2�9�����>�<<2���f�-	�L������>mPM�)A�S� ����]����=���>MF�z4���n����%��"@�\��g����������XZ�(�ecIM 
�=}!Y0���O����\��&<������g�'?����"3��/�\�F�$��6��D�6�N�0�@CfW@�I�@������^n��=�c�1��.+��S��P���c�b�a�_����D_m��#��o�nB�c��fI~��F@�b�*�z�Vb��*���n��G�xB�5�s^�����M�����������e����"�#�f���R|�E�JG��t�V�H���yEC}�{���C������0}�wFF�F0K�TV��#
.��L����W��i�{o�7������*���7�Nz���4n�9���?��BrPJ6�|4]���� �F!W�������)��^$c�����n�����������3�?g��]/&�+C�u�fO��%��"�d����<wN������mB	��6K���R��f8 �S�=��s�u��+�0�5�9����[��,��o+w��f�����_;���{sA@h�Uv-<D"����	],��	��=�@����s��@T��D�j-/2�����Wgg����u��:8�s���FQ�I4�M���=�����E�w#���l�wo:����wO�:�v���M{N�s��� �9��a��M������������R��6m��_r@����S��[����X�����1��|O*�
��������[$��~x�T����H���n����%�z5Qo$Z�!�
�"���\�4�T�x�6��v"@B"�/+o:�V�P&�z*���6�G�h�K������aOj�����U�cx��e����u��p6�W�W��P�v�F���#�7o�o�f����cAR�y{�����U�b�dPR\�������d_�v~x��5���q��
mC�b{.8y{�����T:`��������2f��-
G��N�.a�O���"%*m�2��B����q���t�Z��6N�d_��`����������'w��{�e�������/[&;��eJ�����LF��c�c��qe�1����XS9y�����,��h]��Y�	jZZ��b7`d��U����c�C3���J�j�B����Z��$���������'�S�,fhjc�Y��	��O

J�{%�P^+z
j��b�F;�����=M_�U�R���O���c�AF�%/�JF�i��X��������>�E�l0���}4[����=�0=��V/\FU0����Ck��f��i���<w���y�zWpe;t`V��F�������Z����/�*��J������~7��io������M,�9�g������j���uNT��:�'oN�)2��f�����[����j2���������TK�XYiq��*:��ud|:3r������d�b}F�����?C-qt���k~4��rKf�T7��~!'@s@�6��m�9����'���sp����7�l���=����!����-�������������7W���F�z��k���_�^�����.@��mEu<v*������WX�E�/���:Ki��<��`1����4����=���UL:�ms��:����ELjR���kV����u�Gi�?���<#����1�2����Z�����nh���b����Xv8��zyt����"Jo	�T�$h��J']�p��7�7rH����2"|o�}O���XYy�_ :/|f��z�uV�r�~��Z���&C�.y[���)�W�r28���>w.��bR����|ot��w�������8�~/����A�m�)����P��o]�d���'�����"�0I���6����c9��X���VWv��j��*Q��.Vznk��KU1��O��e��77E��.�����G�J�����b�G}��E�{�w����<����(���N��U���0���6��L��|3�g6�,i��KwE}�R��������}r��*���m_`[�|+8���Dv%9��H���c�,f�S�,���'��������@�c[���S��?�X����L�d�f^�N�=���i�0�~�*x�A3�N�*����JN�c�����36�PoC�4�h���FU��d��V�7������3�v����4���w�&6@>
�m�8S����/���X�g��d;u�,"�B�D=��2���#^������}=������Ix5�����/�-��aYr[ ��-�@24	��T����U�GN�S���*��g���z��F�jW�_�*L��v+�5"=���K�Q	H�����_��d�#`yN.��F�m�i����K�����F_o�O�=+�3���T/|����<����#u�aY�I�k��������2����w�>�9|�g��=�O�jL�����vHRtq����
�����/A�����B^b��8�_���{�JDb���xG�5������_�7tM�*5�!x�X�g�J�$�~�Y1(�4&�v�ZN���5�7��I~�0��`�"]�gv������Y1���m�1����b�����<0��Vi���=����.��P��U����7Z;����)��$���Y:�_�2�_��h��e�G��4J��������������0x��)��������4~�X4��R���9�wdb�~�F�����6m���&�<+z����U�K|?2 ��Y��[�����h�i�y���p�N
Qb�%wo��W]�;N��c���
���
�+#f��p,�	��l��*f�����n�|k��S=oV��;di#�^YZ������vy���W�)8���DG�SFq
��G9���hvu�{�!S�>tY|7�
#��1�P�����N��2��0���e�l'�hKy�p��<K�b��+�	��T��?_��T7p���s��X�x7����I���>5t���n=��Sq��n*���������A�+��Qs.@���/�=�S+�2-�~2A>�a&�N�~�}:RGpmI]k��?PM���
����j���J�Jk�Y/�j: ������JX[��L��r���:>��`����*�_%�-��)�P�4xu
�����Zc��z�rP��~���o�-%N���?�����]G��<����?�z1�_�����Ea��b���FS�`�o�d���&J�Q7���PX��)��/�`.�a���'���h"S��������
A&�z�;!�A���xX	��*>��A�|J�>�*����!�2
�����hZ�����������a��&�:���P�����pv%���8\�%�htl�;qn�D��dH�J��\/po$$���d>��N�f</��=�%���.���R��hxyhz<�������i���-v��nR�������eJ���&#$,��xh��*��d�.�����1���Ad�si#����-��<��N���|�S�6�m�Sk`��Q���4��H�	F8��c��[s��A��������M����w����O'��E��g��$m���P�nMW
�n���KO�:�n��`�<J����Q�fP�W�q��������p��R~��g�v����;[[�Z�]m�Vc����s�l]���Z��
���3�,�����3��>�M�����8�T�^<�Wp'VXASd,h�V��Lr���$�]tn����CK{��6����=�.�!�
�kF*V����2?j������}�w���g�s��������t
A�0�p&�L��P�8e0� ��Q�/�M$whS���������g����*��p�R�U����rm'��lP%���K��a@A�� A�-0���Z�9%Rn�at�����UI�������x�J����#����/��1_���H��/���'��M���������:B�����d��-���h����k{YK�'��O����Q�)�c�d�����rE�7���'Dn9�W��K��<�����3��B��Z9�o����~��Qa+4fS�Q��O�{c�������gJ9����j�*ah5�l
n���V"�z�5n�E���}���s-S^�.�^`�3���;�&:W��sq/�s~2�R�!���e�������G�0��V�X��gT���2=����Z*4��Mt�q]/<;�;��D�aj�W�P�2��v��Zb��7������:���*�v?`��vTs/r�s[C��\����?8/>��ha��x��S���M� y{����dA���'m�����O��@���<!{a����V�\m������rT�U�/�����(�~���}���l�^{9n*2������.H�V����7h�^}#�"�\F�-��VL��^c���w�=x��^�-�a�LU����d��-���x!�����D�	�
%u��V��F.��*� p!����Fh�P}��@�s�]���@}��GI���K�YL���eo��Y:����������=������P�d���[X�
-X��-����f� 
��]���
�c��;��w�[���{%���47&D��;_'��J��{M�y�V	 '�A��M��;�W���:h��'�(Ue}'������U0�<qC��F����Qb�����,����
����w�3�|�FK���J�Vc��:j0���uY��q;����U��tBB`��������2JG���3s�F	5M�����}�^e1U�@��f5tK�-���j9T�>8lm-j`d�$�E��
1"	�`%��*[a�_�?��l���hbK��"
�G���o����#�c���v
^�QS/�/������q4�kG��S�Plt
���-#���<�,DL��v��AV�r������,�s�J����������\,}W"n�z���Q���N��Th|��i�
4����b�	�8
}�G��+6tb^��P����@lT#^�5K��6'��B��v���F�x��m���?����?���,�f��M���j<�)�����w��,e����W*z^��K��v�k<{��,���z`l��^����I�*�n�u��P<�F���m���Js��!f6i��S
*d�0��;@DMY��^��6��`�z�	P�voV�W=i��%��c�`5����	��Q.[	�H��d��vQ���%��4�0��b�rB	���"��_L��{�H����jD�1��!*����k:0�����Be����*����&mL����S�O��r�.�����A3���t5�*F��F��BT�}����g������ts�&���W�7"��Oj�M���TD�7��w���u���wG�v���,����.��%��r�F
�7j���i�Nb���OI��N���U�OU4`h"��N�:�g�������^~�8�r��l^lOk�������D������%�W�]�.�Thp��W�
���+�3��H>4��#���I����b�NK��p���T���f�5��+��8����ka6�sx>���T��.���������QE9d��;9�
�#/go([q�H��H#B�<(Jd2����f?���w���{����C����G#��&��d�
�Q�I�@�[���5�c�Gq�G����X��l���:z��3������l�N&`����6�yk�7l���`���tf{�0��y^D���j�Uc��
�)�g1Ce@3%��;�nd�3i
��2|�W�\`^tE�3�`� �K�cu�0S�^�jl��3^�HD��`^�
���cK�N�l�^�A�����k\9�&i7�)wz�]�7ZZ���������7V����@�i%�a���Yz�*=�<�M
�V��TYE�#[����m?`�t���7xd�Tv�N"A�����:v��i�4Kl����Y5S�8��m6�����st�;9RVT.Ot=I�����<�8�%3�2s��g?6������TK�F��b�������ZA	��eT�����%�J�a[#e��1m���Di:���fR�(��H!���3�@��bv��h����m��`f�o+��D:��R��#�D�31�Fr�kti�r���2����&���DF�MK�;qf����;�[�~�{R�]��2nj�����i�hN��1p��;M#��b��&&�hD���C�T+��jIM+���CO�
7 ��J��g��"jo���}fb�����0������ab�K��b!����I$���� ����*'D��u�Y��j�f'��f{\��M>�'�YB?�'��I�?��*�����Mdd���`����$j&�)��R�4�Vh�U��.�M1����+��|���iYI�pB���c�P��������Dc`������1��1D]`�E�C�KWTM��fW8[@��I��-��Lq��0�J
V-Jm�R���d~�[�"��l"4���X�>��f��Q�����Z�����wO�;;���t��s�f�3�	�Qg3��v�c�N���8J��|���
i�Q����Y�y//�*3B�\?����h���3���;���*�9�2x�P#�������8�����qT{�V7�'��9���7$�����������7�4W�n%�+����,tlh��a��$��$m�_>]q���T���%#�1#��&5s�f��D�H=��O.��VykK"��.� sfR��#,���Z���c�� ��Lba-�r�_����3��v�G{�bf�CQ�IE=2������ �\�����1g����T��1���4n����1�a�a��d�#S��{���'@�W>t%K�B��@������?_,X�t���*okN�Gy+���\��v�r�N��S�Ra���$�o�����H�:���o����ll�����Z@�n�6)8�K$aju�cD���sb�2���DVH�h9}����G��l���)��3��t&���A<�'PO��fBk;��?"��j%���y'����|L��\��1��eOB59��
a�8��R<_����M�y,�r��l�q�=�VL
��if)(�u��U��+\#�lU,K��@�y4D����k��@#k�@]B���M�X
�V�E�/�4��
�������U�A��EJ���������5�����|	�����s�H"z&Y9� |	�@�@�P�
�	w;��)��at��b�-���F�l�z�u}�F(��'!����7��
�0YVb+;�`n�/���)��-N�K�����W?�X���f���=fK���h���C�L�m�Q�23UT���e���4�FP�V���&���aUHN�����x��P�z}[�_��8au���&+��Qw6U������<�c[�~��5�"�H�3Ot��y��t�B?�X����8s�=���@>4���'��)hK2%�&WG��H7!��$���zb��C�dLI�o�}cH�&���l�$_@4���&I@B0����d��b�2�D&I~1���%~�r����hI���<#���(a�:~�uX2�s���1�J�n�&���h��c���.'�����v���P!�^����f�����cS�MM����\��$��$!�9�cN2z���F�S�:�GCq�O��jS/�
J(s�t�+�.	����7�|������C}E�0���������`��i����
�x����
�Y�G$\�
1��%C��	����I
�5��%?�J��	�32$����8�psL�'o�U
F���YQ�3�_����TN�M�,�M"�4�O���+������'HjT�E�L��54p��z�-��������A%�p���	��)�����3��:2��f�
�����[�t�(��Q�����`��F����.�Cc�4�R�go0�S�h#��wb6��M&�Z��Y�W��M�k�/��q �Q@�������cz���)�,�>e�,t
��>;���a>!��9a����@\�*F��*����
�z���b4�Z��,$+,�(�
j�����m���X��j��5h*(��!�8��I`��l�D�b�9#�O�
)��\�C�3'�*R�J,���
Mm��8�0�����5���]���NR�.�;�jmVG��U�x(� ��s24�����3��+���`l{����u^���=�oHgr#3�L�"c�����p,�%JIR�$
E�H��D���*YY��`d�TT1��V�J��
���t����������r���/	�w��;�?~:9>:�+�|��d�t_a���'x��~�_�@������Y�r��>ph���F	����jh���f�/4I&�G7puW!Y�n�v�1�0�ks���8��1�O��n��:.�����N���<�#L��M��v'#�6!��=�;dI�m��K^T�C�������2��������i��I�_Ii�*K�}���������o#�%�4]�u���+1�;��[l,��W��y��c���:)g�7�����~
?;��7q��f$ ���g���������Ef7���V(ga�5���b����^L?k���'���|��Z���Y������;uh%C�����:���ZB^��Qn�f7x.P�}%9�c^�?e��c�(��e����J��`�g[0,�$���H#������
]a5��*$g�t@��ieH��x�"��=��|��Ej��@��������n��y�U��q~��/�;����;^=�V�-%�<
��o�J��3+i�AQMV)�������j6sy�S�p�c������+� %T������h�tQ����r�oXi�����-�%�����8��}@���b\��Z��I'��8p�����+�(V��$�b����/��o�E��H�.5����"kH�Z�Z���������q\r���G/�0����������(�P<cHQ��r������t�Q���	Zd��-��D$���Q
����y���_�F��\�n�O��p�3�CN[���8���2S�5=���^��~q5�Q�C�����}�P�8�3�ZW0��6$Z�p���ux�������A	�������tS�_����[cS���$������
e������G�Am����0P{�J�3$���	�]m�$Fv��0v"�{D�h�#��jY,��:�R=*�J����Ir�hO��5�0��HU��6�a�Y��=�X��������j
rDW����������+��d�{��d�F-Q�*
��+���XWg\�*�f��H�tt�{�a�TA�B��������s�!���]X�t�@��W����!8��79c^'IWj8-����Pua<c�J|��u��X��.���] ���Y6��jI��FnX��}����e��(��e��y��NN���*�;?�rp��������,A���\w��ws�%I�np�v|��Z�$����9fw8;~�����N���K�������R���� �=j���,:g36���G9JM��qC��1��<`�`)+����>'w�d���)Pm�z+��~K����`\
����s9=����� �}6��}:�$l��kA���;s�p_���4!��r����z��\��G������1�};�D�A��\1��2C���������g�8zJ����\�%�PB�����Kuu8<�\YhL������;��
N�s9�����2����{���'�q������$�"�hf[+���f��� ��V�&��1���*F�q���b�"�#����W'z:b����O�(����R�y�Q�f�x�0s�������Z��y5�������.[���Z�z���>�B������
��\Ca��lL��������m&=�O�	�r�YS�c$��.��;�N�=���F��5��o�������x6�pIc�O�O����(����0�=��:az�Sr����e��Y��� ����	��@��������d�G���d�a��������G���(����|vQp�c�'Gq.����|,#D[���S���������{5v���}���Zm=�w����|�.7K����ne�q���Q9��#=p�LK���3�B���d�M�<����d�)����
��^�|�^�3<-{ol�px���7�S�"HF�(lb�qZ|kN���#��[���u �o)�e MslD�[��s������ B ��0�h@��������e]~�D�B��0)��\Z����X�kz$V|&������XKE/�0&��:=Q���{��N^��v�C���8�XL��|'��b��:9"��$�*�l�
�m�DG�M#���'�\E�{������m��W�����}��K����9E�~!#�-���Y�D��K%eW��#�`j�s/�o���f�S�Y��a?�f.��_�m����m��s�A.��D2Vav5v��|��{�������%�y=��<k,H�U.W"��G��U2a|��yX��lm5��p��sk�|3c��+j�Fw���|Zw@2k`�����6�|+�X��	�����x��Ai�P��g��1���f�^�J�CH�"�v?�	�t�2y6L��0����	�5aJ���qnT��usT����^���D
��9�t��n>Xi�ON����W�����0���/N5�6n���92-�&�8����x6N��{��IX t���5sAp|Nu
e�Y�� �k��� C�6�1�2��D����FAEC:v��a�nmuw�V����t5��|U�<�m�#�V"b��F�T�M/F\�r@���p�l2\�fc�&�0�-P�#�`~���|U>M$F���1���TvK�n�"Qjh����_%�#7���G��(X��������w�e��������xr�r�s�0!�x#�c����d
;���ul�����yT�iUvvz��O��������������+Q�������5����^9��v��LR�������"6}+4���8��FW`!� o*E����4(��D�����>�ED���PW�u�V������J���Y��n����
��$x����>�k���%������HW��r���F��iVv�����V�Y�n��7���x��$j_]��%�a��������XZ�5	�=^ 	�����[�$���&�7*�	�V�9�$����Kd^�qj��>���>�%i����p,���4qMAH�a�����su�.�L�Q"����m��
e�E��tIpR!���9����?���������$��8�m���9�0���	l���&ft;=�%7#�&"�ss����&��A2(��h��wJ��IvI������ADN� �����\���Sq�L,����f{�d�-p/�~I�di�2����?����f��h,/�XnWX�H��Qz0|g��H�6i���F�\�M4=�H��(G���z�]m���������hC���m
����������""�����32#�����?��t|&�Mk[b���vj����|3f9���h�f�g����1S��������[(*s�r-��>?������y��("���c\��J�lG+6G3f���m��?Sg"P������Kx���9v	�+��6�����z�x��+hA����O���.R{}1Z�n1������C.�q4=��C_������k����DX���y1!���%Q5����F�],�K�������N�T��J�R���m�4�oF/TO�� �F���s�*7���ww, ���k�D���-���]����_q����D�t��J�g�;1�tM�!�I�)������i��W_hdZ�E����swx�Be�`�1��Y�A����/�{������F�NW�Dv�,��c�[�����T��9�_��(��U�ojQ��k=��A:�f:.�}�A��z���x�O��:���>X���jf]Tj�E��j7.����{h����i��[�e���o]H�&3����OLEK��q����>��qw����X4u��L���-��-'H�^�yb2����sO@�x��������$�����([s?������ �������v�H��c]��|nmJ�a����g��9>8�kIz�W��QP��������b4�v	�?�����<���`P/����7���z�������o���+	��fW3��-Y�������E
\�����<g�^��Q�h��a��S��T��yQ�U���q<�:N�d!F��I�����7�t��5 m����:��d`qI�NeF'���Nq���P��2��fWJ��Pcm�6z�%
�w��9&h�g����4����N�/j�S���fN�+i��h�T�5�����Ma�/��R���)y)�Nm���=&j���nm��j���V��iK6eZIuE�(��U������&I�J��=�����%=��~�b��]��f��Vx>�+���=����:�'G�i���Ims��5����W�_V���K�{�)M:�Ol�>	rw���p������	lgF�@���8�m���������g�M��DK�����i#(.Er�y�p�js����VY�<���4��l�$]�E��M4�e�_
R�q��5�*�?#��F.�u��etn5blWU��o���#J�����8�����4sI2JE���M�R5����z�n���ok'M�7:�u&�����wn�\L��:�t�k6*!M�������
T,��B��'iC��5�9'`dr���{K���&��_d�\�|�=�f�sLi�i�@o2��K�Q65gk�su���D��wFiI8��VT���`(y��r����8��
��.�PD�r��vTt���C�����N�@�MDo��c��6���;N��?��q��+b���������3�"����(��/?s��F*��v/SMc�����&�
1��I���gk\�/��6f�LG���&����o�L�H���U��!���&Z��H�C��Cb��j
���\�m}��u6���A�����8�Y@�������q���~������sp�y�?���L��>��I��p>M����P��M�"	���,	.�MO^*�e�K��,9�.(�h�v�"�^�d��������r������Z!(�{�0��Wz-��5��8[gs�1j�\�,����$�����fX9�PY�����9NZXB��:z�%��G�������l5k�s�~7�o��L��f���W�$J���
G?QEJd]���R����v~��.�����
�?�����z�W��%Xc���i��{�����B�;��	YC��8���������N8�(M�Iq����
87]Sq�Y�9�-]�T�[�~����&�\���i���	;\��F;Y��Z�)&��{B�t~��>�8	n�M�
����v���De%�3
��e4��#~��Qo�ef��	�4�����4��t�*$����g1�,:��]�n�F��5�a�F���j"R">Jo�|
3T���X���L|��:�mC�������7�5H�i�V2d��>�S;�w��)�0��Ls��F'#�����j�k��Z�%6�PrD�u���k��������4x�z{�����\�*���hV�0G��Z�b���o����7�!)�J�%[�����iO�^e2�e.�2���6������U��i7��������ye��pa#������-E�������	����{}���4x�2�<�_��E?����P\�~����{��C���q�'|�D�A����_�s<�\N��F"����<zF���4�������i�#�g\v����t4����0����[$�	;<24},~d}�����KF���pV�t��C2%y��,�������z�6�]���^���p6(:�Y��])Wm��@��+��&���������dA���|����W�Gg��v�=����$��{������\/��:|���Pi���g���f���R<����ev��FD}�E����(Y�_v?M�I�������Yg3��3���R���+���Ze'�6��3�����S��>��n&w��y��A&%�<���~���T-�������q��;H��k[��d<�%1�^���2�������M�	I�&2�a�U2!���AC��>6�[���l4��w�����lm��kB�X����w����
L�P{�Iz��xf�N�����������W$��������r������h�k+MI�n���9�6]1���=B���}~�4D�Mic�8�2]��������4�lV�[��7���g@�2�R���k7w��&��K�����=�KS�I����S4��4`R���N���.��'�F^N����h���DiK�x���-3�k$Y-���g�JWl�!$p�,&��F����h��8{���N�����vBp�QF�x�=r���^�^�����3�����`F�K;���a_�2Oo���*�k�y�4�e�WI����m�^	�3W)���zak�=���.z��Nr�k�kb]�%��Mn���%w��g�����sU�57k���������uf@��oR���o�Ev����/32"Y��I6f�dd<"�}6(�\�����p��\_/L���oN��6����4=+����RN�2Aw�'����\��^�{Q�,����=�G��3.�wnQ��T��.I�6���-��I�p_�������+��r_���36���o.5x�G��sk�����_���j|�c����7�@C�������?��q�\�>�'ux����!�DP�s8��������+�������h��y%(�JGB@��\(���*���sD	�uJ����^23�"���M���F�~fi������Yb+2�q������}�;X�
�)=��(5�4����mc�{��S�$�5�#�2��r�a:O�xE��,#�(Ei
�'�ab�O�B3���f��)wbE�U�z��\5��/� ��w�c��&�{�d�wvxb������^\R�.'65�1���t��O!��J'xz�������y��\�{���O�)9.�X��
�e�������%�W���Np�u ����mG.��z.�*��|�����X��&nG��.�i�o+w[������W?�5�@��Vi�fr[�{��^������$]�$�.�������'}^�p8�ZhEc��P�$�v(g�kY�Sav���=���W?����<�����^�����\��'��o�5���pv�?��$,�����h����^��)��;�b�������c'8P�h6�>����'+��3���Q9X�}Ml7�����H`vY��K��@m���+��������~W�_�o�Pk?���mp����uN�t��^~�6��~><�������6qk
�c�L�qP��Zj]7��^u�_y�����W��W���,����{~w|pt�9���������gk�ZS�'�>�&r�)���2�-���I��P)?������}�$
�'������<�<]<�X������sy���h��zu��p6;��MC������]nM������_O:8��1���{~����{�n�d�����	��{�f?��d����d�#��{���O�/�~w���PaCH��n���
����*8w��T�u_���Z]nSJ���efh���B�5��K����������t^��5m�����MR����F��*
�tn��=���:�%37I�$����yvz�������:��v���������'E4��������&�
clP3���iT�95��U"�����D����n{L�wd��p�����;N����6�oK&��g�C��f��0��/F~y����d�l�v�4cHr�ZQ������$	��X��8����2����FtI5����J�p���Q�$D�����d�l��,�X'���8��;`�]Q$�c�3�z��C�(�8e��lm���<�(�/gR������c����(x�(����2��h,[J;��Kh��+����������V)�Zn_���O��'�����'����f�XNo���!���j����H���'����+���-�p2���K�L��I}}�����U~���0G��~��mad�z�+�L��V�fD��:�/{�OO���?Z�i��9�s�X�nF)����A�����!e�?���KR��w�/���>D��2���O����YV����}`�#�&��y:����:���������n�[���hy�o/�%�\D�pq`�$��88>�C��(^�p�Wk�5�G�$��W����������C�V����4e����z_��mE�#��]o�A36���5���(���5
�
��M��`�hc(�b���81�NS.~�Kz�d5���?�q����-��W�3����cj��'������d�����\!�E��XB��i2���1�W�r��d��lB��V[w��i��x�}�mB�5������L��'�xv�&i���I����x���;�~oKd���W#�������	��H���e�#
�LL�M<���]�a6����I#9��]lNL�-��VNB�e������A�����/��Y��"�l�m�j�0���d����l8����e�S)��v4���%����H�x(X�L����3�w�$u�m�^a=�����7)���4�t���1�'�)��!ed�
W�s����;;����O���9A]�j3�d���]�m.�kRke�x]��{K�e$�U��Ll\+i��.(�����m-
��&0]p���w_$x��(�l������Ml�-�\M�D�h}�0��������>��������93��w�����_N~8,n�������������U	Z�����/5���� f�M�����s�[�FnC��U����D`���i��l�h����.h��b��W���������LFt���������J�K8h�$_[��;h�l����>���5�mKV7������{������?�SB3�ZTpBo�p��C
��Q`�Gh������g�'�����ht�����~���zA8��X�+��w��~0�QZ�T��������J���;���t�aY#�6��X�wH�P��������
��E��?��M�=��L�c�/b�
����I!dpaD�����+ ����CC�mE
<�S*P�8�vS�����<7A��^����B���������u�^^�����e������zi�MMQ��C�%�Z��)��&h��k&%�|t[qm)a�,���
)��3�G����n$�x���dL=�a0���``�$�p��n6k�lkn�M��4NhY�%L��n^�U�a>��rw���)1/�FV��o��9
�i4��u�������W���W��I"�i;�s��
i��B��u��f9Y
�M<�KN�lC�A-���ud�w��I�Eq��%+yI3B����Wp^�/���������S���4�����n��m��7^w
�$]sh�X��,�%NB��P��
��|1'��+�:$�[�,��,����5a���5{1�����1�b�@����T(�)����D�qS+R�Z�a4/��/���6n{�����_��fB����$��Hb�(���kY<��p�Z�T_�4���2V�`;_��\�2./�������Ku�Q����0������FN��{zd�t3�����BN�d�����y$��B�
'IZR�#31q�M�8r���|�qB���^��8��XmC�T��WGf��4�X.��C�`Ao��s��������;O�e��Qw6���l���`.a��#s[�$%�_h;J]dD���f�����I�<��Lc�%��u�)L���e���n����!L"]���H{��
n��w:����\Xr,�'��YZ�6f
�Uh���Z����%���� �Y�����K�n;���t�O��{^8y->G���!B�}���|�u���YHG3��!�t��x�0G�������O}�[iS�X�
Ln_�yf�$\�GF>��;K���^����.T2;�Y�������(�q���U�e~��7��K��H-Nbs���6 n���6�����C�� k��8�H��JR7�}��������e���>�m2��>HU����,a�����b�~�L�$�7(�]�m�6$�5M��'9��64�m`Z����6�[�d�T��8�E�e���y���K����$���*>��G}��9G��05Z<Q��Br���6������B�h�r����
|�%�z�L����m����2+`_-��A!}a�{C�����������_�N\�
���Ut�����/N��48�L���O����������H�p�`�iKb���z���l��a���w�i�A�N���;F/���+����?�(7�l���!�.5�b���������Gs�qC��2��x���zsq��n,���1�fQt3�Y��������+���.\6�3�����B���^�=�/+;�J3Lf����X�H:������� �y��@���U8�	>F7K(���Q�GY��?�,���C>~��_Y�#;X@n(�de���;�'��;����'���f������=�3sa6����K*������<�R�;��_���=oK��l�2����J��^�S��8fm:^]Jc�Td}9�Sqc����}�wJdW����D�������?h��pX�|��%���oE�[`�|�v�g�+�!W��cC������X�����/hm��ZE��Y(���*�����De9�W�ZQ���YS����"��*-�:�~5��Z��f�:sN%tBbs�
(Ez(������d��3~�L{	����:����>������j�b���d|�]o�������,�:��������~�T0v �=�;���m�8(���c73v�4���qYA{�6R���-4e��`s3+�\eO�����py��Y��6��])��b�U��{���Bs��Q
�j?�8J#d��D��WX���W���.���}�Bhl�0$�w�L+5RS$��b���y,r��D�t3�0�������������>����"�a������1N����������M|9���s������s�{�i��
�r�0��B���(��{f�����4�����4������R-��s����E���.m�����������7G�h��+�;l
m$��!Lgf�!<�q��`&o�����%I��	_=x����q��Z�M��"���[	b,~�������f�v!�#_S'gf���S�[R;��$]��G�$>��s�������Q���Kr��
^����6�E�#e�����8�r�B���k�g3Q'�&��`�����*;������7jE��������Nu~���s�}��J�s�o�x�w<bL4:��%&!?X�,s~8�r�Z�������B��U<��������a*�t��<P'����1��8k(MN��#y�j,����b�)WW��� �X��[�#�-@� 2�d��$<���1 '���X��6c+C���������s�Tm�}�l����qrI_�������3�?�^�T�H(ud����*k�)���%��zq�S�	�����jv���$�����w&��I�Z��v��+KP��]H9����V������h�VB2]/��
��J����J���n��n�)�����b���kL� �LC������wG |����m���F-�U�����Y���<�`���7q��%s�v�������N�-@o�����Ku0���	<������v�>��Hm�~k���hH��"����#�_��[4���x6 ��U_c��������g����rvE�zA�s6	�����r���4@=�����
�]�_��gJL/
��2������I�r���F�HS3C0�$R�����-b�#�)�������5`E� �!���:����X~��:�"��:k~�X�s�tn�����z+PGS�����D���"�b�i�
.�>SH��0i������I��,aO�U�Z��A<�kN>'G�v� ��^I��lH�E����
������{���&~�io��6���[�  	��/`h��5�>
'��f����?�������N�e��T��	2�����O&����'�	UN]b.S������a��x�4'k����(���{~a�r=���D;����M'�`.����h�N��;���]����X��;wh�����[����w����H���4�b1�g?��1��	��r������a�v6d�q��+$?A�<t�f��i�����i��;v77x�_4p�;Ih=�s�d��*���8�=�%��^�b�QlW��\gB,:�FngZ"�Xh�������3�ksc���v#w}��\�U8q6d�����h�vv�����.�(g*8�c�!��x	�;2����_����7��N�����������������}��8���\(G���q����${��
�����+s�p����~�Ak^�$�����4�F�<;~u��6����`��������B�[n�l�vp0|g.���H|�z����������w�'g��V��I*{n�r~�����_Hf���vB�#�l�\1qs����H�@'Q��5����pG�rdes��i���6.HK`��[�=k.`��B�a�)7�������l��l7�J]���%��@;F����/��-U8��r��y?I&��e�46�&b��ld��$av������U P�����.��1�A� ?a0wW0`,.i�\VG����0���*�xr���
=��(����9,4����w�V��0o��W^�x�u���E|tT��{Pr9wz��%������;I>=�l����M��������Ki3:�A�D���(��%�y���oY5����.�Y�sF�^�y��9���F��?�����L���'�$M�<��M�g���@(�J
�x������v���J`�8R��UV�m�!/�n�>��
�ZTB��'����B���6���������$]�9L��o�M�����������s����in8=Z��!���tY_�d���G)[��R��Z&`5Y�G6����=$���8�T���W�J	#�!�t��\U��b2���j�2}��:*������d�{���}��#�\jG����Sk�`�+������GP O�wb�)7�A�T���fV� v�����"�#d���X�������2�W_C�����?;N�y)+K
�.g9����;aD�n��Xi��K��x;[Q6W2VJ���~���c?������{xx�w��y��z���Y�������/�C�[+����u�4�a2$���O%v���d�����3����[)�s�b.�,�J�>R�����^��H�*�!M��Q�9P[R�2��(�B��0MR2�6�{e��x��v*;H��A�<�)�F-��h���������#=�^������fP�K���*��N7��%Q������C6���9��1�����iZInnK�Vi�eDMw&$
]��ID���Ou �cq����,���&���v�^������xY8e.��}�{��@�B��H?�r/��`�MS�az��D�h�k=5k�i���v�'L.�n^595mr���n���a=�����y�D�Qn����M��W#�J�	F�0���'''�{zo�=Hn�j8���M5���oDY�����L��e^D"rV����E2���E'O�~�w4dc�j4X�	0
M��7��1�FP��x2���|;���l&�x�13!��Ji��-���$=��-M���o��V��,D��Y�]�JRV����Q����5s1��Q��v3��
e�-GY���Q��\,ME cx�]����B�{�=�0��J���y�����]\l�c*�A6A��`n�E�*�~��q�������28�Q�=9�`6fg@7�sOB�����zs�0zE�fBOF��+�^�N05�7������������c)3�rp�Sg�g�0��`w�n�����|�:�?�#��r%$z��#<���^X�����g�,M'3�Qbfy������g� �	6J"pJ�>l�����@�6"H.m;�[�a�������~�4]���T�W���
'_�'���
��y|��SJ�
��o��j�H��oK�)�����B����aYz�ow�!^l����,���n����<4^�SC\�(���|���]U1�06�NWv�����8��t���;���Bz�X�!�S��Q$���O���x�h�D��0�KVx����l"�n��.I3���N���W�A��Tc��LUWK#	�������&v�}b��!����J�	�F��a2��`a|�5������������9�����g��\D���������q�(��@�^�p�����PN�ma�;Gj���-�N��Fa��0��G��+�U'�s�D���1!�}�:Bz
�X�N�������0'��a�C%^�a2#��&q4�I��P����j.��=�:=�]K4l�|�F��2lkM��On�Ayd���)h~����8�:��{����D���^��k�\�������-�$
*"T���7/�.�1���������7I��/����X���������I��Y?A�U��F&K^6x�m<m.%xIT�����>��q�V9�
n�d�p����u�g/{��[=��f��>����~�g�/�����M'���=��n"�,8�v&O��R%�R`���,}�LN{��=�e�Z�x���3���gI�rsms��Bs���j����<[�O�{NCUb�-t_��:^s��:#<��{�cs1����PIsb�K�E�+�~����h�u��|��t��mku�`&G�H�r$d���}�^���G�!����}i�;���������O�zF������W5�B8�9�d���J9F"H'���'���C/�����Ho������cqh�B��A�7�T�w|tzpz�t67I0�$�V:1�� (J!��O�+S��zP�&�l��/���f�x8I����V��D��KP�dh��c+�B0����3�\����yi ��c�Ye���;�g��h�d$..'/,�������V�wb:f����{�"1�f.�&Wo����4���y��/�D|��jP2��d6����T6j��L3	y6*��xTV{mAr�=U�a������i3m�uM���Z���F�M��|��F�
������d��������80�D�0w���������^j5����I�����l�I���N�T��H�
��=����)�G��:=7^�+�- �I�b�����d^.�yM����e�l�5Art�>&�%I�$c�5����,bWy����O�l`=
��A���m�"p4�w~�k�D:G�S�O.�������:���!�\����[%�Yl����8�R�dD�&�.�������l���8����q��s3}���a<(���Y���z�$SV!Y}�U
N@���3B���TLM�k3?jx�t�y��H� ��nN&�c��o��#�_�E�NS��Q���As�,�WY��p���V�y�&48}����y�!qt*�w��M�[�e|��
�9~�[l�y�}�R���!�������=5m; �\e�����R=��{���`l,O<�lP*��"���))1��Bs&R�m�\���ko��;)2nx��S	C���A��R���4����M��t�����#��?��������+��$�����f�����/���+^� �����I,���\T��J._<L��J�m��d
4��������o������f�U,�	Kn�@�N=s�9D4�:���R�o�dX��p2�5��D����1��Y���kH��z�5�f�c�.Z��Y9pm����}����J��~�^��\n�����@��$K������j������b{����VI�mmg����oR���6x�h|��a�&���y<*V�8�N���f)J�5���3���2���:���5�xG&nj��U��e�q��������jqE_���:����s5mf��-�*L	�d����h���,Z�b�_����2>��z��*����2�up8��	4e����h=Q.��]|��6E����/[�U�|�
�[����@�������KVk�������J������{��� �8��0�ST������kU%eG���o�������{���m�t5W�i4y�gOT���$=�u�`�[q�V���d-��&��#��b��;�%�5�$��������/����������L{�^��%=�L��u9��2��N�c�(�?�xl�I9���Dz�\���4�L�k���k��_|�T'Y���K
%��!�����Or�]��x�Ql�1����N�A�)����\}�4zM:L!��{=�S7_�x�,��Z1��bO���M���[�
&����O�_�c��d�_=*X�)�v���B4�\�����sm|4��i��&�$��8'&i
���s� p��a�����x&�jN�D|�I�U�~�����f��4]���8 �
����'R1�X�6�GR�����_�&t�.��T��\B���xC�vk���u�w�Js�>S���j��q�zJ~;����W3 N��T���)��+s����M���txOv>t�B������*�wj�\���R�#PzQ|<��;�x\b7��k���I��_�	Y��d�}�&#�lq���������`���u��9n�OX���Y�%�O��]�����b�yqa)��A�$�f����wp�K�
�������&���v��`�k��e�s\ k�x���
��)�m#�.];����~��M�z�d�
;���J��������(m��?$������@�G~k�����o��o��������\��F�t�D���t�����[���8��^ou#Fz��>�J�K��
$��t�d�4��LP�4b�P��ZgP������r����r3�R���
P�A�����z/J�m�"�1����������c!#r~w���)����RO�[bL8u]Z����x\{��4���s�����P������$I��g6� 8�5�+��u[CH��8��o�lr�I/�k����[C��}�����n�[�cWF���Z�eE�9��;q"m�����]���$����8�#�d��{4b�O\�g6��	�����:��3_���z)3��[���9����8�������^tw���������q_�}�����3����lD�5�2w,CN�>� S�s�5�{qe$p�,��W}�n�*�~A���*}�z]di�Eo�[�!����H��/~%��Gy9a��,��P�h��Z#M�]X/3���H�Z4�l�s#0	��k�j$f�!c+D=�e���F�PjkE��hE]����t{���P3�.��N�l)[Fz�*��}b4��972�zr�a2!�$�������Pn���������6�s�����O$����k`b[#L�gWc	=!����\D����z����^v�	��i�����iy5A��^��Y�eH�_�7MPF���?�x�
'!VK,|�����i#&iby��e��,�����ANL������J���gc�c.����hL/y�G���B��l�,��$�s������p�S���L�����4D�~���� ��d/��5c���_|�O�������^���&^�//4d,
��ox=Xh@2�&L����t;9[���o�m)C��u�_iI�/�t�
.������w���f�i"[�$2���.q�!5�:8�Cp��,�8KFRR�A��3�
��-U�T����������Kt��Qyn<v��+���YR���L!Kb���9���0bkZ	{�B��-�8��K�D�������x������s�1��%a���d�N�4�h�HX����I�+e{�[�Q9�����R�q��-Z[��j8�R@"]��gQ��$�HF�j��J���+�������g�ur�VJpT[�n��K���,G��������td{5?K&.���4R�K�	Wx�Z��
�K	P����-s�RI%8����Z}o����)����������/�.�V8�p����81��6���&@�{����3��5�?�:������ K��%�D",����a���I&�K�!Vot=�K<��M,�@_;Nm������i�w����dU�k��4)j���^?Q�%�g�Q'���T���>|�]*,��$��k*��a8�1��h�(��E��c�X���#���+��%F����;6Y[������3XpSvB�����j�.U����$��d}o��=�,X4�W�tv�,�����}�����"� ��.����E��d��wHL��8�7yiF-�$	�r
/���4vU7����L�����c3������NN�s��"ODX3�.���>� a7�{<�7Z��77�,��c�����pzQ�20����f�	8u�4y&eY��������P�0Z��bCj�>?�=��$�p���5��k�*m�$)w����
&��Y
���0�3�<Hn6����7��P��QA�?E���M�����c�^�M��$x�`j���3��E��
��Y���t~���z���#�a4�J.V����q~3�B����ez+S2�[��������E����3����UK�T������9t+�%9j��nlL��L�H�vC�Tc�v�7��eH\��pCf����Is����]���`&F�(��;hs*q��Wb�!�$�G�����0Re�����C,���`:���}H���]f84�*	GC*�M���A��k����00���/i�7�/�gl�4�<�DPC�zT�������@���z!����]���Db�a��f�)�G�������(16�f.��K;'����<����P����W��c%���]P�
�O?�����Z�w��R���	�����������w�g?�bUH}�t&�E��)pD�L�1^g�!�uOw#�c�I����F�Lk�.��;���A���k:��C����h�����������������pp�{���f���wv���hB
G<>�?:��`&W���A������ju4�b�&��p4��vD��3Y�o��g�k:����4����+���u%t�&#:
�����������5�I���3M�$d&�>Z7Z6����y�Ofb#8x����
�U:���:����;��gs0]��k���e�u���5����
�Y2N��������Y����B���5��@	W8Q�bC�!�0IH\��C����/-�,��B�=X?�����
�IAM�g�J�x�����g"�:�A}�~*��$	���u9�t����7���+x)�c����d��ll��^�������#	�F�T�:���Y�l��U���vP���33A�`��a	4��)SI2��O ���h�(�<��c�����������{ ��w'98�S����nI�� a����)�F�y��,�+�D�#,�b��p�����9zN"39���I���[���!�/fU�FW��V�7\���\E�#	-	�)�D[�[��}~I�e2+�:/���
��!�k~!'���I$�jF��h�/��7�#�Z�S�8��72��:�l���feXiO<M�@:K��	q&Y������xEc��"��No$��1y�����-+�yT`@����| ����Fv;u��d$cP��h�dv�F�c8G������~��� �����������G���M�c�/�?��T���<s�<5Cz���U'=�C=1Q|P�rd��u&"j�ys��I
��������)&#I�
���.�V�>�h�v�?�%��J�^�j_�jw0L��w�3��g�����^+<9`�M	�����]�P�pT�(�j0���'q���At!����I�t@�L;I0����X8����BX����O2�8�g�yk��'�8n^�(�����$�4c�G�����{��>>%=Q}�����
�t&{�T�T*���EUyM��A�GQp.IX�O!�$
����������|��s��A#���a,�8 ��T���>���'�����*&��<:6Wv����`���-��fvk�j��t��-��9��2��������8LNc������\��\|���R��)����:�Ou�7$TL	���G����{���P#h���wXQ����v�T�$���a�'��Tm�A��>�G1���|v�d�������f��cy�v�u��TSU8?$f����f: �"r9����AI���[�7�|k��$yg}�����}w����NG6X�#d�$�)	�8'3����6����Os��y��Ic��%6�[���u��F��9��3Li�:�r]�<{6p�������O��+�{.�0q8L�����;g'U�$4u����@�:��r����P�������R��k��s��r�i��<���J����	���\Km~�e��&�����_�;����MDYs���rab"�������X��e#5�[	������/v��8��N�r9Ca6��*�Hl3a��x��{������Y����H� ��6��C�'���O�*����J������E����O�$p\�P�����������:�Ki���k������/�&1����������������oK����5T(f�u��"�D������/����4��Q�r���J�����J�5a5�F�Z��i��'xjX�#G���7=�Y�����	�FSi�	8��2(�l�^����	�l�k�`��3H��b.)v&����@2�86�������������_�o[?����d��;q2;#f�R������7�'���4�	��
G��"��I�����M��8��4�*���I�Lla��J������d��%��>v(	�������l��\^�����^�%�Z�s���I�e�k~!�x�rW53���%�E�{K���������[��DsA������%���'��~l�r`i*6��w�9�TZ�tn������I������a[���J�'�Iy����?vU�MACEvLf!5=��������H������_9���RM���U��s���m)L25d�m��"I��y�I���?MiR�(�r�u'����� 5��#�~c�3��vA��ECka��8��K���?7�D
*Yz
�\�vhl5;��s�N,�Y���:;�eu�����-ph��7Ca�a:�'/���k��J
��������Q���}#����-�Q������|v|����d�C�Jvd=Y�lk���jg�q�����m:�d��H]��|��m����g��&�$��eyPh���B"�w#������ZP����/��A?�.0���O_����f��D�XhD�R����b������
�O��/�!P���WJ�QU}]�c�%�����h .���X������*B�k�M��)$�TI4XCs<��
���H��Q�H���cZ��0�t��"N�/�������~�����}e���!'A�d���L?F�8U�4������w��1w<�ZKi�-��Z\Rc�����+1��^a=����"��2��4�3��w������X�t~Zj0p�-��\X�'���&����s�,"_�4�Y6�C�i[�5�T"�&9�����i�����U��W��<[�9P���g���u��sp�!�~�{��_7���f}Jg1�i��OT8
��'���V"K,�u�.���i���~X{��0m���X���Bl�[��h����qG�MA��
44�a�B� �wzO��=zn'�=�*%3\p;.��"o]o�[����8�_Z�D�p����k��kWY��]��]^f|���CRa���K��le��Z��w���f�rB�W������R�]���LMMi��h�K���Id|�d���uqt��N-����� f�L�Z�]qrE3���y)MBT�|����]�Z7��H��>%����A$��rtq��~$/��m�o���.���
w�+<X����W^�!m:��V��P�r�|_0�\b��p�6�|..���<C�b���(�%7��m��[j�I���T��2����`��;v[h\t�&��{R�[���2�H���*S�?_:I�\�Q$��B����&��_g�F���i�{+��+4��+����d���9[�E�]����x.��W��{c�{��a�����h�?�"h��j}����~���s������q�������ot���`.���l���+72�@	��{6�HH�����p>�3m�x������ta��u��0&�������e������Df<�8��o�+�lc#HM���4<������x(�T����)E�������u�����7If�r>���\�����k�XyrA.�Rw�G6��4�>	�ds����x�Kh71!���r����r
���9`�X�T�8G����������}C"4��1!{[W;��p�?��������&*�8[�K�)����h��[�/��<�A��TW���8��P�sH�cL���P���q�5/�������U����&4�����]��
F�Y�}2%�����6���!���w�z3��B��v-���@����d
�"V�IS	�g��RD���q��a<�q���<�e�)1��d��0F��	B����T�NC�t-6�������t}u�u�S�����&��L~���G�$��J��}0��h���[6��Y�|m����������Dm�������7�	���i�x&���o�A&Q.6�]g�U:?�$d�O&�l��)�Q�
���i6���������.�p0��:��@��l�1K"��A����<e��hS��eT-�)�9v������*N��$����g�u�Nv���sM��8�h0�\"�28y��t���i+2q��Dw4�]
��y�=�kC�$!���p.�vX��i��s�KC
�W�N&7&��,�y4����<j|'�'�
�"g���O4�9��\�����1���i����UTz�n8����fN��<,��WO��*_������O&�X
�P,
a���$����S��������^0��������.y��1+���%�3{�����WQ�$�PO�|x�#�����0� N#Z�
�}>���
'�0z����.�2i0����b���@0_e��I�Kt��l�{�2T��0�OE����?A�M9&:��[9�D��z����=�~��K����>�q�@�rW�S_��������g����=��j�p�l_��[Q�'�Zj�1�Bd�zS�)��S#e7�U[�����&y�^o�>IDc9)mlmm���p6�>�H.���%/�����Pex3�NGB�3���8r$(����A�>LFCQde
2'���O�nOk/���O�w��^�:���p5���h&��7bD��!|6:I4�������������_��?{?����;G��T���
�**�W�xz������U:�;~�v��U���
����;��;x��)��� ����C�c�ME���4{�x2V������U��I��0�T[?�����6sQF��� 9�����m�IN�e�e��CCG���^~=P��u���<(KX�[GO�D���j��oq�g��}�w]�p����+?��1�*'���%�2q)J(���	���~��bH�9�HX�P�K�0��,��M�wj�"�I�#As���r t��c%	�}b���2�mIj�e�d�l.z��S���^�p4-w ���T�;��!C�'����9���x���N�v��KXg����s���>������}uY�������/��Q2�,���i6A��~ON!w,I�!#[��9���AH����%G��;xb��A"vkrS�o}��I]�7;���c���-������c'�D�u��^<�9l�>�:�7���rI�|�<DLH�3��dQ?���P�m��VdV0�SR��%����F<�i�@�(������@�����8�d7������L����.��-�����#:��EO��zo�����U���#}��b(���r+|�rP�����"&'R�#������LS��mmkXRM\�mj��)�4��0"Q��5�$�������;q��B�V9I5�[exI�i��M���=#�b#����vM�hA�$�Lb�@QOh����>T�o����h@��6�����c[������@�U@�z��A��&B�`4��������dh0����?4����Qi�\�85�T�t�V�o���p�	"6�����`t��.��C�����d�z�Z���Y�������[��	���;B
����?��c���2hVk�*���00����7��-���[d�k�%g~������['�/2����]���%<���D����+h��V�������}m$Y�(�>E���-@���E�=��i�U���?���@��R��TW��~�5n�v�L�g��]FRdd\V�X�����P��y���>��9����=.���w��*����p�+����Q,U��s"�!�W��[�D�V@O' �R�ox�9�VF4]�0I�U�Y2�Fz��W��H���������	NeV���[0�f�[���:6��H��� //�)��!�{�o��a�$��3Y2��!�)�����SIu�Oz�a�wdC�n��������B���7�&�]R�&#���a,>�*��B����6��p^��[N�AP���
d��d� �����eh�����Kr6����.������Q~����u_!k/M������.*�Z��a��G��d���(���a�.O0���7���;Q����ge��MvQm����xvo���|����|��_�,���~�������Z?��1ZF��aE�$����F��J2��s��7'�tr_��hT'�vI�w|7��g�[�����l��n1����M�������@��=S��.���N�G��^d#1��@���l��N�����r��"�r���x�t���v���Y�l���Omsptp6������FBt�W�Dx4W�$R�cC�lp�g4�C@�p���o���U�|h������f��#OS"�2m����1�����!�.����[���C���AO1��L
��&�R���r��B(I3�����R��{|��=+����z����}�=�����f0��
llG[YkEM�8����+�i�� <�%-5������`2�VBi<��4��
��ECc�"�1���
5+�t�k������
wF)���u���/���e�_O� �:�;��)����:��/��vn������1��r�c���"�=��j/�X����������&441����d�U�2Z��I����b�4���\�����n�7[_�� >�v��8�����&h�L��i�
�C�:�������{��:��\!Y��x����&�"lL"8���1-U�(�H'�����t3��x�+gqP%�dO)��qalx��8����0a��d�u��i8r��`�d����T�,�L�l����\:�7>i�}�I�����@�t"7���V���cK���H���u$t@�����%�f����J�a�lqi���(���u�kr2�"�5��{�G���~�����+��hr�'�x�k6"��x�����9|wrp������
��t��������6��>l_d����������1~V[1���OC�_g����J�@t��)��R~�/!���������_����u��=D�����]�s�+�[0�WU���zNsa`�`��������"3^������x.����6gE����Ss�����-��
�~��i���F�EW/��6?��a��%F��}�0���a�O�0�,B�|���u�������;n�X0h���Gl����<[w���S��>���qsJK�4u���7��b^�nO���'oS�Pk5���hPB���T��Pzl�S�LO�~����\#���E�),��K����
~��dF���o�9F;}:�o��"km���;�Q�|��������K��g�^~S�dv�g�I3s�/�O�"���z����*G�DVC�B_N�
��y�N�J9M"������������r�}����QL���mH�'B�a
�g'��"���������9�t}�9?98�`L
c<����8�� 4�*i4���l�,~�������C?!OA���p���	��%����qD%�e���\��4%@hV`���V��y����*?��<Y�(�Sp���������{�=(FM��@�(����o�Ql�xl��,�%d�uN7�LT�~�{��$b�X���k�`�D�h�mq������B��ZA6%�������	j��&c@t�<c�S(i������KEg!���1��j�B���~GeN����{E���ZqGb��GFz����C��#�02��Q��wos8��7�:��|�c>p�g}L���>�u-��>MK2��+�*LRF21��eF���Q��5���"T���i$7(�������W���r�2�?�����Gq�_�f�D���j�'Kw0:P'x�
T���,+4����g�D�$g*��y�)er?�b9��
J�B��jP��9d�6#�`�J3r"�gKZ��H:�P���ks���9�!�������?�Wq�����Q�:gE�����0���������J��� *aX��p�3>
�+q���l�~�y �b��*�vx��{jw�5}��$�dT���t�����$������oL����z�I�N.<s-�af����P���q �j)�A��D<N1��<��B��{��H�L]�FLe���;��0���g\
=��	T+��>L�:U���8-�p�Nf��_�.o�����I��L�<�X�j�_d�o�o���F��-x�y���t���)"�+}���V{�O�������|C�����J���m����� .'L��%��m�SQ)T�%��M{�G��78k�*�vv5�F�����
����)^m���CYKR����z�K�9	0��#���������Sv�� ���O3"5�@F��wh�2�����&�	�zO,�%���
-�^�_@�����Sp�,����ss:���#(4.�V�!��La6i��#W�2T���LP���IJK�j �'7�j��#hQ7�5QxdJ���Ph�^0��7��2p����?�1`L?H������8��u2�v	����$B��0]3U���q�^���,�����+8�Gi�����O��f��)mP��mwo3y+*��j8��bEn)�[*��&����Wv��������l��bl�Q�(��V{p1�IW�*p�fL�,�O��v���~���[ts�(��Za�Rt���c������F�|w+8B���`�D����f�O3}2��"7������U��;]��	Hf5�$��s.�3����H�*����DF��{�?D�#N#������:��<����������W�1��k%g��B�R0�%,*�e����`5>�1��Q�Ao���	�#��cB�o��6W���Y1��pi����b#$s.�$S^j�|�4��la���l`.�*���KB�����6�<^�rfQ0��m�u�����n��#�-��)j
Z��5 ��u�l���kO��l{��jQQz)�����}�F���>v���J��������R�a)���0�#���{����SMPth(Z�����a9-�O��B�B'M���o�h�9�
x����h�oFN`�
c3���#��T�9G��,�C��n���R�`S~�Z�Y�Md�CmA�����8�l�\sr������D�##v��p��n���� ��(/����O�j�{�&���sc�'i�K4&p��U:]�.�HNn���Y�B9���(�)2#l�g��e�L���4�����9�vf=�1�
�������^��Y�e\���6��
e{��&
=p-�p��y���H[����r>j��v���`f��$�l����.��`i��,���I����������y����}����>��C&(x ��H���E�a��y3�Vy�PxI�M�@�e�Z��'H%���,U"��|�q)ru/���^��P.���������V�Di�J=h��(�+�JY�8V���!p������"�7�9\ux
 Fbh�U8���f"���L0�G���0��F�H�� �p�;���������N�������`�z�E,���u%Y��9�n���yEd?���sXA���ig���y��3�������O�vm�
T>����:G������"�L����0:�#;�B�R�dm����-F�"�R�[�O���s�" ��U�^)$GGNh&����O������$P����� �;��m^�8�>��L�m�!8e�6R��r
�W7�����u����`8U�a�\p��h�H�$��u1��<����%#w���m���4V>�Ni���2�:�n�up�s�Do��f�m�|]r)��k�k8���pc���1]��X���/����Rx���x���Jv���%�$e�GMq�
H{��N����,\@���B4>��}�VJw��"�k��T����
D���Hbp_�����Z�8��WQ1j��<MS�"�^������*�]�HO�kr���i���)p�����F�|C&�����W�������6guk!��C�/�@��N~Mo���8.�U�b2�f�>F� ���>Bhg���-K�*U���0��z�������9�B�ZKI4a+���
3�r�l���0�4�md&B+����$���+;FX�����&j��c�<���X�W�67!FT��oF+��|��i���$�7�(8=dAX�7-
��]�.Ty����|�m�w[���A�G���qr��sl���a'oK�6������y��2��DU�1Q��F.��0��	x���H{fkm�������A�{�|/�������J��,��X#��u�*�%�g�>	,�m���p�C�A�D������m�x�P%:bH�{#������\%��=�r�#4�"�,����=���~t9����>���K���{H��&V��;�F�"W����O���X�C��������'iL�n\�����Q���8o����EO�"G~��N<uP9��4X|i��BO�h�+'�
�����	��<a����J5�V�����w���l�@�Z����]����zXA��eF�h���5�Z��b!��53���!��s1�* `I�20�z2��NV��m&�r��n_R�g?.�Z�*���Z3���%~:����	�f��!�8�e�g��"p2�h�9�}U���[��� ������	{��i0|�R��T��z�al�����-k�\vK���������\P����m2�;O�)��k't�.(�LFe�6�1�$�0���:B��'���6�w�|=I������G�8����T&��!�Bs���tf��)b
`�@�D
��P��+�Q(��Ky�����N���f/�Z��-�
���b ��	<� ��������d[�Y'�6��.<X:��������: ���@Go~L�Q��B�����E�\��@�HbJ���{u���Hq9��M[���e1c]�Tic��������9�6p,�p�%���8�Y�:��?�Y�G���l9��Nm�:�P�5<��	������mDazO
Y�.��,��E�-���jZ�5�������u�.��}X&�A��SC�s����ww�&���	��-����
�b��,�DR�b �*��~��I��+���$��Y	1]g�H���E����T�����U���TD*l��|��g����N�.7����.�PJ;1W����\���S���Se^Ar]�5��6����o�&��b�?I������3L�=��My(�(|�����G�th^{��-)��n.��EKJ�aK�J��[��i<vb�q ���PGj�c���g��kz�7�W�u���&��w�(�o�;��F�[	-h��7�f\-P�I��hS-#�6 �R����0U������3<#���Mf�at"�f�
���K���b,.�\pBB�!J������rm�D�TwC�d����a8<�������kK~��&����(m�x���k�))F�d�c�Y���_�W��P|����Rr��X���g�*��%B3p�����sZ<=�X��Q��F�	Rd���J)�,a����\22�*��|�oY�K�J�Y�/t� lv�yLm��u��dS���5Gp
�N��.�>Z5g�sp^�]
�����8��Y��Y&�e�]�b���8h��	iL�����CMo�r;�����
���JN��->�dC"�N�/��^X�����r���]����t����4��/o�����"���dZ�>E�{�$8����.��3����_����%��_R���rJ
�e(Eam.
MtdL$��&w��,���4G���s0Jo�	���0$�RzNU9�GcN��a���E_����DC������N�|�3x@l��O]�%~�.�8l�#r�J������5�W5���s@yk����$Zj�^���|���Q�#��a���8��m��C�^����_����<�$1�K�$#���t��;����"$.�Q���=d4'1�����dg�H�����L�(�T�M�b��nWn����&T���d�{95B0X�������@
���S#(��m~-���O�@�������8����i���(����H�`G������'����Rku�A��)�@�C(�L Z0���36&e%�j�Z
y�9G&E�xf��B����H��>p�_!�����W}�J
�]��t��F�����E�(�U'����s��G����>�	pd>EB��6
Y���V2,�c��V|�D.�%Q�������^��Mkw�~&D�P�r��^�q��<-��6��q��>�����C�[��@6r*23�	I��	�m�C4���D|�g�Z5���92A�
�$���Fxi��C���0JzA6�}�YA�D�S�k%G��YU-Sf��&^���	�l0����F��i�<z�Y"Y�72�y�������"�����S���>�4��d4=�i�3�|�o;���1��tx��U%m��X������������
�m����������
wZb[�����?�k����AKC]�R�gY_FG�_e%��R�������1"�/Ha�y��_o�3����K)�V��/@s ����=2�NG(�KW��:��A�����d����#�S��A�~�x�
�
����,��Gv��O�����",�z�c���0zJ17�0u@ ���Q,���?���T=��2��a��q����e���BL�8�E6�4"fm�\y3���|&��C�;������G��7�o
7�Mv��p��N��}�����rw����gb���	3�V6�
y����GV3�>�����H����S��,�>`����t�{��1����a���|U�6��,�)V�������K�`s�)����p���������.�,1u��"��s���j3���Xp�F�8'j�$�1���{�����j�=�M���.}�z�8��59���x]���K����A�
4����:s�B�>i���Q%�i)��=r���}}�S������ ��Tb���&�NK��I� ���N�5��
s���c)�c�s5GBp��Y�#�
meK�8B6��6�����-���<��b�g\YrE�P:�E�kL�f���~5�;G���'>��a��w= zhz��?�P�'d��T0����2���;����}&�a�2������C�M2]��C�h�		aKP�Y-^%A�u�B�u[����Q�gI��5������<�Wa��3�Q��{
XBp�����e����7���yvM)�%C���OJ��V�������}��z��=�3�8���O�G��f�2�n����:�Y��6��y�����U["���� ��U�M.�-���2����A�������=��=�����I�glm�@T���~�����1�'�WBd�,�R.���&:+��y����&��q@7�A����f2��	�"s&L�}p�j)�����.�}^�_L�H?�����RP=�
�|.�c�f�9����P�
��;��(�Z�T�A��;�r�0�13���6�J�U��o@t,�����UJNz.(:�}��Q�K�("V�G�ag	n(�'<~�V�Z]K�O
�*1x�r�D�fx
�
n�k���7��XU�`��k4�����N4����4�����%�WL�����6[d���#�bP!�T�D��I�v��e����IK(3F�P�T����C*��G���+R�7���Vm�~�w8]8�"�%T���bt���,�7a�#7����U"����jpJp���?%�*[����m���7�{����M���%��������}G7�����y&�TE9�s)���5��=�[�V��
���o%"��(E���;�,����T���,p"nUw�%F�av�u'h~���G|�UD
�6e��8p��=v�?~Y�@#���	��2��kB��]��;F�)9y�)�FRN������(yi8���g�V�����',����E��H��fwW�M�jC���G�b�i�l���x�Q&�`�+tX���y!��%���aNa�X�w:���F�J&�D^_� hFh��n@0N����tSc!��cw���\a�7��>��T-qPh?$d{>qIw��D���k~������,/��
t�$P��aA��2���fYAk*�lw��.��/�#T��u�G����k����;!���7�d������� ��?B���]{w�l���6y��u��.��������z���t�$�&X>R��\g�;��u���i�^�9������\��_\+j���w �dd�D��r��RO2�=x����.�"]lTw��>{r�K�%�}�$���3L+h���+�>�ec��#�2W��y��z�P5�D���x`P-f~���`�����z�E5�]���1E����j{����-��M�F��J��C�<\I����j�-�1F9m�O��\3�%�����$�Mi6[�}mT@}[�@�n���� iE��2�q	��N��*I�O��jMu1@4�;���NU��1�%^����WP�(����V����-V�n'{��9��*�������3�G�ep�^e�����:�)����cx�����!����q����P�Tzg�0}�Q~�����&G���Q�'����z*q�S���O'�(�M�}. ��H<�I���0����N��&���Jp^���f������{�	b�S���W������%�{���mS�J��T"���P/!P�f<�PR�h(���KD:��/�ny0�lV%�j�qWx%K�0�F@
5�sf"������Ec�C�I�r>���l���*-��O�g�,��+N�Ze������s��8�QM����Ly�t�L���:a=�����u�B`�r�"2�F��BM*?��4��������ea�a�������Xp����3o $.�X�R���)%������1����4��^���i�H�3$������$��H&�d�+MYU&��������D�bG��,=	���Q������VX�=!T��{�X��lq���-��~�W
-��,S�w���p���d('���DG���N�|�������!���e�)m�*�[�aDGS���	aGd���g��3�I,@�E�6�n,�����C
�g���:�z3�j�$��4:�U�wy�c��8y�}l.s�RDq4/qUG�X�!��TlSM)���2#�����A������'��uS
������n�5s1��6������j=D�@���0o�y���[�������!��!����<`:�0���d���/�1�����,����ru0����5���ZS2D"��
��z�p��m��
x���w~�7�������p��������B�����f�g���y���5����4�T��,�#Y!4��J������q665�[�'���.EB�d�W����V���mV�;���L!FX�7�Lw#�;P����B\�}�"U^���Z�����N+���g�W��R�N�@-��8��|�$�1d��* GC��c��,]|Pvf�U
q�&�o�:���v��k��o�����=����~��|l���������q��4�&�-����[��$�#x)��P�V���L�-�q������P J�}��Y�`6��EX94
[����^S�}L�6����TAZ��(|��("��.�a0^�a�C�N�S��d��]��Jh_�D�������$z�&�5m���B$�^�d����L������!�����)�����t[�^�e���+��*6�N��4r�i���rO�GxAtI�)���ue��{X���UH�&%��C�����J�kc�J�����%�j;�b��8�6�����\�S�2��i.[�MY��[�G��_KJ=��h\�W<u���Dm�N�NS�}6�_T5_�Oz�o��z�<�)f��n{��~d���������-\���K�Q*����*�W��p�����_�AT8�?����$�:w�@�A��Y�U������r���C���8q�G�����))�������>S��6����Po�ts���"�S��O��e�Ii3�0���i�J.���7��}ZT�6Hn�q3�Fd����~%���d��T�d�#v���q-U��pN/��xp���Z�����U����0����]r�Z�+J��|��j
h�T�)�e���-��o3_��x�k���}8	�}��HC(k��:C�P(&cx���5�~g��~�/��uM��`�����y�(��U��<o�P=�n�h�$@H��oL�.
����L)<��{0�����#Dn��\-,� ��1��uc)n+���i%@X�<)����=qGy\I`�w_`�7�}9�������O����7
�>
f�2��|��8(����Y,�����F�l�"�>�.�
,�x<��!blm��--a��_?�|������{)"��b�u��D�����^��?���� �va�p�d��M�>G�|����jZ��,~�t��n��?�2PP�{��-��o���`�;�7��r�0��?�+��$���S�����8�r���".=��T�]M��9���o"j���7��l)7[
45$��X�n��p<�����	+
tn#\��g��Wo�������sx
�)A4���(���),:&�	���������K� R����S,VS����%��O\� "qn]�M~�9��	>�B����8��*vU�����Gpp����
����_e��~G�&����sF�<�c22��~_�,@3�����~�����#��<z!�����$2��#��L��#����4CWL���'�;g�o��/'�G��?w>~�?��??�k�98�9����i����)BO�_��_+������`Qd����F#�G!h�������k*�&W�E��@�%������C������p�`C_��.���1�S��y����)��:�hq_�z\<O��������r�%�=:�MO(�����_{�}��r�|�������?��l k3�x�X(�u��3���tAT�U1��:���5��C+�JE����Wi�/�����XI�8�X�����J=qT{����`����(^
����Y�e��(���{q�m��c�X�*�]��d��~��
T�3_�k�5��fU;�.�)k:*����x������%�.�_���Gm�n;6uP��;��U�A��#��*X���L����.��p����Jx���x�����x���sC�s���(��4�W�,5���
"d�d	:8[
Q�5M>&�R��-����:���+����Y5eyM&-�9\u�WD	�������["��ww���s\	�)DP�����[��J�����0�xq��&�Ry=��R=���X�1A�������u��tiCI�J�ke���s@�'�a����Z
�T�b��y-�-6-A������w������ �y��3	�2�����
�#LR��_m����wG��5r��M$A�r�f�>@8�*h�*qEq��Q1��Fx(�f|���]���+7�/��"U��D�@��!����fjK�8�aqX�2������+X�_��K��MW���T�!Q�H�Z\��M�Yn96�m+��vl�R���H-�J��M��k�l�Wk�
��5��$8��,�M�*��1�����������]�d`��V�$��$Pg1���@d`-���4K�X`]
)���`	S`��+�]l6���_^V��������F��S���>V]��M0?&K�����LzF�K������;��l���Q�%=kP�]������`�]�fcM��'{bM�&T��7���(�;�aL/�G��Gg��:�.�
[�B�Y�a�x��%vy�-�S!�k�ve\4'XF
����z�5v|��R1q�]���I�0�s��!����P�.��P��T(�)X������ ��:��0L���i��
Qs���4s\GN��u�~"���
\m���Q��HN�����l����2%��x$F�]�F�S;dP�f�w���m�\��6?`*g9�?a�u�<�W�����!��)�3O�=�K���������w��3��`������{��5�}���7L�[�����VF)����T�M0�r%���T^<�cV��#��������p�EG��O�N�[�6�6��_P������Z�S���c��f�������Rx	c�VP�$��J� 	�y�g����jgB �#6�����2�������`x+2K��b�R�]��7��X��;$)W[�R�[�Ck���=�K3�b"W�aca��Z#�H	k%�)[�Oz�F���s���Sc�^a��a��#�wN���n5�`��Q�u�7�_jl���m�u�M����-���O�]�	K���.-S:�,U����0S��3�\O�t�/�]\���Mk���f]�`�>��a�zu����E�eG7���x��@\}_m�k���?-|���E}Uu��K�G����J����S��d)�4���"�R�����n�!�w�� p�,�I	�!��S���N�j%���AWp�*�iMA��T�7T�N������hL�5��u���w'�����c��f<�?W���<��������	������F�R�oH��
��eJ������D�iPc5}��A�j����SBj#v�o����P����E&|�����<��&�����;����
�%�x�SM��s������!gf��j�����P� �i!k|h�&n���8'\���Q�����wJ�������V�\�����X
��F���_E92���j����@�;{���.�1n�����%i)�as�#�J�����X��	9��G�%�:d{<�^
�!�������+dM~���fj[m�T��A�� �v��r�p*p��D��J�M)`�)����3<��qp�J� ���2���+����]����Y�&hH�����~*�� �XulS9
���k5���
D�����8�h�hq�&��,?t���H2�B���S���N���K}�x!G�������C�)E��p��<��%b���������>=���\Y,�����I�aK�C	����6��J�}9����c�	_��HU��y�J��st���g;���3~
�)>������G����8'd��W�$g���~�tW���F�u&C.7ju[��ltI�Y��LM��&�,�����1'��km@v(<�xiN����$�Pq�t�K��wN�("�����@:���#8���g���$��O�s?i��s�~���?���YB�*�\_S`i8Fs�+<�svfn��7/h��d, ��A\Y�_�k�"�G�.q��������d?��o�?�DOo�c"���N������f8��<��7NT�*k"=j*A�D��9�	�����{�]��56�.(L���'����{�PqP������
��#G~��b��y�8�|���������'(���I��)Qu?��
�/�(��9}�{v�������_��x���������&��$����w���S�Kv��V��H�i��f��:�}	�4O���qzA������v���Z�����_}'�.\O��6�7Ip%�����������v������1��gah�G$|�:������^�2dWtD����y�O�cT�REx&���5���w ��������C�$A���r�L�^�����RJ�j����_H����T;���T(��m���IiI0��~C�����.!��Sa�]6��G~�K.�MOs-7��2����9^��3�?�~19���j�K�������;��A�q^dc��5I	b��l�*a;����V�{���yL�y��������]�%�|����-'�2KG��p��������]+���6^���������U�d�00�����J�o������U[��jn}OA��::�	t�q�:Y-M�x������p�����+�zxeT�H�I�F��O�x~��nq�n�Tt3�h�K��}p
P���c-�����u�?�d��Q6k��+���}�O���'s.���`D��;����H�Q�U�}��q�����@�����i8$�L<��k�������?>9s;#�3���
��[���6�G���	S�"���{�3�^GU!�� �A��n�$�;tq��9^krZ���J�����c"*Fw�Fl��q���J��_G*Fu �&�����r��P�����p�Z�W=�+���
��/������l���>�%�������8�/���F\�tSk/|:�)x��������,�L�&Yp��>����8�$x�R�H���<~"�@�J��5�+m��0��0>�%�k�a-������Z��9��i�^�!����0��F,qkK��C�)p�y.F�����N)���.����t��<���FH(�B����N����HPp���!^�}z����.}���v�2q���M��n���3�'�*���V
Q����y����d����Y�=����5*�������7]kr�2O`��B#��,�����w�#�-�{x�f�U��+�����a��t�`�Z`�W��������
N/6#*G�,:��h����h��9"Y�bt�,=p8���lW��(�?j���a��<G�yb�+�����p��6a[h��[�P���+[�RUGk����������6_�a^�F�:^3��
�����;1�A
�u��1�Z*�%�N�S��@Y�����j"��%�����JEPtHv��f��
[�9?wx�l4���h"�;A�����Q�	=8�<����i1�Yn��9T�yt8G����9*��������h�|c��2����/\5������V�5�"f��&|��*�vV���(�/��_���"-�����qq�;i�s*�7��u�z�j�l�G�q%��&�m�)���J==�����F�y��6�,D���{�W������~9{����&}��������m��=�����\z���+p2"���fh{�D��J{A�J*4)&r��Y�$��t��:�j8�(F���"�.9Z�\�z>����TOt�z��L�)�a�:��4>�6���vm��o+J��R7S����v�YJ3,�|&��r~�OU��V�f8t6�$S��m���,��a��y�~�-���	�F����p�����L�q���sv&������o�d<���abZK���c��&t��8��`����2T<�����
�?����vT��z|�G�yLE:���xA���!�1j��Ff~O����)A�~sE��_���o5vx��^�m{tC0�b2�f%�H��OFt{�����a6*�f��a/��s��V�a�e����KZ5��<�J����!���!�����C�P#0[�n������M�'gD������Uw���f)��3�����k5�������l���G��l���ir�/a���oAk���u��XH"���K<��(�%I:%D1"��]��4>��h������������g$mJ�i�rCi�
z���bU��"����%@�f�]�
x���Q��X�yT���b��=Or��P���y�w�~>6�3t�4�'�5�K���]�$;UAzD�H�)��;))\M7���^����uz�y�X�Lc�+=������")��������i5���2jc4�8QV���"T�yBD�(:��Z���E�����J�D
�6����)��rG�7���R�`Js������:"�F�l���g���#.E�c+&*_�HN�� �\z�o��5���"���C�lv�^3v�X<��Y��hp��!��P,�O�o����i����'���qh���U"�����*�.��!����Q���t�$p���@g�8��l�Ee���%�����A%�.�r�u�-'������1�b�� ��4��QAp�d�;��o��D�
-��*\%�G��_��Q��s������xy>p�qswYj�J���������r)Li�.p=��;�o��C���
EE/�K��E��R��Je4���B2iuM�^�~,��7/g[(�OSi����
��R���i�0��,��k����<�":D����6��������$l���/��n���s�����tB7���=zt|���f ����������g;o���E����9E)D�K15������������3�����-�����&���a�>�D������M�gG;���w|������_�aw������O��{��:"3q��S0�V>lw�_���]����T�!�fk2����>:���
@"r�g�T���K��u�]s��M%Z��JK�:�=��_��Ox�tV�,���nV���J��s���"*���Yq�@����1\��'k&$5J�<�+����"��a����d�i���WT�T��AA�x�?9��\#���OA
p������J<�!9�Txl9Z CN���[�+#��*����3�
�������������I_n�a���@
5|�P\[W��] F�}R�'����'���*x*���6��%�6"Jm���AC���g��mSs*Z�����SlF�Qz���U���#M���A��'X�����Z@v�)��[`X��;>���-$���q����8�vm=Qx$��z�����Q�#�4]w k��/S���?U]<���[�����+�[���K&T��*X����@�#XJ�B�I�
��4_�	���U{:�4	���L���*J�f��V�K�������h��|�%ip[Q�W�p
�B�5���"I����.�E��-��6����H*3:�NG�KY��It��,u�e��8�Wv����T����l�3{�]K�_����v��a�o��CT�E��uT5P���[l0|�A\���58�`����2��-��'W"	RRG�lz�B����GP�G�9r����X���(P��qK��[���JSN)R���������x|���P%>����X��]��t��eu���y�3��N{h��)��)��n�JF4W��|iI
����h�����5j�e����#6��c,eG$7�
��Q$CG��Ot�|y��)�+��1���2���j�+]"�0c_�	����p�S�6�sm�^A"o��_�S�4'M�:���kB��yh���0�����[���@$Wg6��oO)���D��Y���V��i,��i&��W4��;������75?������0�G1cD����B%S��sv�y���<���:��D�2K��Z9F�y�/�/�A�|���F�������]�;��9l���rrp��~{|�a�����EM�K��ZM��������i$y����������Z�/!�����{B�n�=6������Xw��uGs�����t��9�5�3�w�r��+�z��G>nx8-�O��[���+���J���Z�aZ��F�5��u�@H�H���qn"�F�
��{�|��J�a�28�r��'
xVm�r)@����������*}��8p$q$K���
K��!�Z?\�/�u\;G��i,��5CI���&���m��kk6�'4j���y�����OVyWb�Y��#�7���S� ��c��:?�c�����q�G�1�����(�jR��A�t4��u�|�n�za.��_7��DSg���z�)?+�1��:Z��Tk�7�8��er����8�h�]%*�h�u�,��kv�-{�����w�U!��;��&j&�����0����*H��Z���(��Z���4��-Fb�F���(�u����k���������_�}����f����4Z��|P���o����L14 �&��N`��������
��uzK8��pD@W���%��|��@e�
�������q�}Lk�2Y���.�-9�:�*~WiN��/��{B�����
>���
��W�m-)���R"�JX]����mdL=�� 5!��|��������b�rlS&�*�O�< �1Ru�!����NK1u�3r�sG���p) �I�v� �-�����7	Y���c2f�]|�������Q[$�h�I���|�����_��'d���������L�r��$�hI���U�u`��VH�0��^��XG����b\(���F�
��E�u�G.�y�y5f�����E��#���~_��p]��_�yO���#��A����J=�K�.�,�n�Y��2��9)���x���2�kv�l��Z�����l������<�e_aH���������O�7���fs���g���;����1N���N������(e%��H'����r����&�@)�$�J���HU	�Qg�/;�M��8
�1�8��W�/����iXP>P4	�
�������S�K&����t�_E@w�D�y�����S��� ���sK-��zi1
$��g�p�yT�����
��:��@��!�(m���$@(*/Q�L�D�?�����%��+-��hd�?D[�M��"�Y������;�	�}�����YKz��H�)Buny�6E����B�[x.32��������xQo�Bm3�G`T
,���p��e��V�
�����5������� g�mm���o����V��<P���	�A��?��^W)����#m88�)4P00�9DS+���-���](m��~>�j^�=7B�s��C1p��r>g#��1)�&y��Nc�H�������/� ���K[��}�@!��wd�z����P��}E���:a������g�����$�]vQy��1,���;�C�9�b�x�4�I�&�c����d	9��k�l�^����~X�O�*8���U"mO�Cao�9����8��c�?'X��*����������e�n�3�%q��#]�O3����s�|$KU��>������ZVj��{D��`�7��!�E�sS��n�������e���!���b��,�*a��s���A�)|��J{��F�GzT�H�7)��[�[��$���������O��R_7yOB���,FJ�veK:��Ca��N�9(r4�el�A�,$��j%����5������L&����l��V:�����S����''r���'`%�OA�.��p
���j<��!�^0��e~����%��A����
�!��_0����e������@��o<j��������A{G����U���2����^���W�����d���������J�X�$� � %HD{/�_���1�L��j���&����4��K�k����4
&_����y��2wWZ�)�_��+���W�T.��`�r�_c\0Oz�s��.� K��[��{y�n�,S5�,��|�q�����W�y�S!��}H��Wx1RAc�:�n�!in,��>�i_�
�1m�R������h��f"��s�u��E�����F���,��EP0-Z�ujx��s��f�kQV�J�/��6@����b!�2���0EQ�c�Ij�D2�wJ|�s�n��@�:�G�\�J����g�@�.zzj`bg<��{FY�#'��qsz�]���@g�(��"d��	�P���v�3'x��oA���~>0�0�����gn�[>R�;������x��/j�u���	���nf���>|1J����$���Z}lM�Q������O�{�{rf:H~�?������yO�?U���O���2�=W����o�����>5����rv���C[b$���w{?�/���(S���H���;�k6*���>�Y$���s�����Ov,@t����.����y�n�r�����7���v�~������l��O�o?Ex2�]��	,��|�&�s�d��L�J��~��@G�'G\HT����&���b�8��A�������#T��x��R,mh�u����`����@�y1xP�Q�S����v�Yy�q4�=p�����I�0�T��%=�J��_9���,{�mGEk���h#t�$�&2��R��lT����	D&L
e�[6`�t��\A���IIi> ��������M0X���`��V���E�1���Y�q%~�����T�U#�A0m��O���E�%�u������b58�����a���<�&�ge�J�bR2�gN%������+R��;Z�0-�c%�j$C\^ma�(M��d9H|��52�i�)R �n�l�����t�������V�X��P��D�(q�`���lmln���4��E9���?�w���!�.�$��)zh9��������/sn�I<b��e~���$��#ke��!��l]��~���-!Y�._�_c.X|?�;i��/��������-���g����7 S�J>DW��Vz�8�����U���K�>����#2��2��5����hL>u?^]���������P-��yT�W�/�:��V�����+��������'���S~�����K1���zB��_��af)��9����>���J�dhr"'C1���p��S1l���:�s��������{I������tPb%�G���@�zSl�)M3Be������T���_X��W�����i�,�Gi:;����0���(��`�(���:�hK������/+7�Oa����#��� ����5}�~�t��4�+7�yH��^�1xo��J������+��#�%��s��!F}�K���1�wa<��@f���~�x�.��F�wM���I<����(c+@�D%�m�������=IX=JN��i w��L���o��S��l����rS�qK�"�8u��pN�H�K�����D��.o"�+����c���B��; �pBO6<�0���H1��8��E����m�v|g�E���l�����sc��Pxr�q|����������"�^�)~�T�k-�I]�-QI�[B6�d�1U�|�>
���AF������_<��l����g8������� (�%fl��-�T�jTGn`$����=h5��"���g��!)�q�$`g���9a�K�_������r��x�|�)���`7(���(������N���a~��T�����rD��C�����sB7�����
��<�&�v�|Z�����
3t�]�ZKA�m��B���������Nq�7�bWh��
l-����d�D
����b�o��\5�����xg�q�u�;w�nd�|�OD����ZH�M���z��GRzp_���5)�+�T���h��%���Yf��U�ZU#CC	g���!jA�d!nA��s.������NP��R.������j�3�Ot6��
]��4!�$�0�U����_z��Yr��7�y,.9�9Z�p��It(�a���?�������DA$�g CZ����qFAE���&����V��Y�~��������KCBvO����~GN[Fz3��t������q'�/�>��D��8n��a16`$T���%k*���R [7P�"�9��]���G�F�0��O��3�-�\Lh���H)dH�����B��%y���SHy=�%F'|��"F�m;Z��zV<�+�\t"�����'�����3J:o��w�YT�,F�������Es7.2���)'�=w�
�S4�{_��q�������i��`�QD/j���������@s�z���<�4�zg7����������p�P=�J���c���C���|T�Rx�Ay��D_=�U�'�����G��]}(>Y�}E�}����=�u�k�q�V'��Ef�
&�x����)���Ivw�`���t��Qv���}�L|�1�zCAR�x�����]=���n�
4?��XKAoA�Z`$��3D~�h�^t�����*+s.Et"R<|�����jmH�_�n�D�����@
��+�U7��7������kMVl���t����Wl����7(7t&������|����j�G��R��u����vf���Rg��V����A���3������t�A?���v��B���NBKr��e�\�o�
t��*������{�Vw�w�yo���������#��������lf�;�(~�b+~�r���Y����k��^%AL������G���������yL���aCA7)w	�g����R2G����;��J�a����@�������Nw<��hID,��sA������8P�J��j'���4��9FX�l����u*G��U�&���_E��aSh�����E��)l
��aC��k.��9�YMU����:	B$�����d�92��iG!N�'U�eV��<��B�m��2�Y��U��ZD��f���Um�{�;z��(�������m���d���
��"\�#���
�3���(�����J)�sB���KXMP���M=�o1���c�)�n�`��9z��Nyg6��C�E�	N�
���P������DY��H�Qv�ku9u���4&�b��_2$qP��I$?���%���S���t.�b�������ZKz��h>�
����tzg��Wz��e�]�=�Y���h)���S(c���,b}]�y|F'�m0(�p|�d9��CD�������������i3����&��~���$b��.|�n�)�����P�-�9g�;���q��%k�d^�@r��z6�B���_eh���0h2<��^��KNg3�5:^�*mR�Gw	�7L[/��L3�)I��o}z�������V��5#��E��<��N>W��-5�H-���������<�{�do8+��g���?�cW�������jXy�f��ifV�:�t�W5%���n�*�(�p��xir��c�]���>`s:�U����������f��:���
��6�2��!�8���;fh�H�<	B����\L��9�w1�������$`)�p-u��kWu����T������+�{ii-��$��|�*9��D��EF����������K�����58YNE+}�cOsq'�E�&N���k2s0<�����]$�P���-" ���c9#2<
'f���X1���q���P?�h"�:��@d;��M�x,Ry���c�����D�&�f����o��g8��t�����x�&���"C�����Q�)�Q��]2�V�5����e,�`$���;��\F��yu��y`��G�8f	R���,>���a^�F��Q���	u����	R�Nd
;;����
�X��w����i&AN���[f��~MJ�2��V�R� U�Xr���[�!��e�������=��w�!R,��z)�%5��]i��������x��B���qW���!�����|S`,��6c���
|��HC��"I�WnG�?�1�+�����[�i��|(�U�+5y�
�a�>�ZyD!��U��
��l���T8�
#�x�n-i����Et��Q��r��o������������$����������J06\�\k�V*�y��:jq���_�uSL��b��K`��?���Qs>��0 L���z��VdWCL��[�g��+���S���m0��(�_8�_�v���Y
�K���E�/�:7���L���H8j�t����iQ�
���E&�c�F�x^��UMl)h�82�+��W�hP)q�U��H%�-E;��}��������j�Abr@����v�L���h���@lI_�La�����BK�Lg�Jl
�5��"r����x����;�D��'�v���>��2T������,��?%�k
*���L@���.
�lq��Dn9�:-��q���x��p�U������Q��PHp
����]��|k:i�\�����j��/c ���"z�k����/g�QpL[��B)��Y�l���.����2�x��D`T��N��n?^��P����=�q��K���|��>r>r^c�w;a���w_8=6(�6Q[�}��`mw�b�+�3#��:�5A�D!���}�,�0�F�HL]O�i����H�T����+���yv>p$�XL6�:(�C�:^%���O�?�����9��?w����aS��;f\#t�m������#�F%���er�$����0��WU3�0����[fpF��aQ}��	�Vrh��KcC�+��Zc5Q��x����+g��@_c4���fa�"b.Wo���K�!������e�U��8=��C��${?��'���P0��s�hT'")���e��D@�zG�R81�oo�Kg��Y�|K����Y�k��jln
y~n�x3������!������ou?�*�_oiQZ���-�t�����P/s�fP���}��E����^k����oEE�+!!U]�����E
Jl[\u~�I3����~������u��"�ce�Kr�*=3,��������\��?ic'�5�U�2k#_�C������"���������V+��_���\'q�d����S�U�Wj��FZ������)"���Q,3�� ��?L��`��t.qH)*G������83�������+�S�BjU��Jv0���5!<,K�	����*e����*�c�V+�2��k��e5����
���h�8E���t
?I��}^) M�<��=�1�������Q�\5�{�4�|2�^�����^���P����W�T�g{�HcV��d�����H�=�+I"ZM�
�v�D��YQc��������pB"9�<�
j��U
�"0�0��=o��an�N"q���\��J�*�(E��e�J��T�'�Wl6��
��s������|#�m6&;fO�9�>}��$
�O�^ {$|�r~�Q!P
0R�'�����Q��W�X�/e���45O�	D����R��]sk�t��)y3��I�z@5��P~C�HF�hD����Z�S���c�O�\{M�^:�V$��d3j�x	��R�$��(yR
��vP�x�gx��.��#�X}f����~K�y�@'���
0�P��3�F�
�����D����f���kd+�D��*�Q,Do�r�"
4a$
�\�VRn�6��&���@Z�������7^�u��H7|�\!u��y�z��&>�SWc�0D%wbw
��H����2BV:2�	x���T]7����Y����M�#o1"��T)�	��9���v~[�Ak�uY#��}��$yo�����|o:�7}��\8f]�����v�� p���t��~
s�RW],��-���'����ZJ�s��qR>2�����-k���t�z���`A��B�a\����b���������:���[d�>�x��Czk#��V�;�/P��c�������={9����R������V����z^�n�t�L����tZ�{��=���H�?l��Y�(�bI�35��a��D?��|�
>�����m"�e�M�f	�h-�C�|�������<��*~(YX�{�$��)5��%���*�}�\�^��K�%�N���:���x1nC�;Q��F
��@ ��[h�K�D������W9LP~�R��x�@��CF$��xxS\v[���-,�&w�V����|�#���o&������-a5C���0�6�.t�PU�mV�yq>�0�E
X2�{!M6���#��R��4k����
�[�J�(F!���c��\s�	�7jJ4�-��g���$��bw�'���`&8�Z�m\�N���*�T�(9����xX)>�d��;�!�08���gx� ��{\�Zc64LAJd��7�6��U~�o[�������zT�
�����f���C��(Y���lL��0�i�D��)����#1_s�=e�U<��p�l�`R���b�dM^i�Az��)�(H!uj�p���U�x��-�
n2�hzZ=O��]�J��������'���Ct�i��q�D�8�MU�#Do3K�ux0S�����DA�w�*����vP|���(�`	r��D%���V%PJBU��"��vX���7?2�\�/x�F�J��Z_�@ �]�"�/�v/a?+T����o��b�M�\LF���CR4�:�B�D��T���h2�����/��/`�7W�$���vK���2����V]�l�>��a���>?�����M���1���[+I�*I�N�o�[�mX��U�v����,
�(TTp�i,������&�c5+�O�����vk��2WP|�)�B{wMe�0��3��(qX�'��)���},�V8+iyVr�*���BY�N���D���l�u���u�T�^�)��K�`Z������(C.��l�Xl\B��	�{�L,��������;���cf����Q�	
���-�R�i_��|C	5!{�K����Z�~���w�!�D�'(�"��_��dQeJ��#`���]��G>&d�������V:�L��t?j
��2x�M/�Ic��Aj4�6�y
?����?G�I�@���U���a9}��
F��H5�\��P��T)W]Em
�6��h�Ii��E1���M�~H�d��[W
q���V�z�f�(W���b�z��$tE	��?G���������r]�tPh�x�[s����k@^����6��H![���������O������������X��I45|1L����n48< ���go��p��Y��!�
�#�K��������h�����#0�c���]i�)uH�w��$��U�����/]�C*����5U@���g�����RW�&�GW��>����	dLX]�A�jJ4�����3�����E��"�cs�{F�u�+�Rj�PO�W�����d�Gcp]F
���kM��p�&[>2��S�E�����b�Yg���$$P�����N�T�$���+��s<�sz}����q���d��y�[_��s�_����}` �5~&�KUF�k	Gnj/pW�A�DO�@N���h���z��Z�0�0+�ON�S4��1�xm!�4�G�JT9C��8���\��q���)<o�E���%2�-�{'����E��kg����"Lnh�%�:I��:��_��8���k��5x"I�1�+<��#r�U���r&P��s��s��M/������4#����&�2E3'b���4Lo.m#qG��2{VJr�F�{�k�����7;q���W�~�d��m�f0�7)E�:j����B���V�Z��nB�2��(r�������X��|�����;F5aY�nY7|KpG�d����$���)���������U0���K�
�JV�9!�t�Av��M�����C9U����5�v��s���{��a�%\|����x�����W��SIY�z���0��b�2��������(��A���_�:��@$Ik�!������qE�@u��;��X7������G��3�:������3�%�z#�
��B�p��r9��aK�t���o��~���N?3`��c�������-���)TBB����>47hS��%H�j�����!AW.(��.>U1)���V��P����%��/��
�6�5]W���j��f��]V������J�c��^�?E������)�|%�b������5��8�l����"��b/��.&�#b���#K�,c�5es���m2������p�< e�*�q��O{m�w���$��?���C���F�H�0l�r��:�)Z�U=	���������q�p������pE������Z�~��7������ER��$���9%F���v���F3��b�cf;Z���}>��$dG��}�����3�&�%aJ������<�(�]�Ir�z1�z��[]3�~��
�$#,�����1`�$���4��
J3(Q�U��1�JG���4�)	��C��|,u�R*b�T\�QG�ox�E"�����>�}+�2�����U�@��l������p���c��ohjP/Z��]�*��:�H����V$%h��".�"���t�`��\���q�=��W�:��Uc���T#��M�)A��	[y�O0@13'X��9�'�����P��k�I/\�:���mv�u'��K����+�.����F�����_�����B2��
?�� �\ /L+�qG��,5�������%�\U����{(\��IJ�H��T�����D-{\xc��6���J�n����i��81�[����$���/���rd�����*8ZI�b��r��}�aR=����x�\$�L����<��1%���
l*�'�OUL�G<�x�|@w���Lo\CP��sc���%�y�(y�:�_��%�ZJ����f�F���6E�<��$�\L�$sJ��V������h(�|I"uWN8�}�l�Cs��L���6rf�f���$�2�;���Qw���+�g+?q���Z]59�H�q��:�C����fl��D����C3�tS�;�� *(4xZ�&�2�cU%<R\9�GT��hV<hN��\�PM�q9���BZU8G�p���|��:�����|R�S\���t!e��Q1�OG�����:,zR:GJ"4���7���	y�BDI���8!���Cz����t|�A�T����4���� �)w�vn��	�o�p��t��CS"\4�%������	R��x�����E�<+Po�������~��F���iw2�"RA�<��0^�5���hID
8`�8��RReqm7��aa4��3L�m1:�/qY������p�I���_h�y������9@l��b&wqb�f����`c IT��bx�yy;��`5��&G���4tJ��JL�B����C�G
t�V��y�\p�L6z�h!�w��LP��E5�-���}M	
�D�)�'3��ed�us���'�"���/����iw2Xjr�'g��rW��-��UsHd�R�(�����[��	�5���aY`t]���bOs�0{O�y���i�@��h�����B���C��J]f�0�bt��i�=6K���/���fI�����5��K�N��������Q�,�#h�=Z������������I�p�8~xSHF�c�>#�4�������������;�����>��^�j_u�����z�i2���`���C���xB����u���^��T��_./^-��%V$��9����Y��I��.�

Da3	�;�?h�z$�1#:����bx��<��X�������d6EE�
��D�=y�*����ZlGq�x���Q$�8�~$&�|gE_g~�� �J�ljV�����k������]��R''5���z�6��m1�;2���KX��te�y�u����
I�]Ld��i%�%�6eLm��6��=�}-��"H�Q����X�
l��X����M������#��K�RzY^ez�G��xP�z�^,�y�R���	�;��������N�)o<�@yX�xHF�
��(������������n�AP���T�����P�9����	�?�@�L��Wp^�=CKI%s�F���b+���l��]�H�
���oi���v��Vh��������9�X���[
����`�jZ��d�$������X�*�M��W����]��������X]���7���X���Q���;0����|8����K������5}�cB�+�m��p�Fw".eb~�p�~�$_�0M�d-2Elu�i{�d|��t�O�� �2\���feyk1w��Jl���_�X��
%�I�:.6fJ38��5�X���@�6���j^���0��)������1��=4���L�����i��|��r��w�}��B������Z/E�L�k����&�����Z���Gf�0�,�Fr�@�y��]���7�S���lC����!p�1���*'���hF����������6�yr\8�u�k�&�;����
����\�7�?u��������q��`JQ�Y��� 0��g��AU��y�J�[-
�~�
��u�P��J+��������7�<*���F^�J��\S��'��k�x�2�@���fRY�
ovzE�e�?��Z]^5'�R�qj�������,JbCYv���3��������QVO&�yF� �5����6�������3�o_������j��^+�,�Y3�i����@`��T��<�i���]����g��B��.�K. Q��:�E�~����k�����7a�_xZO6m�3)��G�]D
Cw��y�y�d�^5���f����MW�
�$���;^��YM���A�������z�@�%�CtO��d\����*������O��)���7q�f��(�;k�����O/d���54�fm��Su�B��D�%���I���$I/Q	������.E%%&{*��$i�qN�y:r����9[�Y�P�#��/}0Q�A�bX��rX
�/q����s�����W�����&�(�`d�23/qj�t]�����B~�z���r2��z���_����M�0���Z���+��9Es��pY���;|�x��ms�g?-�^��va���&�)�������o��g51&k���9��o��������vT/f����Z�I�}�!���Q�+�wfOp�y�|x���������:�����h����L��0�k2�aZ�7y�=V�%��Th�d,����(���1vM�T
_S��������
.����0�d��z-���hY6L�G���G(ly��H0���veX�6�_�:`fp�IU>��=Vj�:*���3p���QVc����?��;�M6n�n�l�oll����rzp|�l:G�����"�p��2������a�.FX3����"	��~$5�lYnV�R�[T��DP=Oy6�9!�����J	��M�:��+5����(b�����|����PT��=lZ���P�E��=�N�Xl*�7�T��o{U1��%6�������E�9"�m��R@��j1����e���6�CN>>��K��!�T�������>������-�w�+~�����;��Q>U���V����^����:��A�ql'?����A���J���d�S�����D*�P�m��[cJt�T_�,������� ��8�=�2-q��c��h��c���3J�'c���������J��1*����I�a�1M��AW(��d^��D���@�GF`j�:�R�E_��������"�b�����Au�EI����-&�b"c���Bd&`������1��E�������� ���rW]�A�*FN��!�����
�|.�p�^<�!���������Es���Sa\��=�N�6Bc �������Oq��Ap;�BiO�����mR�����+P
��+�H,�40��atB��N[Hmq��a/�����c�k,JO��i,�a�q����`"$��i>TM����l�p0�Obu��j�=���i��L�g�]
i��?TlJ��:������ex:��2�h8T�4��6�|�\����FyQRN�?�S������'B�������4������X%��M��*f�z�-������&��j�u�{���><\ct?SS`\��I�p8�����&�U(K�����ax��{�33��]uP������j%xlW&]�f�&`���)�2���p,��>7jB�f����Kt��e0�^+A�����,�*�~�E�4��qSz�Thp��n��{�y����e�#Hu]>d�G
����R�Gi�in��@P�'r����a���s3�&?��c%h����/4�b��P�\���d�}��(�U��$LU�$����1u�.X���a���hY������T)��xd.���C�D�����!�����1�%��_��
���M�q,m������+��Y�$��K��c���5�iv%!�RWxs�?`�+u�Q�i�lT������� ��C��{���	}%qr�{�5,<[1i�nU�_UUU��Y���pptp��=�}����j��A��X��qS4\�Zg{4[c7OO�����YZ���Z���'���Q����+`L���X���$�9��9���������X�D"���p�X��B(`i7��VVK�������m����G{���m7O7��XE��L�Ml����_�iX����p�)��B��44��1�^��C�T8%�x��sI��WD:��4O��z����l���a��;g�o�����C�����������������}��}p���~��~��h�xc]��3C��4Kx��`���^��R�e�@��8���u_9�:��c����ddV�VH�%�B���Oa\�0�*d46IA�AA�i���G|O��!��bC�EQ��^I-I*jZpo��K��#��q�:��%*k,h���������Q1�z�=�g���PeL�� l��`�8�����Ks�l�`�H.��9�������/�6+�J�f�PIR�!��7���t!(2M�4!-����+'C�p�pM� �5g�X��B��; ���x���P����?s�t�)���)��]6�l�6&�JdG�($^��3�EY�(���r��l��=�t#9�3���5��\^�`cH�;���hm��9G��5yKS7������V�.�c��D��P*����= ���l�oU���	��C�Q>.�y�MO�Q�����@A����>b�g����8������r���5y������qT�*���p'�j�����0�����^E@1��V�Z�+OKC(��s�eQ�5��#
�!�����L{��[�4���9C���R�46a2T�������]����,�
g���b(7	enK�Fb��C���W����`*<T���X\i�l���S�^�W���|��(y���#|Xs��K�#�����S�_#������?Q��Ep(����@q�?��{���L���J���Sq/[\^��D�Ul"���.w���g�QA�4��7*�Mi����iV��j�R�4�"v�o�d �'��*o�s
&��:,��c!��M�=�o2	9G��ug���3P�4V������$��s��.?k���5�mJ�_��[����k��n��D���w�\�0~����_gm��u��=��}��W-i�
��m�����q��+1�`�!�h>71�0BI~�5�q��\��Q7
s	}�:z��P�hy��@�]X��$L&	gy�z�Nk������I$�O�4^�`!��%o�@Q�_�V&�k6��q~�T*r\(��M�`/*�R�Y�%}B�j���u~Uo�y|X��2#z��/M!�U������@7�E( ��AQ?��h��h;`q����>�zH�V�	j@y*��$�g�A#@��k��St���n���i^�I�sL�O�PZg��JFW�5����@�8��r_]�S�}�oFI:�f�\I��m0�S����L�RxdM�G��r13?l�S
���1��)BS��GE�.��-V8�cH0���I����=@|Q��bR�f.H}=�i\]��w��#������T�H�Y�������4Vv��^}���\h��������W��"���X'\TC!��Llf��j����c)�+^0�������#]�;��(��a����h�3?�M�2��m����t!��A2��Zg�1~��������Ff�z�g�XeT�4R��*�U�,���������8(8�	�����;,3�	��"��|��bQ0{�	&�+����(Vqf���l�[�����&}�NK��!�!�3�T�{��i��
i���yN��`
xN(^H�!��qU0|�fB���������AF:f��6�q)X?�Rw2�b�����~�wpB6�U��v/�� 
��O�|�?e�|��i���!�z�_�
`��p<[ 0vAn���$tq���%����L�Muq�v�I;�1��Cg�Y*������J�!���
���|����`�����H*�R���Ip�0a=��#�^����q&}�O��w�d�oQ����#cr|�0��~)Z�~�U�B�N�rG��|�x�yf��FC������	�(������
�������O��R�;$K�N �_���x�����_��:}�u�b��������[���w��e�:��B�@��g��0C�y�$�N��'������+�[�2~�.����b�OGq��?�������8��R��s$!i����[�����"��<�aWj��7�{�K��]��-�����4B�[�B��)�gW�d�(oD�
��-]1���f�?����G�1�P��^�#/e��^0\30�����&���pTt�5�2��z9(�/���c`���+P�[�q�D�%L�<B���3yp�����-�\�Uk5V#��K'�MG���|�����������2_I~�	�����/������
�'$h��sV;T��u}�q��������5G��0~���{�.N����x�Hl]��_B��1��7m�����`��7����uA��9"�Z_��
����to�Y�K!%��h^�>�����W�u��9ZF���J1b�m[(�[YZ�H��RJ���['�k�<z9�����?*G]
�����mu�����(~���z�}~��jm=�<�^>K676�=y����>��kkk�������?y�|����'������)����I�������~_���M�w�������_����F�-�����?}�c|��yssF
%'\�C��t�a>�����s��.h->�}[@�Hy��o�����~�bf
*J}u�������*��\��~�L���O�?��}��H������m?�(��������n���
�`w�����{�wp�n��C��������O�m���=y��v9\��Q1lP~~�^O�`%0�����Z�1�Aoe&�GDS7v���"����-��hy}�F�<�	��I����FC$�Z��
k�$��tk���"Y{�����Y������LFzu����vGEY���Z���^q/�^���G��I�>�<E��)�pi�So��������UX��������n:�A\o��c���������6G��oN������=c�N����5����������R_<Y��
�TMx�Au�hA
:���I�����s%����k�;�K�kR�Y�
2(1G�n#������Q�0�
�����>(=F��+3���j�{&��R��{�@vH�}������>�S���Q���.��Ce�]w���n��=����y�)Ie�+LX�4:���)���i��E7�9=��f�O�H�������
o�=�?��J�%;�����,�l�1�;q��}guU�!����/Iz�����9h/;!]�g-~y��sHz��^���*��U?��lU�T�+fY�5�MJc-��[*�D����`�%�kmS�U�4�]~1(�;:��-ip���W���j��Z<����_�����Tn!U$s����R�9�o���If�JCj/��\+
T
tqS*O0���6�:�����G6�P�X_�x��xm��X�v_	����������E�^��6�Y0U�w#���^p�x.3
�����e�=��?��J���s�Z�*4g��y��5�*��MCI�E"7��Z��.�	��T��"�yk��S2@����8��;@�}�Or����~���R����s��Qx@'����;U�����3x%����5�c����I[
�zV�(FLh��z�(N�m3�S?n��	��"�W�>�NY���*z�v�D
��?#"� c�n�(�G�f�k2m�����)�"-��d����S�.�e��^�1��B������n����\&�}��R��9�c��E8���)X���(�D*u�����>��1�����`b
!����mg ����|�6SYYd:�R%��>�j���S��0<7�/��W���U��= ��RK�K3Q�ML(�>�|�b�������\G/bC�&��1��M��K��xu]��W�66���8��^��,����}h�
D��U���I�Kw���9��T,9i�\�I�6���e������g�������6�
�q���7*x,�I|�^a�S:`/�)���
�G������qSWi~Z�r>�nu]��zG���+�z���
�����b1�7���be�W�.��=T��������p�^<�dS�)�5�ax�61�kb.0|�l���&R���R�Tk_6����*��w6�2��m�U�����-�M�[����B�y�~;*�0!'f��y���Q���Xe\m����61��}w��_��2��iF����f�&�����|v��s���xT�<�K��=�����������3��&����0V�L�������gY�������|k~��3��-�:_�������E�7*�1���]�������������S���t<�Z�G.�qU��=���u	�_O�v������'���Q����������i��B
C�)
_��Dr���E�:*1����+�y����8�������{Y�]�����tT���o������77���������,�����B��]+���S
������?�����h7A@�Q�����O�5��4���s>�y����Lm�T�I���tCk�o���y�#`N@_����������qa)����2�O.�������K�|{��a�p��=3F�$�{�����3�J/Dp��,1�,	�f6��Kcw�T� V�r�y�Z`l�p����A;8l��d�8����Q�y��H���E������V7������y����3����qs���KM�jbH���w��$l���g���NC�L�g4�������TZ������i�>��t2��b�'�<�zG
:�ND����Ctw/.Q�f�50������y���K=��}���/�|O����Db���,����8��s	0���f�/��"��N��������A���l��_�'��=Mc��t`7�`����_!C�%��t�����O����}q�A�K�I�P�RU0f�H�!L8���^��}.}��m(��T�'���������vK�vF����YbM�����d+7�u����V��������so��g�F���+���Jh����l2\,N���� `l�\��J�7G��p�E\th�����D�O7��?
�������q�8��!^����DHw�B��*��:������F������nM+%�[��O;���[/{�F=���S%����[/�	���������g�t�q\�T=������;
!&��v�jL�:��t]��AC���n���/p5E���a,�&�9�nM�.U�))*�&��#|ABk���t�����$\6��!;$#~��q>7]I(�7�:Q�44���1y���j�':6/F���yoY^�{� ��^:���<�?�A�E��W�-�(�~&�r�$��VQ��_��t�	4�vx
�����ADS�8�v3wp�.���E��B�(�5�M0�C�G�)&F�[>���Q��N����G���@y������6_<�ZlO�7���jA���@e��*����7�����3hAE��	�{�x��7���$=�}%���2�^b3�G%sy����d�q"�����u�4��	��I����y�]'�^������O�>��Q�b*����-1H-�KLT��V��&|��������6&Ku'����p�Y�`ZU�+�g��y�����z��V���4�����E'��p���p���$�N�y��D���F����n�hK:g3����k*�����ai�U����d��OF���z�S3,Js�Q'��"G��n�F4.��~�Y��i�Z��0�:oR�����[,�q|Ho4��t������n"�Q������_t�>���k���,I4D�pf��B���be��>����p�?��ch%Z�T�1)n��a�E���)Q���t�4>'�l���D�PrK���
���t�1(Y!P7&�
�7LP�J����5��\q���RoZH-�F=��b._�k���4y���<V5�Ew���U8w�H	����	b�b['|���^�����XYB��
$��Z�|Nk�d���f/�����:����$�����u�{�nw���Ko��9�+c�V�s�S�9��6�n0?}�b~2�?���G����c�d2�;������ye�m�����s��!����������X����0���N&.|���b�?�rrs��D�����f����;��L��:(y]�p�"�k��EU���<�B�Ur1t�P�3�:�V={�D�U�  8i�p��������������(��,��8��Q�7J�C��1%��K{A��x1*�F�d�azR+*�@��uA�����y�]6�8 .	 R�(��,���u���0�L��+����IX���=>���Z3e��$p��}�EX���s��yA�/i&k���"��Z��KK�lW�BQN3g'Euu�@�!S���}��R��s^`�
h���_�cr%Z����0��2���2#�w ]J8��'\�/&�m��D�1���)����'u�0(B�{��;�31D�����J������Y���c9���!|�!L>��l�u'�88x0�U[��4���Rj�A2.��R���d�5k2�V�.1fa���S�
���)Ww������`��a$A}>����1Y���q"��ct6�������Cyd��y��27?b%�m����M�_[��\:�~E�WY�WI�U�XA����a����_r6Cr����3\�t�H����GA�[5 *FE'�'�C��?���n���sI9Ra-�~������1D���^<ei���V���gYb+�7�XP�i��g{r���|}=A�F�G�x)%r y�'�=��8�����p�H^�c��c��T�OF�u��}��k5�fzMw
�U6�\I�!A��y��
���5�Ic�Y���b�y��B���'��1���S�g!�Z�����213�c
�_��N�<RR��`5	�\U�����e���-�.X3�Jl�c-�a
~ u�`V$h\�2��<l��o��t�����I���2q�gv@	+��e�:S���OJ)�WS��C'�y����p�j(^o�n��9���`.�KL�E2�8��d���|���6���sy�B�^a�'��;�������v>h����S�$�Q2�~����C��8����\U	�qi����N& w�`�(��3��C���I
#����
FB�>�	��^f��eX��-��K��iq8��q��=#T%�{~^��<3&fw���|@��������~����~���kzy�]���r<��i�23���A����.J��I_h*�K�M��|�q�������w�Sg�A�R��1#oC^6�����<1%�$m�a�J�~�j�|��k�Q]<�����E~J�c�zy�O����M�Y�5^S�������U�b%*%�W�f]��NZ�^�-P�9��ro��c���J��@��'Q�����5���w&%���`��������L�98O���St'�d��Oe��>�ke0�h
$E����NV�=JH6@�6��&���$�ca?EU�N1���������D�	��x2�+��]�.�7����`G�0�2�yP�i�}]�Y��3�����	���lh,Z<W>P3����^�����a:���g%52������=^q���J�<��J����G�[�+���/��*Pn|��e���l�
=�Q�����v~�K��Ii�1��FPa���k�Y1������a�:,��2�J��D��k�0�*�A,��0g�@?1=4�4X���b�qg/���@��_�cT�e,`�L���]�@�)���<��:���h��dWI��I%Y6�����t��l={��|L��H���������Kx�����K�<��&c��p����p�p��Fa�(4��o��:�'kV��|�X3z�u�3�����6
s�*w�|h<��KIq��_���y6e5X��WOa���[���
>���^.�"���]����;;��\1��=5B����������Y��m=�nm�j{�j�Ql�����&���Ev�����[��j�#f�-F=����F��4��uN*l9r�2,�-���k���;��
�lJC+�t�y��PL)v���/�Im���1Vq�d��Y��cg8��Z����>��J�Vx4�O2���] ����}o�k�0R���M���
��4��72���UAq,��H��~�5����l����^�yY���1���D�v
�`k-���A��_0�����V+6����<�GsR��$#�!G���)���~�������D*� �B���'[����V���A=��Q��V��������e�_`E��2	n!Z�.�/X��#�Q����pH�yR^��h�����q%����M=�C�I�%���3�/P�l�&��������8%�[��d���PPD�)/�_��^��"����?���U�e�,	�S}�	���������u�"]V�.�������4 uK�i�1��/�tf���-l�Y\���:y-�S)�6"�z���y�.���O6��#r���t�4$T����R���g��+�#������KP��Z�n��������xu���-y�������I!x�yHk[��4��E�5�Dq�O$yD��rt��h��Dj"��%����^�%t\J�!���o���P���6|?�;�|���=)�{��C�\ON�:�xq"# �2NG(����D�FV�Mh&����k����O�����/0���s�yu�iIns�QZnm�Q��������W���������5���jG�:���	����U`��6#����R�z��?=�Xs��#X,H�iX-���i�������B;������|��I��M�dP���� 
���AI}�7H�F���FOqI�_d�#�Q~�|g�M�"�7�hIQT6[����v������_�/�-����@��X_���v.�~����Lv�o��NF�Q�b!6S|���/N���H���=�d�N�x�go>o���z�s�
v'O�����V����}�Z8�'#��X����`�:TM���*b�k/�<Q��9�t��&��E9���a��CoG�r$PN���q,Mx�c,����z����^��x$�wm��lZ������D_2wD��eS
�H&���t��/�7�l��w�KMwz�Q�7r�E������T��B�y�S�p�g�iL��<���'��*��})v�������W�T�
�{�Xza/7iZ��${
Gu�N���L���%R�L�E��r �T��v��0H�S�*���(|}�������q��7�����r�&C���w1��T��o��5:>qI�W�����ed�(���j����H~`OW)��I�b@�p��r��j� ��P�(�u@_($	�������_���/d�_I�isN�^/Gb!���x��V�F�`�Vp���4�|G���q�O7����JG>E�i�������z��O�D�B�j�����A� �#g+�����R}34�U�"�I���a&a��ft�E�jC\_:qj��5l��������N���x/�4�����J�n��������;"]�(7a�����q��v����������/�#�*QQ��w��n��3\���1�dQL#�x��Y���s��$�={�����*��[�ad~A�?�Q4Hx�����Xp.�&���i^�^9]��<���s�FN)t����<B<GGY��s�4h���T4K�D�\j	-�T�h5s�rtg���t�G��7hMk��'������O������_��T�����_�xo @���]�Yq�jg}D��d���f�r�%^L�"���=�q�:���dE���`)<(I%��#���d+3,/�g�
q���DM���l#��Z/_n>����eu	:������B��hqq�F/1Bl��w���
8�G��<+?�����v��S���tt;w7����5=w'k��4E�&�V*�eok�F�,\/�J��3����:�R0��� �w�%����B*�vI�\�6��Gar������5m1
h��oz���}��.�7�:��A�P��H���a6����T	���NR���Yb�C��`���H�
����|lc�0�t���h�u��DM������$Pz�f���,�u0�k�g�o����X��`�S���D2���r�����|�K$�����I��M�����>�x�>&~F��e��%�?�O��K��w����/k�"�l��%���~�Q���m�0U*���[&y������p�"���O����k�o�����0�Q�xC�����bc���J�;�����O��]����'O���*�b�M����"��3%p
�\Q��s5�;���Q?Z������q>(�?�r�)�yo�G������|K�h�{Q�=H������Q����m���c��gEZN��g���+��n��Y_���@- ~T��	�^o%y�:it)��{����*��H�y�����b}���Ps�,p���PriCU���m��W��{��������t�?���7�9P���fR=c�5��������Z��.a���2J�m���Pw'���=ad�^��]��2��l�V�M��T��}�������qF
5/{O��A��C
nj����F�����L�R�AB�`��R�%a��|!uZ��l�����������������
b�FR���~? ��P�N����e�=G
��,r�$GV���X��=L�B��bdj��vN3���
vq!��|evbZ�-}����d�N��'T��_�ARt�O��g1�bj��Z�������?���G��}�"�'�&��Zj=�3���r���pH�rN������La6������ �������������+�p�R���J��}��h��w�Av�w1�3-%)��"`i���� 
�3	_2$����q�b_
��bB��PK���4�?8�~��?�'1���	����"y\�B�x�J��g��4D�E����G�5f�E8J�R��DY������c���l"	��y��+|*��>u�^�����^s0��DyS#�[	7*���@G�W�<XdcRr���|6H*(�MzkX�'�w��~����3�Xk�yer(��T���g%�@lX�h|��(�q�V�99e!�u��`I�f��`��@I�����`l���`e���q8N�Ao�[������C��D���{S�EL���#����Z-�n�x!�[�8�l,um�tu��0����#3sJ�����^��:M��|�)��d8@���V�e"�(�����7�����3����2����,�= a������`;|��L9Kdf��}�T(��cb�s�Mm^�r��;u�*�G���e�HZ��1=z��_F��I��A�EN#V���x)��^��}����e�������Xk���Y���Q������O�_��.%�y�S��Y^�z7�*
�9�m#[y���-�������w�v�]u�@Z&7����mE*�z[�o�<�����z��Y)��X�q�	�_�{���|l4��>��PS<&��)o������Q���~S�L&��:�Vr�-�
D������J�~�.k
F��F��g3�(�f����%d�����=`v�%��[�x���K��E��v>��~�9<��U�c��n��T[�������t{�><��3���G���a%��e��%��a�r�xI���xK��i�y���p�=�-�S�(z���{F��o�OJ�}������>Z)2����.�c�N�>���+��?
1�s�^�f��M��"n�7w7���AwU��z92"��y<��]nt{���/{��0C�z���0��78��u��)��d�k��m
^T�~}T�����.�+#2����.�8�w4���Sg��>����ppv��7���WV�z��v�������{		J��l�������5"I�V�If���.��%��\������:#��bb�6pn}�;��'���+��������rAj�o��wk3��NcdbAP�3�]���C�2�urr�,����"�L#d
�QQ�2����!���w�X`�K
j�K��5����8=
9�:4Y?�Tj���h<�b*�� j����X^}�r)�9��'PX�+�;�L���cL|1�m%n��H"��V�&|U��+`��5���m��l�FhSC�
5tHx��M��NsqB���xf�G�O&?���@���BP*��F�j���7K:
�$�7��\����@|�2��>=G��@��=tg�^��2l-dSy�z@�	�i>�O�	��q�����f�*��	;2?�Gx���we�{^B�;7���I�P�a����_�+^�Y� n���E�q��,
���fz��m{RB������gU� �l�YGhR~Z^����3n�ZD�j��g�S��a�"{{��V����,d�P��\����P��;�����O�� ���V9��]v�zL�$�RL�dk���
���Hk���x6������L���<��J�_�����Jp�bH����������#�LvH.�{����MI�p�4�,cE�:�[_�a�[�.��y�Vw��S��d���v��!%��i �m���
���Y��VQg,dL�	A��)�q�,�N�V�.���|�����q
]�H'�F�V��
�"�Qv9
?7~D�0Iu-;*v[��z�������a�?j���n�\��#����
:wSj�����D���G#���?6����Vr~��tc?7^<y����x���N M�W��SP���1�_���t`���+
"���	Q8(�w���k>b7�a�|h����a���M����#s��%N����pfuu%�����}�^�o��RcZY����/��Vk���g��F*N��.��f�Oh��0����3@�$�����nNN_:�'����������;�x��������
�^�W���E�d Tm�ll ��4�&��L7[��'����OG^f;����rrp����},'����;G��f�w���q��>4����'����c��
�D|����5^*(�w�oSz� �nw)�N���=�<	�Q�����	�$��d?6�J�K����(�6�"��D�6�`���4�B�1���kl��@�y�����:�l��h�����2�8����4�
���A���m��?@��&+�{�y:bS� ��1������	(�������J��������U�����UvU�n5�K��^Z����n��������_.��n>�{�vP�����#�?��wa<����FS�f%Ys�:#��eq�r�v`6��}E����O2� ��y�)��}B��?D�w�R�h��I`]��|F]
��Uy����/!����Lp�^�z�M�i ����������V?���O������6��m	Q�Z,�,��y?���Ai2t������%{_�KzS��5�h���t.�l�q/�����Nj/ ��O�X�.�f���z�^��zVlQ
�`
lhn@5�:)gu�X�b6����rv����v���N�K��>��EI����7�y!��~�|��)6�
���!���<������W"q�>�Yp�0V�-����7�>����?��w	l[R�A�h_����b�}0`gB�1H�'��������Y)���8M�����Qt����
��o�K������t�7���/Q��{y��Q���4n�P:��E����$�WF���"��\�0��lk���^B������Cc����������Z"p�u�j���W����O�����`����P��)�k��DZ��G���b@-�b����zlk��_+������A���H���0OVT8Py�,�R����tO��bS9#�������?R6�%f6X���B�a���D�eA�Y+�)?}{|�a�,��Y�����OGg���/����l��BR�!�7��
,,���9A^�sn��[��lWu7��Yn���?���Z�����O�������f�M(�������&]JK
6|���5�0���J����uke���/��$������'�c��X ����.�f������|�(�m�H)�"�
&�a&�g��H�x-q���[��S]��*[M�f]7������!t��^�8>�[I~�`J0;{~9��������v���U�w��������3������[�TU��JV�6�n?��J��M*f��s�����&��J?�2i$d�����PL�!i�����G��'x���4�������}~�B����@^��/6���Q1�������}�o����H�o�����~����=��TMF���E���������y�RUy]�T��f8�qR�7[[O^&��'��������Ys�Ys���;~[4���g�����Iz\P�>����$�:��D�����<���/��?w���c+Y�a���������(�8%���5Wh�tJ����r�ve���U��w<8[f�7�f{��u^_�Z�B���[�pM�3����$u�[����BY�~��B!1�Y=����R��o'"�}��9�U�`<cX���b����&����������l���pW�k@��zE�,�������c�r��z���l�Xkq������v�:� ��������[�`�s-"?s��|]K����k��7�����QK���=�_�eJ�M`��������Z�Q~q��4EV��3�V�}[���������r�rs�"{��8vw?�[{�q�^�����������/���t�/���������}�{0�||�������@������#."W����E��}�����V�|��b���)�����_i�)����f+h��Pd;�H�t���o�r�5���k�����C[�
9:����
S�1��,zmx��^d\D�c�L�vy],��J��>���"�Q���{�����&<�Cqm��[ �s�����G��
���,�B*�'������k���?}�{������)8B/� �l47�`@�C3�������?K�W�4|~,���(;��C�o��A���<bdfc��X��`��������$[�[���'M�KFII�0��R0��Q1jo�unh���h���=��o������P��>��,���4�����v�~�B,j��G�����F��n1c������R��M�/;�n>b7c�B���\�����'�������������z����)������p�{D�?������j����O�D��! �E
���	�W���;|/E@�D�����X�����G��4B���+I��B�i/HV�a���������^��4�+d�q�,��k+�\�O����\{�>xN�%{z0����2yc,��m]v�pP��j��uv����G�-�>��n�N -��k�	��J^��d�
0�Qb���*��i�Qn��	�J`V�j�S+1q�c����Z�k;h"x���	:=�r�����0�b�bO��<���#��zt���
��}�1PP�C�y$��G0�,%���$�Q_5A$R��In{�c�����'75���~3����(�orZ���>-^�DN���rd���>G����/i�����x�L��6��mo\4��Pz"�o��]p�s�SX��*X�~�{Gc������=�`YB��^8}������/���N��AE 4(F����"eL���x@jNG��G�#�e��!T�����5�gq�wG1��
~"�	��-�7�8G"�i���-b��y;��4���i��~�����2C}�m1B�[�\��c����	��u �~�t���^�N;��_�N��y>�B���k�;��L���/�U����p>�����f��.R�����������pA��p�%���������l��O�r��d�F##|?�D����Fc������B�%�����
5������Y7�Bf��1p=����x,c/O���5>�k�*��wN��:��tR� ����U������>>� �@�b4�7-��A�'��[O����=�>��aB��\H��P����������Kp��Og?��?~zwp�����[�f+��{T7���lD��G����J�?�7G;'i�����g���>���(����v��T!������|�&C�K��?F�=�It(J�c�������3��Ha?���T�^u@�k{�E`�%��4lx�)�a������/'\o��G+�iDDg�������[j�+��",�:SnO�������eq
u7��nb�MR5�/��}.�c���0��F�����%/
���,�_`	:s�� f�fi�?�a~�z4��u�)s���ue�s�����bo�an�m��@��Z�������JjQ
�Kv	5Z��M�
2�'�7]��+��}8�H�)��B�����fu�y��
��Wbi�BTt��s��(Y��s��s���V��������^��t���5������B�#T0��3�N���������*��m������r2�a|l�E�:��pdn�&������r�]�k���Z����`��������H%u99�&�����&v���s���������!�1M�:�y��o�Mxc���q�S��)w�r.�~c3K;�����=�`����H������|��
�Ko�k1'W���+~�n�y2��|��d��do�����o�O\���C����e�	�S����y�Q�����Ls�J����	f������Bm%h�����G���P^��g^�z:��������� N���4v����r���:���"���'%-I6?����>�� ��dA�)[��RX��K�kB��������XL����o�����l$��)�"��0-�8J�<��Z_�����}m(���������w����������3�f��{���g�0)��Ik�X����5^�(��A��T�������%���kb��
'Va"�R�o+�\�Y�)E!5I�&�
�J�d�����&+�f&(rO�
Pz��**��e�)�����|�
��w���m�O�8�fN���a�mk�RC�^?K����Z-8�R7Ug$���o����v�����kK�lJ���&S�&a�#{�����}���Z���07���%mU�#^�JV��cj���Rf�[�l
�"�������\OG�6�����o�O>Z�i�:��~�-�Y�t��Sd�S�����0wO������p��T�J��mrk�Gh��*��P���W�������2o�{���j���
�����+�����!v7���D2BC\��w�M�;A|�%���-r ~����5&Ej<�eq��$
a�`5{�C������gY�u�����-5+���^��=�b�����'����a;������bcz���1(v|����z9W?�,���k��F�������_���j��CD>�7����{+�����N�����jv/���h4��<_t@	�	]X�(z�d�P�2�	W�`�9��W�+�!�����^1(�
M�J�(������#���EDG<F*	;(�Kzs��x�@,���"\#\����	���i�U�D����2w%�
d�>���S��)?5�2��r2�H��G����-�*|a�aj�-�Q��tI�G�b�����][����w��#���u����d3�oE�YzA�=�6�����M:���'�7F����m�������	
N8��T�*���V�s�:��#�2V�	���e�8������B2�4!���es���g�.�����������6#��h�$���8�������Ad�+��a���{�������z#�I����>�x������cv���BpB��	b(0�d�`�Z	y_g�4����B$;b�t��\�_���R?�6t�3*i0����/��)sF"EY�B>"��7���"��r|c�j��K���v���|�'��4��;f9�0_�b p��\���3i�9����0���ty^�	/W95Y2���Jl�.����V��
�{	T����WcL`��%��"d4��[|>�4�	3v�c�f����\��d�-:��y����,���h��d��
	���X%v���_���!t���0�c�h��,����qW�yF��e9�.|���l��
�w�n� H��.�A�H��*x�,�Jt���bbz��5R0��szi8^;�)y��?de���5���c�1�ZFYF�E����6�j���]�*��Hw��f����
�i������8��J��'��BtiD�)"z����Hm=�F/"���
)���S��X�m�%���/5����[�S�Rx=����:�U��&��N%L}�)|S]TS�S���;L���:#���RT)�c�s|U\Y�Q}oW��|Uq�����J�a�^�/wn�0���U�.�h��P<� ;��P$��ht*�����RF��Pc�2d��
��y��������W�1�@<�V�3:@�GlL���x��"�#�A��$���OU��mr��9Kn����C���(t��d��o��w�����V��"�U��*M__�/q��a/!���`\L`���e8g$$�
����9*����(��lNJ�O;L�p�Kfr]�����)��2��SO����:��,T��V��@
�~&�3:9��g�u�_M��Z�����=#��
�"~AT����pl���8"<���u�����+�fU4��m��H���������%��U���	T^(	�)�	�t]K�<�,I|���r�����fuq"�AE�����l�&����P��������gd^���A4s����������C�b�h���Qc���~����X'���`y�C������]FE�pL��B#�?��j��@���c�M�������L��7E�#u�f��Q���X��#�i&qL35��!�y�2��f��~|��v�wy�#+��[��������N��x�lP��;����a4��N�1���N�0
;9�Z���.�����q�J�W!b�)����Yk�������n�+����s�LB����opGF0�>��Yf��w
�0~OW�E�L������?����y�������@@�RcI��9z������i�p�S{[�j_���
Ex123����A2����cq��Q�M?t�=���.���S�������x��8�j=}��e�����D��'��~��2Y��nmE�9y�Q�+�zJ@�	��I�x%ww�*�N����Q�������}?CF������L����Z�@�Xpq[\��q�&�v�`I����)�.�"�q"1 @@��;#:N�����
��Q�1E�5�S�{�'�9ND����N�!{^CoW��DA�?�O�}Y#p	T��9�����rS�Y ��9!���hn=�M.D l{H%���,;��\J�m����w����������G�����_)�D�u�y���%�jI���B��� ����v��s.��T�;�'�����������hS�?���%fI~1;eE]���������,����V��NuL	)��GB�s~�
M�����n��
��N�t%I���l�F(ac��c�����-���*��G_�����n���z�a�!��#~����0������h���Gbs��o>�la,x�C:������z�0�U^v���B�&���BG����V�b�9����v���SR�5��3�P�an���}��"�����C������\�5,v��H���'p����
��u

}��[��������d�D���%�#^�'Y�Wc��5����|�V�3]���������=](��}�Z����3����9gv�����������O
��Gf���||���p����������em������������,s����� ����j��D��	t1#:=���o��_2����S�Hx[1�����P��Lhq���������B��=_lx/��c��8����xo_K�-?�04L�������R�;Q������n*`��!���H*����3�rA��h2�h'�H��]�-��O��m�x��8X��� �A��9���X�6�X�j��z����&�WF�����cE *0�����@��K\q~N�N��
��el���G��g�G�Km���j{5�>���zw�=D��V�#���{��&�U<7�I�������+�m��6�{z��)��Q�"}�%��+u��dg���E`�;���
������^��7V����w���"x<m�=U�9���������A������{��wQ\�u��0g�se0�8_D��b�I
���w�Y:�2kU�_i�S������}�/!�V��{�e���K>�>����A���f�v$�u�Lm1�r�����S�j���%K���ZdL�����`���%6�i��~�D�$���z���c�X
����Y
\��V,�,��c%����������W#�8����XG���[)�����E����u: �w^l��NA���P��mHi�|�������'���:_l���%m�/Qz��E���Rx��&�F�1vd��C*P���O)N"�5n��(�6��v��"��#Z����������9^.����BV���0�/����5��5P���
!b���������K������.��e��tk�E��so�x���E�6������E��}�{�x�XZ�xr��>8m�|:;�yg���XixS�^8Q������va�G_��������0>�E���������[a�w�s�s����Z�O�}����+�6�����X����������OG{Xy�e�	��N�llN��i��p^$s�Q�a�>8zG��oB���$H��u!#�y?�@�2����c������l�M�0�����9��X��{�oI��MtaV�.��x#�H+�P��A?�����}��6�2i��NJ�5��NA�w�;����'LZhU������q����I���g�3�c�Y�Vx��n�U����	�����������:6BWp��>�5���M{t��[���v��f\o�����)I"���g:��-|�N������Mg>5}���C�`�����A�>o���|��@��=�X�phS�v/��
�'~��-�=y�[�s�7Q?"�j�Hr������r���|��&���N������Go����S-0Q:�c��?��y�h�w���[���Q�Fc]�'&���'�V1e�����</_��^��;&4W�Dn�sr���9�M����S��}�i�bs���=�t^<���M���4���T��y���>�����`z����� �J�����5Z(1�:i�O�:��	�0��7��M�����0f�Z����g�E0u;��K�7����������������)�;������N^�'������
S�@?�HW[1��o(�s�G�������{����W�G�D�;���{ev!��@��Z���
���1�GW���;�lc��s���y�q�b� >_��������_�~��[L8P��)�B��K��gv�G�!��`<�{G�]��u��h�Y��5��k�k��_���t��-I{�T����vh�Pr~������#x���������Ta9U��QvT|��H�G�M��H&�������39������\t<������oZ���������V��|
��u���n�n�����n��������3?��s�\�Q�}dgp��g��)��g=#�r�w|y�����R�A8��jS���T&���Z��p���=/2#�#%�
�dgt����"K���g�s:���ww�K��}{I���5t��6����_��.�j,��F��Uba��[��}kPsM|n�`T�w5�j���)���[������x��z^���l�n�7XQ.��R�/q~��Tq�;n�y<���K<L�W!��J�>$�5�jf<�<��������(��6�q��r�{�e��OJ.L����`Q*��:��-3�t�b6j�M��N��8~;*��+�,sT3)V��T,���`��^��Jtu�Rf��B�-� �{���	� 
MU�DP���i���A�%z3W7hd~�MY��f�p��^�7UDw�r���*���O!�$<_�o6�|5�2_%��@X<��O��"
 �Fae7C�\x4� 8.}g�Vr�nmmd�/:p��?>�<~^�xg�c��Y-I;{��Es�1���$�/����V~KN��w��a�	
��;�{��?�G�X:��%���(i4���z��0#7���rWV����c�D���P�Gz����Z�����5�����V�I������H�u����!�s��xLS���E����@[8���������I��P{c%�7�;�D�������q,�����|�o��:su���X�YzR�i���������d���z������xp�G��*[�:1��������63��^>�x�4��M��9m���Q{�d_�g�T7���y})l�>����AD���x8.����������bX�����~
W�����%:�m&��d���_��G)����^���mOa����BWS����u|�� 6,'v��J��SR�7a�Y�>����2��qT�d6��4���?g�

�L5_��\����.������H�wv����w��O�`�����)��$������J�'�*�A�dxt�F������Q�G|�����QE�Dk�@D3l`h��z//�D;<S��L�'�l	��P��gj�}c_�������JR��7��	�����tT�yF���-��^���C:�^r�����<6���O��dE��`�}��a���t>�f����������������������?�����_�g�����C��M>��l���	[99�G��eO����F�?~y��f�< �#��vz��5������r�%�83�������j��m��������r�WX��B�,&���v=�L�I,����lm{!�6�n��H"��4�CH��%�{�������|�G�1m�$(Xf�GA������'Y�l�h=m��[��,/�6��
�
0002-wal_decoding-logical-changeset-extraction-walsender-.patch.gzapplication/x-patch-gzipDownload
0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gzapplication/x-patch-gzipDownload
����R0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch�<�W�F�?����)vl��+0
B�]&M{��Z�jdI�B���wfvWZ�2���=�'K�������xx3�z��76��o�[���5����-ks����/7��ak�������g�����l��j���v�Z�������L�|e�f`�������Gf�wN���`�5]����;�������j�Z�~<������wpy�n~f��3����lw���� ��+���#��a]7
<+q���W�<-3�5��L��{�3�hj����a�����a�'3��q�t������w������V0>����/[o��Z������xv}%;�]\`h�|h���~�1�#{�z���-����q?:�6�7M��g�������,xK �^~���I�evF7gqd;�"k�����$k�[��$��b�cQ�
y��VjU����,�pq����F��<������R�R8q9����=3��`f�a�1�l���F���������rkm$QB}�s�2P��u^�bF{{���j������br��a��1�CsrK��^����.��v�,hy�M���~:>��^�	F�(���\�Q�?���o�
�������nL�n
���Y������M����Z�NU�,�����UC�k���g&F������
�ya4A_0M>2��j��"Yd/�HO\~M"�+�����4/�Ckk{���i���;��h��V�@��&��+�X��R�k=A���S��x��DQ��`h��g�0�����o�
��13���%";r��Lq`$��������5�	��t�<��g���fz������v���A
��$�f��D�5g���8x=�����q���=t��c�����	�1V	9g{�`��w�n��t��~�<A�	�2���D@H�0.G��r�� �*jw�~��X����s�"��=?�gfp3�qu��'�R��7���v�Pp4��=�w�p�����Qf0AtV�x� �g�c��V���'
������ 5�D���-L��b�P��I�/��A�g�N.�?=?��mI!yG<�\UF��%��C!	�D�;�/
LL��2#��1�
��4+(8�!���!����(��O3���T'����c
E�"x0&��v����4��D��R~c�H�����#��:A��8��A�3����T��8�V�>�l���B��91=L�.����-m�X���A1<��� ����=�
�RP�!����.v��l��l.0�PH��x�l�Dw���t�0D��i��e9�O�dv�C���Y_P��MIx����#{ls���MP�	Bu� Q��^�q��0)�(hSa�zeG
v�����@�=[$J0$��J��)��D����5D���t�f� (�Y��5s��������5�H��d�� L�t9�%�t�-f
����`��X�.���)@�� �`��0.<@��h�W�<e�d9*�1�#��vY��P��:l��&8��*n���g��� =�Q):	���I2dq�'�����L	v��)1�69\(Kyf���lC:!��[�����Y_6��@p�S{����P@~�X���{+������&-���<b���9��;����0�}/@�I#n/c��P@,0�}��_Uqi�����fHV��������2o�2+�F����#Y����`�� ������\�ON�B�E�w��`/D���@���� ��#��,F
��E�9'�8�$���e=/���W��>++aG�����W��������j:40a�R�*<(�mz2O��t�D��G|l��c�iGq`!��aJ�0�`��!=H!�&�VqN�Z�%�le����rZ����\������E�7|Ev;�0��G�5��XivR�$�e��aC}��W�����;�����y�=;Y�I��w>K�������VFR���`����`x�a��`���p-�X����H	mL�5X���Zh]
���!&Z��q#?��~�9�:�i��p`����+��l���wb�60�U����0Z���+<=d���WF���P� �?��%/��$���d���^`=�M�B��C��s#2��>��a)�mxX�l���@F
r�g���hu�y�%��4e�#������(�]aF��E������O�s8����OP1Q��I���K6�H�`�U��{e�����Xr���#��42~�,#����4Yl4`�\��I=I��2��6���
�?���Sn�j�!���8x�:�8k9�_"�]�z��gw�����s2F���Q`����Rm�v)9�����!����'	#���T�>dv�%a�4r
}P��TA�z�(�m�X�������5u�&-����C�^��z�CdP��<���"j�IU�zb���Fz���N�f��f22\�h
K����}}
��������d:�8������0�O�I�<��@�
����84��S,q7���N�~�����������P����)i4o�D��4�����(���<G�<���������n�����SJ��4i����=��j���7���$��G?-�TQ1��t=+S������k�,�$%�,i���f���{a����B:�fF��q�u�?�4�MZ�aB9�
�!l�B�]�!K��t%�dg@Ny#�14t��t����"����Ye/��M��C�4?cQ<������
����(�����I��"t.�x	�U��U�i�����G>IeX����dBd���r}�6�Q���3�V���_�:!�7@�^>��}�3����������[�+8r�_��yv�]3��!������5Q�3�`Bl�<���)vZ��#����Oo`�o������|��������bs�y{_�>��}O�]{k�m�(�_�QZ�}������k���\k��D�_2���8j�T��W����U�i��p7K�;{��w��k��o��q��>�66�Y��	DP��a��[_���
"av�����k�
G����=��E��/F/�&�bcks����E�6J$�H�Z F5�	��E`I���{szp�g;ft�Pl�,;���+�y���������]�P���?t���.�i�RJ�7���i��9$�~"���MH �U�/��a��!����	�����;�M�-.���"&������|�AW��p����~��Q�����o��������j'w�xb{5X���%�v|�kp.��ke����bO����j��������wq~rq�6'E���\9:�_u/�?W@OQ��s�V���p+���U����Hw�����i��!����������o�+�X=��,��U�h���{������s��~G7]l,���v�bOL`����!��3��wJ"�j�W������@(������4��2�n��E�h�e�������U�����ho@��_�D���T����<!G�`��Z�����g�c���y�����%��)=�q($��0������i�*�*k�|���^g�'�7G��OX'�q���=�Wb�t.��gb}���Z0�I�����?�;rb��U���7�+�g��n�GA*4p<w2�L�Ix��M��lE��2G#����/*��A��~<�9��'��<�=|����}�fx6����
1�,����.m��:��l��k��%�d�� k������>���cl�9>��O��{����c�)�J��-�4Q�Gx^`�R@��;{z��*�J���a����v������7YoD�/L3;���s���R����op_�h��q�a>����o0��^��m�������J�75�U;l�o��"�w
��f~Q��p���\�@�n������7�/p#�ME��t��sYpJ���d@]��}�]����0��D��%���f9�����-M<B�[0�h���<~cB���1pmys���������;Nx�Vw�O�����J�I��=A`����<b��W(��%���m�X�W��g�2��n��LK����~rW�u�{ �~�M��j��b;80��1X��y-��F�A�A��J}+�d��L_����:��#�5����v�\�E��<7)��3W�	�C3%x&[�
!)�O>^������ ~� �|V"�f��@J��\�R�J��X�"*����|r��{�����D{g�����[bQqf1�)���v���� O���F����b�>�����;��L�����c�`�#���Q��M���r�C��R�4�����
5F�����@>��2����GP�%�
�<v,65}�m���"���T�~�����w�C�0;���?���j��
[���n��,�Us
`��;�u������-�)2/�o�G�-	���'�3������L>�XZ/n��Q��?0�=�<��}-��pT`#�P�A�0n��G�q�g����2xp�?=O�7�������H�����V�i������r���wyAk}�o�dq�5i)��T�
h~��$]3(<@���b��:��;�_���uE�GW�5�%���+�'��G�HwDM<O�F[q���s�%�
�e���=~u�|�R��������]R�B�9dp&S�RP�����/`_�JoC&:Z<	�
�&Z��	Z\���`w�����!��xo0���=��� 7�kJ�U\D1e�
���6������g�E�%��2��[�����������B�����dJ/������`�c���T��`G�!���$��=�*�G�{�����/F�b���$[����/�#�c��d�YE��u:in��/�'�P�P��8�
b��<�����
��xPPX*QD���pl$�c'�,����h>����3a��<�Y%��kU
��}7�G	��d}�$����������`Y�L�A"��!E���TR��%3�*R-Q| J��!hq;���l,<T��I~�lC���<��z�~em��d��{��jh���M*M�w�P�<sQRE��Z��P���z��e�wD;TE���@Y"}�90h'�Sj&���^������[a��B��&����]J����r�[S4am�d�~uR+����j��X4Y�v�E+����O����_�ZO�Q�Nj�`��6 ��o���77�k��{8f�������B������
q	�����iNQ�"��7��e���L��QQ4�0��u?!��D�;�Q��Pj��}��{$=�AD D,'�"�u�����0\��&�V�����iX��3�������u���}n|qJ���{�v������%Y�S���W��J����rpq�;�uW|~b|Za�O�����Y��m����i%o������u����o-��v>�{�����Zr(f�(+X&��F#��U��X�S�S��,G#f�VXeE���]�����l��U��VK�'yl�|Y�/�d�}�"|�����S&wo�5���~���~��<gk��
��Zk�3�M[&�,r+w�[�a����U�]�e�q�c�����V�����9��L��-��SuJy��+E�g��S���>W5
�IL�*2/Gg��P�A�FZ���`DW��@0�+��r��4��!��G2x*�{'���U������?8<��9x}~��=�3�{��8����2�/:�z��H	j����s@w���+N[�a\~�=��-���:�t%��)�T~�
$��N��~�D<8|����$}A��
�Z�t5����y��f�����)J��^j��'�b��M�n(�{j�<3�
)*������Q�������_I�f�)8(HV���d��=�����F��-$�S��{��6�m?�_���AX�%������m���nn�R�Z��BRi$0������6�3Y����^��>}��$f�������JO4!���J��an�%���w��T�����)��n\XZ$����MQ��y�`��6��nGmq���T���&>V]tYVS�_�EaP_0�;��{�.��~k�RJ4�L�vk$�C��m��A�L�H{8@���a��: ��pW����]���&�9�`4&���o���d��vo���0'�	�1����e����N��kvU2|9;8*���������^�8w{+����Hu��kS�9�.��H��,��L���3@�H�o��Z�3x`������/_�)��h�.��7i4*dz��u���u�!�oZ��8�f������E]v`�;$
[����9�'���k�v��{���U�K_�4���A���$ej��i;t6�T���o���Vb��G���F����(�$��$/�>�2��2b<aG��)M�Nw8�����"�
��(u9f��\��&�IU]"��Tj�8\/�������x3~�X�	�;Ow���7`���Mr0��4�wD��p�*b��]$VL�r(���{������=�����6'����xj�|����z������������
�ZY������*��|��N������+������h������w,��3�L&W����q��_���3�e(���d|%*qg7�!@JS{�������W���SYQ�#��*�o�5�5�w=��6�k����.[�n�c�
p,��<vq�����1}L�Ut��B��Z�4���c������:�]�a���Z���L_�F��1I�]�4��=��uhb�*���o��'�Zm\���3�3^�+��N
�f��v}O���"����H
�0�1������Gf��Z������"�p��d��w�����~���Z�G�x9y��@�.J���V]�Y���2��')��fD$����s<���L?���>�xn�#�=���=+��@	�H�H��Q=m4��d2LB�a�UGH)�9������8����^�9����u��GS3��$��L�T����1h�;,5�����8z���:G��:l�:3���"^������p*���V+�qQP�,R��q���6��;�|<���@���������������;�������_��������bH�:k�~>;�����������erprd!!���&���Y�2��`��h�P
��U��t5�M��*��N������]��T����)9���tFr�����Xx�$��:��s��� �������cA_4����7���n�d	��C_4���8fJh�i�Ah�;g�����U/x�dP����a=�0���,��)�������G������w���KS����M��6�
o*�n-�W���T�|��7�b7�
�?�>��'�����tos.���{��e�<'������.A!�K�M��Xp��(G��d1�z��H$���!Yr�"�1'_����_LnEN������ye1��:�����������l1�N�GU
�+�P�{�[���AG�v8@[,��Q����]�g��:��AG��P,-�kj#��|�h���s���\������I9����Z��[�+sUq._E�8Yod��"���[��S��l��owJ��,�F���,�=�3�����Yf������U'�����������{NY���Ev�
�i�
�@�gNnl$���'�r�Y8�Ud[
���=s �������O���f���{#��4t�T
W��*����kt���E<S����hR�$�������1yM]���E��?�H4�x��K
1�6M�K]���������z{xT����n�r� ]R�bV���(�R������BA����6Y��$g�!>�����}�lGF%0#Mg�N��(�f�L ��ZE�|pzvx|�2�;�@Zl32tlb��9����]wv������������h�l�qNpiwY��;ac��r��f0k�1,T�J�m��B���x?X:��3��3LR3�V�)mG��	���U��U�(�b53��t���H��%���M)�f������l<�
\{��i���=�8��<y�e��I/�y��2a�!�Z>[0P��%������M���5�Hko�yIgc��53C��O_��B��Q���tH@��������J.�������5l�����5:�]���-���V[��(@���F�+������F�u��@�����
���Y�5�T�Y�qi2��������_/���W{�<��R�}�dBPs��H7M����c�����T��3y�C�X��^l��s��D)���QO���"��j
��6�%���Y]B���U��|����pq������f������P(bhbT���uMc�1�"T����m����&����hA�$�nW����063�*n�*���c[$�q}!*�}{>�%<H�o���%?'���X�]
}�E{���I��M�������_1�#	���'���jA�^�r��*���dv�ga�o��xp�Z<
�|9�as����i{@In{����	�h,���)��W�����5e����a���#���;��&�L�^�
��G��I�J�E��%�!|�R(.�"	F�G,;��bl� d��^�jlnR���`���/��ElW*��n<�w.��o/��&����|kO����t����xv������|�+6��TC�9~��jckFC'F�����6<R/��d
���Q�}����1�5�T3!�V��>|��|��^�)V��O��J��l:�C�Pz�! yJ���ECxM���= ����N���#�KS�Q���EA��t��������o��z�\�k�8���Fr�2m;��O~��i'��U?��+1�L��P@�e���F��d����s����"l��"�]��tp��n���.1�V>���(eeL^��a��?�rl�d����d��vI���w2����y�� '8��b[�!��&�A��`r����8g��������A�M'�P+����
�Y�N�'&���>@���:�E���������
5��b.�y���qI����3F@i����.8teI��G}���+��?��=������<}��/

����
%����7�UwK��v�{c|��Ip:9��|�<��	��h;��RB���e__�M'h+��:;C������D<c"����~�9��g��M���u~+��yn�mFy�����c�$$�t'TS`����$9f�d��bJ`;�If��zcd�9�%���!�����}4�cv6�8����c-#�����R@@E��E�3���ek�+0��
�7��L.�s��*�����p���.O�c'�}z�c���4�����u^U��������<Y��n��{���z�QW%�W�%?����k�3�������W�T��pc�xC���n+��s+����h6���g�Y����.l���9l1���t�z��(/��������5�r�'�+n2b�8����x����KdV�_�W����3	~"�o���I�@����Ey{6��Fy����_��5�ZE6��v����m�z|&o��
�y��0c���J��Oz�t�S��
d��5��Ko4QrS|u�X�n�.)V���SO�9*����y�e��%����#d!/[�0L�:����91l�B[������M�&4[NUT��R��������x�
�XG��N���6�����=��Sg��������9��'�����8[UQ�����a��`��yrp�|���D���3��T�?0\���Q��RI���aiJC��K����a2
B�s=f("W����p�������b%��j���)>��!�{������BBVc��J��ov��_�{]���8V��3����P����k?
��[I:)AW����,\Q"�T\�A(��������,�*����Q'�m��|{X���"E�o8[[)K9�	I���[K�L5��t7*�R�N����J��:Sr�G��=}������r�N��Mg5����u�����<�(��`|\{7��Wr�W�i�V�����-���n���.���n����>���pE(2����>�w��t�c���84��{�$�H���������]u�� ���|`QM&rD9�QD�q�l�g�-�(%�L.CI@���]y�;|��`�8����%��C���>N��nly+J9P�-��O� ���H��!���/����
��SfFi��G���!�j4��m8d�:����5l��m�P�N������i:���S9�0��N��=��<��G��0l���8��?��;P��+,�94uKw���r��89L�5m"y��#k��O�5���x�^no�;h;����G2�b,0k`���I���|�����NF�+s�b�KE�����%X5���`8�_r|Uf�'dT1>��OKf�R���,Q
5>�� K���z
��j����e�Q\v��=*�����T���U����������+�����i�L~Z ����Q[��$��j
|.�U�}<�>$��*�2;�s�;�%���s��3B�;������p�8�$��!���|l���Th^w.�A]�����2"��Fx��X��I`�x
k=�B*���?���udy��}Q���_��lw������W�K*i�y��}y��f��&]�3e)��N��J��q4��jk��~�o�^���U�[[���/�<�����WQ��uV[7�������5�����uMW>V�k�V"���Ha���y��a�G���;*��$��E������DPJ��;U�~t^EhQg .�f��x���z��A?�`BU}��������`&XY��{z|t��,����;.��^����@e��Z�]��f���4�n&�
<�����b���x</`(�J)|�}`M�)�8'����kJJ[��oy������id"����Ab��$�+�!`X�px����I[f���Y���j{��RN���TV�=��;��_}q�K�|Y�x�x�C|c��B�F���u��@j����-��:@D�l#G�E]�,���>��� �x�A��
$c|VbP����hJ�1$U��V���j�x�A�z4Q�H�u+o�i��x�46k�F*dI��g�&����t�_x/���F��c]J�7V������*DL7V
�Z�I ��")F�M-���Z����Z�W;�����>��.���",�����r�X\�-P���kc/��RJ�X8���<x��X�}e�X��`i�d�YJ�fF?4��0HW����4���$��W<p�6W�{��m���{�
y�~��R����"�2L2�tSEb�A�A|S��7U��q3h��b�LQ��%g�����'�����0SxDW���)Jq3E��.'���n%#��tj�F����6w^�����)��`�����v���1��\`�
��&K��M�"/���
3&���z<j��8����%��o����:m���e!F�<�Q�v������������7\����������a��XS6�}��V�P�]Q+���������v�����������
0004-wal_decoding-Documentation-for-replication-slots-and.patch.gzapplication/x-patch-gzipDownload
0005-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gzapplication/x-patch-gzipDownload
#70Peter Eisentraut
peter_e@gmx.net
In reply to: Stefan Kaltenbrunner (#12)
Re: Changeset Extraction v7.0 (was logical changeset generation)

On Sun, 2014-01-19 at 15:31 +0100, Stefan Kaltenbrunner wrote:

/* followings are for client encoding only */
PG_SJIS, /* Shift JIS
(Winindows-932) */

while you have that file open: s/Winindows-932/Windows-932 maybe?

done

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#71Erik Rijkers
er@xs4all.nl
In reply to: Andres Freund (#69)
Re: Changeset Extraction v7.6

On Thu, February 13, 2014 17:12, Andres Freund wrote:

Hi,

On 2014-02-11 11:22:24 -0500, Robert Haas wrote:

[loads of comments]

I tried to address all the points you mentioned.

0001-wal_decoding-Introduce-logical-changeset-extraction.patch.gz 159 k
0002-wal_decoding-logical-changeset-extraction-walsender-.patch.gz 16 k
0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gz 15 k
0004-wal_decoding-Documentation-for-replication-slots-and.patch.gz 14 k
0005-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gz 1.8 k

These don't apply...

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#72Andres Freund
andres@2ndquadrant.com
In reply to: Erik Rijkers (#71)
Re: Changeset Extraction v7.6

Hi,

On 2014-02-14 09:23:45 +0100, Erik Rijkers wrote:

0001-wal_decoding-Introduce-logical-changeset-extraction.patch.gz 159 k
0002-wal_decoding-logical-changeset-extraction-walsender-.patch.gz 16 k
0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gz 15 k
0004-wal_decoding-Documentation-for-replication-slots-and.patch.gz 14 k
0005-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gz 1.8 k

These don't apply...

Works here, could you give a bit more details about the problem you have
applying them? Note that they are compressed, so need to be gunzipped first...

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#73Erik Rijkers
er@xs4all.nl
In reply to: Andres Freund (#72)
Re: Changeset Extraction v7.6

On Fri, February 14, 2014 10:13, Andres Freund wrote:

Hi,

On 2014-02-14 09:23:45 +0100, Erik Rijkers wrote:

0001-wal_decoding-Introduce-logical-changeset-extraction.patch.gz 159 k
0002-wal_decoding-logical-changeset-extraction-walsender-.patch.gz 16 k
0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gz 15 k
0004-wal_decoding-Documentation-for-replication-slots-and.patch.gz 14 k
0005-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gz 1.8 k

These don't apply...

Works here, could you give a bit more details about the problem you have
applying them? Note that they are compressed, so need to be gunzipped first...

yeah, unzipping -- I thought of that :) (no offense taken :))

I just gave it into my standard patch-applying-compiling shell script which does something like, as always :

patch --dry-run -b -l -F 25 -p 1 <
/home/aardvark/download/pgpatches/0094/lcsg/20140213/0001-wal_decoding-Introduce-logical-changeset-extraction.patch

patch.1.dry-run.1.out

(it loops to try out several -p values, none acceptable)

etc

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#74Andres Freund
andres@2ndquadrant.com
In reply to: Erik Rijkers (#73)
5 attachment(s)
Re: Changeset Extraction v7.6.1

On 2014-02-14 10:42:46 +0100, Erik Rijkers wrote:

On Fri, February 14, 2014 10:13, Andres Freund wrote:

Hi,

On 2014-02-14 09:23:45 +0100, Erik Rijkers wrote:

0001-wal_decoding-Introduce-logical-changeset-extraction.patch.gz 159 k
0002-wal_decoding-logical-changeset-extraction-walsender-.patch.gz 16 k
0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gz 15 k
0004-wal_decoding-Documentation-for-replication-slots-and.patch.gz 14 k
0005-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gz 1.8 k

These don't apply...

Works here, could you give a bit more details about the problem you have
applying them? Note that they are compressed, so need to be gunzipped first...

yeah, unzipping -- I thought of that :) (no offense taken :))

Good ;). I thought it was better to ask...

I hadn't yet fetched new changes since tonight, that's why it worked for
me. It's breaking because of 801c2dc72cb3c68a7c430bb244675b7a68fd541a.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-wal_decoding-Introduce-logical-changeset-extraction.patch.gzapplication/x-patch-gzipDownload
����R0001-wal_decoding-Introduce-logical-changeset-extraction.patch�]ys����;|�.�T���Yn<f�7^��{I�{�j���b�|�{N�$�����8P�D������G
���)�#��:
=Q�����5<tTU=QO��t��;
�4
�g3�<"�F��GZ�F���t���Z�&�-�*�����P�Z�O��T�s�uX�TH����@���n����r��h�����8]��O��gI�~��@���S��q���e����n�5��D�Pc�l������h�Q+�n'�MF�:���u��&������������Cj�s:���fZRL��l�*��A�i����A���E`�H���iM�C4gL@2���Tb�3k��Z#�FL����?�U����f�����&���L-yg�;��B&�2�7
p ��Y���l�k@��@qP�V�6p���@�`Dvf;�ewP�Pt5��T�R�����R�8����az6�Llc�0�tf`7�[z�g�k1n��;1k�L��������m�)7|���?SZ"�v`���#�d�3����2vm�������]��/m��C!X��'�c�m�	�qg(�K�����Y�8��k@��	��`���V3F�]������!U��y3����C4�DL�?3�S���&���F�tfB���wK�|�����&�7��Y�H�]:���e�����=���D�Cs�%3L��gF��������`"�Z�F����q�7�^���'Q�a��1S��+�e���8P��~d���F.4��w0-����C��%��)��\F�N>�/����B�F��R���"}�c�Z-a��������4������O�����f��G�7��w��,��tb�u����P��� ���m.�V��_���
x9� >j�d|,��Q�B����� C��@3_!}N��a'��U��9S^bpz>��������s�vm�> n�3�[���Ed#q�$���q�9��y9�c�H&}r�.�[5k�`���%5�\����H>J�,���Q#qk)���/0�v'�W���,x*�s3#7�#I)�����\�<�>�Ej���3�G�F6��	��e%���M�K��1$�)�F����W�j��qYh�����>�tV���zXq�1���TMX���S��������J�����T�{�j�"]��1
�������j#������9��;���7c���N
�:��3��N���[@\M����K�u����^����+�����&����|��>�%!�tR&.J�i���d��r/P�QK��X1c���I�����3�tv
&���(�v�t��O�"�O��h�� ����L��V���T��*~O��Gi��N��gy;Jl1������
K������-c�'}����D�o@|��
���!��Q���5������:y�#;��Wr�X�I������"���(�t>|yL����Q"���aS��z�I
[R�)L�O��Q��6��\��`+l�1�k3�>�L�Z�$/]������P�����a����T��>�1���������,i��6e<Z`�H]�$��v��i�#u��������C��t���0���	/�t:�K�$M�NuxuN�n7���uNJ�<J�/T��-�:f��:��$I�1S�vW\12j�K:�A,�a� n%L&m��hCE����,�(����M������<R�
����>n�5P
��ce�:�8+�|����aj�R��$��p�����T�)}������Tr��<8�H�Drk���&����CMWgv��D0��&�����5��3�1������	R����p�b��Z�j�_�C�6�x�t��_����Lg�Bu�v���4#�F���Y�,,@"Z�$m�U����U8y
��H%����$�������C�_�
�P�pr�o�
m�5,@� ���#kf�h!!�4z���T��aA��aA�P�� ��7,Ht�����2��	i�pU�H�P�dI�OJ������RX�8��u����J,b���x���Y[�BD��b*o/Q�4��(D�H�
�J%U�H�:�B�f��6L\*��(QN#�:���U��y2����O	v52^��B��
������������o��'����;{�}���������o��Y8��7���ZP��.���`���`3j)��� ���p�����#C~�,��Z�������M�z_7\]�Y(�=��Qi�r�r�s�����x.�����>_����1$
K��o������U��T�~�������f���NoO�$������2����)��y`���$�N�	#��6���9��� /���{~�H���&&0����x{(� 4G������.z�8��E����) �g1�T���6�����
>}��_*�08��z�h�L�R����I�'�eOp���!�f�����N��o}��t\f�CU�������c�<���Z�^�������KnJ��>����[�naM�@3E8��fc2����)�=f��j��<T��{���A��w�
Y�6��,���Cu]�0�������0��=P�&��5jx�i��vA��A(�v���x��0
j��l<mt��9�����c`X�1Bgf1�U��q����ceE�k���Lb�P�}N��+0����x��V��������
��6�0��8/1��
���������.@��{���� ���1��4�\�y�qN��]�-%�K�����^���w�k�'�~	���+�	�kI�'������
������H�xD�<�=��a��"���j�dU)y�qP$�����jug:�BC��`��{0�������6�\wUk��~�U=�__���R�9��.Il�J�`���,�;{���=����*f������}��?��e��x}�{W�O"*9A����Qeco���;��V�y��<U����Q�U�*���j�6/	�,p�t�ie<�L�	Z�*����&u��7"E�o����L������F����dJ�
)�Q�S�I����`������x��}E��j3x>������s-�7d�<��'������������I&)�4Q���;o{dQyG�@���������3�����5U��3v�Bi�j
��4]s`���n�=�h�L�t��!h�!M�|��wvKv���.ys}�KZ���AHp)��]����n��FT�������S�5�p���{Mb�@o�U�T��B�(v�����.+�?^�(����x*U�0���U�%|�zs����h�}MGT�AMA�Z6��~tD�CEm���wDK�Y��e(�<��{���K�=�������m.S���9_
4)��������f�dxK��Y��
����� ���Oo��-ll��Vv�xaY��%J�����������Mb�T���W��H7�������P��H6�%t��`�(���0�B���Nk�Xh���%o{��~+��K�����[����p;��S�Y!���O����s�O��Bs?`��T��^��n���������/>_^qn���O=��K�i%�i�Q��Id]^�����(p
�#�7>@�f�3l����w�������q�~�R�k�T�j��@$�6��R��(|I�%t!1�w5a!���������d�����f�_�	Z��C��$��$�l���f�~6�	�3�)	��N@�����j����&�:����u����"s�,/���sG���lo�C�m��Xm�P�[
jf�5k.6���73}�q������z��w��9^i.����\|�5X��]��}	~���%���&��d�����{����*��l��m�?A�?U��]�7(�_Du������������o��Uld�����-=6����g^3e�&/����M\��)���|"��&�����.����X?�a�����^�l�a[�lQ�qQ�eA��nh��3�]�|#�l��<��qj1%��cv������!�g�C���S��"����O52����Y�!���}�4���A��}��+�x�����:eH 4Q�0�2-�XR��8�1x<�n���"UUx7���A�-P���3����ete�>�n�{n�l���Q����3n%B/������~@���o4$5�R��B�+_������B���A��Lf��z�$���/�Oo�)��U�K9��N���&T
[��V
�D����Lf��v�7��9O�m�?-�_J��b>=��l���T
[�2-_(�u.%P�CL�D����mA�o�<ZCp)�=J���]�����Oa���{���<L��������N�Sb',�����M�#'z<�)�-���{�����Rm
,Jk���|^9\D����G���-RoRo��Z���h��/b1z��miS�i��G<�k|���.��f@�>�������^��H\�>���>�k�.~���YO�AB>n�Q����6�hOj?����Q���D��Zj�G���O�P��Hg;����6�9�i����%�}�{����F������yv����h��b�������K����m�������4��mq���Q_?3��/o���������[v�������/�Z~��v��[T}����X������S��R�>����x�����r��E~�XUs�d�70�o+
�����������
�9u��r2d
umF��F����Q���T���%;1r�o�K&���J:e��~�q�.G�d'�`l�����v��������M�t���}Dg��b��!<�9���0�BFX�bZl�������),�V3>eb��]\H�v[����x9����Z#*����`�3�p�������i���	��A������GN���{�'����!�ka���I��m���,R��Qmb��bj8Us�>O��x��$)vS�l�;`ol�=^M�@��.,FL��U�4XN-GI�i�#���W��0�&:�G(�L�r��y`�����/*�����[X�!S�$�{���1��g���_-(��L/�4z����\���0a����	���#D[j�,�vx��z!UL��g��v��k��kp���L�d���/�p�2UWa�(rl��L�;W��q	���B����������P�����y�\}���MF������������A��`��H��������!�t����7����������ls�r�wJ�	�BB0Q|��)�O�&
����I|Vp)1�����T�JY�\����FG,�@�Hh�kPa��oD���w�i��Z,�@�r�9�����:d2�b`��'[�.����[�3!��@6�`�!6�a����]�A������������w�k��
�4*�]�w���J�k���M~� ��I�Y	6�}��-����>��Q�
�:����
R.Th��kguk$��<~��i?�N�CO!C��7�o
��Y7��^��A�.d�����e�7���asUH�f�K��	�B����U'A��p���tG����U�GV��h�	�*�Wx5t��lIjtij����\@�Gz�Y���l��^s���V|���{���u��k��c��}{-����wB��O<����Z�%�����e2Z�Y�,c�~[5q�]���k7�0�ye���������x���������x(�L@�t��x����	��b���oD�?	�s���lE��5V���W��C�U���O:��j�p�����"J�V��������u��:��;P��Zi�Yt|��cYMR�5�Am�����3Q�J���(:�<[~p�.#Qh�e�c2�r�'���%H\p'&�����N+��DSY�!*x�r��*
k�xj[���L�HW����}q�f�Fu"��Nn�*�o�fA-�$ {�F����H���<9�����)6��)��D�=���H]��L"�{�*��#�vMhN��;���Oca���j�L��i�]���������8�������mI�8����IL���g�v�=�,;:#K^I�dv67	�<�HAZ��������� H���d�t�0�F?Uu=uu�Y��^�%['�.������������j������i�x�Y��1�����&����clLtV�o�h:]���R!�/���]��M.���%��0����f�4�Uj��FpY���&C�����}����f�RA���^q�n%�)��^��G�����D��G�rp>�*e��S�4���C4�u�?�(W��������P}_���7'���?�5�g����v�#���*��C�jJ6��\��2���e����j��K��/{���*f��Z��3�����'��
Z�4��6-����(]H ������}6����{+����tnSY��6'����Q��_�J��������!��Rs���o�<���8��tc=�����>����N�jv?H[#�Qt�a����u�15}1�S4(�(>�������vWb�������V6��*��t�/���Q;�x�j__����p��=������3��ktQ[T�e�Z�o��|3�.�����d�/�V0���[����:���U^���X]��z���U^m��Z[�����W��U���e���JF[���������A��B3�:4-%#xwA��
���?��/�M���Yr���o���hoc�+i�[�s�9���
;�)%����\�g^������k�����1���d�X�z�]����*��,|}%��^�z}%�2�~�m�2\�*�H��Wu��zs�@8����FM��#���2��"x=/�f���H�����v��L�]3���s���YK���uWf���Z���J��Fa��a3���1L4�0|5����&����[�j��gl�rp�M2���[��m���s_�����`��tgx<��6�?�*/�5B��E�3�&K
�Q8��k��u�%��9��57[#�����yen�9�0GA�����tHUZ��+Z�-g���J3;�?�N��:�Z�4��5\M��lFMk5������E����_��g��$}9���~w���U4
e�K
�b�>K�Z�S����C�����/�b?���fh�c��u�/1�Y�����=-����g&���Mm���M�	5[�]�o�j��_�ymY�gp:MB�h�3��<
'��*�*����^qr1�i�_w/�
|��^2j�������E8���)����Rv@������?����l��� �#��WG|�
��3H]��^�\n��b���1o������h�����������
P������QD#06��������X��O�u������;i�'���dP���n&p1�4������o�CR����,s%J���>O�
v����~s��}������;�w��6�e�~�������9�f����OYK�q�z#��(�����6��U4���|{��y�	7Tc�V��Y����'=��|A���R�`e��t-�#��?
��3�=����� v������7�������y���Vv���[�|v(��z��/�/�}�1����"�����9�Y��u����a������Z�y-�9�t�V���:����}�;_:�F~<���G��Ko�j�����#��g��%.,�������la0w��>{��{���3�nG���
�+�������n
��j�n���]u����K9��r�6���x8������"R�a�����s
8N��lk����I�6��5��U.��zXv�'�q�."�f�J�\�'���v��W�Ggg
^�j�6��n�k@�>�{���[����^��S����K6��EP�n�[mc��N_Z�����<�8FP�<2�E������������D������|���O���>G����2��������8��j��,VO'�HV��x0g�1}mt�8���Z8��,[q�G�iz#�=^��n��\��'�I�m�y��_Yw���t����]fV�#����9,���G��^��>����y��4�j��4�1C��q��iE��\���\�a.�Z�v�MM)�x�6��+��f��#��	��jp1����������g�����Q�B������Z��62��:����d�A�2��(���T�)$����V'��,]n��?�xG�o,�W�T*��8	�����m����Q8-9���$~7�a�~���d���YY<�fv�*���\mW�qR�N��+ND�@�eP��E�/������������/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/���?���i�{��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|���?hy�t�_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|�e���i�����#��w�������4<D�#��s��~�������������������[8m�����ih���r�}���P^����?J���t6D�llc�V��{��V��T���6����[�K��Ao�,�'F����>���7W�����xs����y,|����57��Z������U�d��W���Y��}��+L�w����U��+�7��>�:���3�
w�>+�r��4���0����e�����6�o6�5�~0�~/��W�Jwo�i�+���J���}�n7����n���X
Ga<���	�<�z��hP��4�<���z����iW+�j�V�W�f�U���T��J�Z����F�Yk��k;�v�R��k�z�Qo�[���N���4��Z��h4��Vc���h7+�j���7�f���n�4��J������F��j��[;��ve��]��o7����������Ne��S���4v�;������v��������������+6F�Aa�=�A���2%N
���0/L3����j��'5��^�5��f��������j�]�W�R��6��f��������j�]mT�^�Vm`�0�f���6����j�]mV�U�Vm��M,'�UmnW�;�f���p�Z�U���V��]m�T[��v���U����Fu�Y�0�D;��vu������;��N�������;���S���H�v��nT��j�UmoW�%`Y��+�Z�^�4j�f���U�k��Z�T�\���1D���k|��@\2�� D�]�W��xRb4j�f�����k��Z�]kT��x�<�4k�V��]k���Z���G{�z�	4��j��Zs��l�Z�]���V���k��Z�]��\�v����m7k�@R �Nm�]����N�����4k;��p�D��;0��n���Z�Uko��@q�x����*�z�Q�4��V��]���+X�
Q�x���%���
��+����11�C�8�u�X�����&�.�6����
q
K�'
��f���7����z�]oV��X]������j�����N����*�P,<�k5�-�N���zk��j��+D^�]m7����66/��N}�]���.�b�Q�i�wZ��m�Al�
P������f������ml}��
w���W�J�Qi5*���N�,�p�p�af�*�@z`6��^�"Ja�@`�X`�����E���p��F�!���J��C�����h7�nJ��O� C�Fs���i4��V��h���K-P-���Fk��j7�+���P,<��n6�A�@�v���N�������fc�����q���.����n5���6H"hb��(Hb��f��jV����f��B�AJT��I8@@����R��:������f$b[�3&rf����q}�\.���a��&�Q���k$�$��� ��v�U!����a	�����l�4[��v��
�h���K� � �;��vs�B��������Vs�td�r�]�L�{���l�U�WTH)A��FQi�*���N��V!%����� ��� ����W�:�L�������r[�	�"l� =�U!U&"��� 0`��*$�\�:��+����1�v�C��D��FK��]�������zaS���x�
����n�v*� l��@C�.^�����9��a+C��h\����o�b�ytU����lW�*d)�mu�5Y���W!�!5��I|1F�Q�Jl�
�W������uZW���c��(�`��
�Y!�"�����R�4���W���:��E�snos�U�rv� B�p@�`���S!?�����a	�d�D�
X%8�+���� 2l�![T�E�@�����Xx�W����SV�`)�����[��,��B�K�W' �jqd*���e�:i�r�$����c���I6H�Z;	0�Bf��\'E��kqZ�*�q�|��['�!��8c"fU�@��I���-.�����U��8�w_�L�j�]��~2��M	\��	��v�B���
�h���K�_m��"�E�i�����-�C[������0�����0�����0�����0������������������������������l��l��l��l�� }[��-���jr��mX[��-����h���2��t����"�V(��a��(RJ�I)�R(�P���J��B&EI
�)�Q�� Gq�BE/
X�(,Q$��C��BE
$;(\P���@q�L����l���,�����L����l���,�����L����l���$�����D����d���$�����D����d���$�������[������[�������O'Y��"�Sh�0F!���L������
�d�@�<'�As@��]�j�(
�)�S���Na�"7k�C��()��A^MD�J���@�A��S����z�	0	7��
��I��\���T����������I��YI9I�2�Ay�r��E�{�1�O�2-��B+�1
d�d
$v��T6d��%[Jl�D�a�9H���vpy�xP���A������5X��.!�J��>w� |@v���QFD�Q|�XDvO6F�L�CuF48�&�G5��U*�)��:U=���x@4���(��� < r�C���E|P����`< n�C��b�`
���!�x@���Z�2)������(�`�������6�`X�b�X>�x�)�C��l���"h��� ������5���*�!J=�)�T��>m�P����X j��z�X>�x��I#�Q���F��<������(�T�P��
�*)TE�p�u���P�@=��>�x@���x@����:eh�<���A=�C� ���kQ���z�x�hE�)���< ��C
�H���{|P�������������������4���PQ�x@���Q��<�7�|Q���
��FCl6Z�A=��d����F�N
>�x@b���YJ~���B�zT@(XS`� DO5�$�*��=�~�U)*LT���B�("��@B��>���!������hI�@�z��>HaE�!��< 2�C���rJ2_���q	�f(�QP�Y�H��"�A=�lZq*Jz�k�`�i�< ����h
��MvES��+�_|P���$�F5��\�����<���i@�R�z�|P���6PQV@k
��]��!J��^)�Q�$���H%QLRT�P��U4*b����>����������r*�vh����j�x@�V�x@������F��RcE��C|P��D���������,��N�0��"���HQ��c�eW�-�kB���a�5���x@S���< E��V���i����z�T<|P���	v[Q�x@w��j$��o�A=�*��e��h:�IDT}��jF���4�_�n��TX�����*&�Q]�Rx{<����z��)|����%GE�j	>�x@����G�:�+"&@X��������Z*+*J�;��<�zV��x@��V�
��u�P��3�m�4C$�8RQ��Fu�h���h ����*��i$�r�z�S|P��p����
�����x@�����*��T�����+�P��A=�CD$�Ei�����;��D�?T�)FQ���L���r���T�CD-�:">�x@���_����*"�As���:������+*��m�'<����U�Q��
C�\��;�1��+v��"��������<�Q��z����u�������<�NA|��	x@���0����A=�������a|h��r�z�X|P�Q��^���h���z��7��Wi�����G�h,#�Qi�Y�"-U|*�T���S�;�h*�{����z�O|P���X���g�����+P���r�!��(������-H��+�*kA�V�F��h������$�+*��y@%�(����bzEEu�z6>T�Q�����P�U�<�q���*��x@��������^�gT�Q������j�-�<���C��(��:���uZ�i	����+��P!�P��b���t@�T������`{��]F�t����-�I��4n�d5s@V�����Ys��!�OKo�)�J�r��C9�Ow��<}h����`��U#D���|��gZRi!����"�qMt����M����;����5�T$��i����64���+<����4p�pK�$
m4 �ph�h�S��
N�.������$C��"�^x�@S9M�4m�dGS�L���r������t��i��]��*�:
0`1<�����4&�HJ��Z�<4������'����LK*-��|q	i���xX�C�i��1�FF��@���)�f�`h^���f�<�

1C�*j>hTT�oUT]�:�*4�c��Tk��R��I5�*b[A*jU2�[T��&Q�zC���`u������)�S��H�V�1�",�S��+)2R���V�����&�Dw(�PL��V��,�����l�,������h(����l�������d�$[,�%�$�$$m$[$I$7$%mEg�����5��x��Z��(/v����5���"w�D���.���99E=�u�D���<��$O�uh�<�y�A=��x���Q<d{��x��Z��j�x���Q<d�x���Qk�X	���Q<d��Xx���Q<@��A=��x�V�A��5��x���6�P���N�#�Q<j�G
��5���C�����0Y��Q<j�G
��5��x���Ah��{�:�Q<��(������NQ��):@]d���B~h�3n���$��x�����i�&����g�r"�z<]�*OJy�SO�1S�:�Qo����:�Q<����:\�:�����P��u�C�!���G��u�����u�CH&
��G��u��x��y��z���Uw�:�Q<��G����q��^�u��N��x��:�Q<����g�R5�DC���h
��Qi+	{jMlF
�U4Ek��#���y�k<�E=��x4���<������ ���R��@�5<� ������<�3`��y.Omy6�X�����<M����<�������<�G��G�<���&����<�G�hl��
�a_4�
��x4���<;<p��1�7����
��<�G�hd���{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~�������{~����X~L�a�����(����������2}����O����o����o���4<D���(��������w�v��������i����@�G�Nw4��m}��GP�fk{���<`E��^�
AQ�A�K`2�C0zX�����
Vt���5�<���f���n�41�E���l�Z�����
��
��nn����w0_����,�Nkg{ggk�����������&?��I��8UJ.�������0+L���03L
��1C�u<,�,/��`�A�����C�����4�$��so��}�{�y����&�H�����$��(Z�, f�?Xm��68%%Y?�
�2�����{�P�����b�5����).`�m�)�F��&�!�!x!XaM!��&�v
6���&K�Ja90gL��1t�fGL .�
@�����'�� ��� w�d R�?dhU����m����}�-��@Ve{M�m�P��~vF�
���:h���
.&Fvpa� ��Mp/0/�.�.2b@��i�g�e�c�a�E0�6�(R�
�
|
l�.L���m�D
b:�-�&!Ja�@`�X`�J���X�&��11�C�8��z�u�@�B�C�D�E�F��d6U.!������H�����j��T��x���������!#�b��^t�;m�,����mP�&8�
�
����(v@{��'`'�&`&d���3��Un��������4���d� T�� ��� �m�n��������f}�$���gL���%�&�����\���1��0�*J�)Hh��+I���%��&�P�|l���h���K-P-��mP�le`(�m7A�A�A�A��p�����	��i����������<�L�����}y�>C��
H
�|,��B�AJT��I8@@����R��:������f$b[�3&rf����q}�\.���a��&�Q���k$�$��� ��6(�6%p
K�'-P��fk��j����a�
��xi��|����%��V�b���N��^�2�����V���l�UP�"��DK�������
�V!%����� ��� ����W�:�L�������r[�	�"l� =�U!U&"��� 0`��*$�\�:��+����1�v�C��D��FK��]�
��d����%��m0���v�9�+����v�#������?��a7I��hr����I�A���aBer
D0�
Y
y[�xMV�����s��U�mH��Dy_�d���BFD�U�n ���A8@���(��:7
7f����@V����u�!�&
�`�r6B����ElQ����}����5�P"P<�nC�"?�����a	�d�Dh���`�m���D,0��hA=�\��
eLb(�h�8e��B@���<����b�*��d{ur�GA�jX![&���6�.�8@�Q��
96I[�d������p�+d���uR�����W����ub[�3&r`V�X�t����bp9�;�X�L��hp��5�T�� �Bp?�����a	����=����E�m
i7�{��"H�E$j�p�1�-G[D��ma�ma�ma�ma�ma{ma`maEma*mam!�m!�m!�m!�m!�m!mm!Rm!7m!m!m��m��m�`m�*mA���o[�-(��h����,}[�-�����e�m��-��E�T��V��m�JmZ�W�E;S[�Cb��]�6�chk��6�?�jA��3�h'�
��=uw��m�2��L1��	�W���;�SR_l�%Jt8�g�����3Q��C=���*0"�2�2�{�tn�h������l�8������h���d���$�������[�V,c�|�b�H�.�D}"8���J���B+�1
d�d
$v����Z�d�kU] N���9 v��Z5A
��)�SL�0N���5-u�R���z�y5yi+i��X��L��%E�<��H�IX�a����J�������H�I}���*��5)BQ4 �#)'����!�xP��E��|���t��S����A����2O2;nb�@r��%[Jl�D�a�9H���vpy�xP���A������5j��gM�:51&@�<����<��)���>Z��H����l���d���hpTMP�j�	�T(�S������S����z�D|P��R�*A
x@���b+������!�W������G�m�x�)��V-Q�������eRlA=�Q��D�l�<��!�F=�C,�D1�,�<����J��k0���<@*�A=��
��Z���\[];�=p}|��*�� 4�b!����`y����L��F��,K��y*yU+nQ����/TR��P���[����u�< ���z��X������P]��z��0>m��s���A��z���x�����������R���z��X����{|P������m��s����z��>�x����V�����)F��(>��E����	$�?�< ���z��X�IZjT��4���z��H�D�i�)�QhQ�
k
�������DQe��/��*E��j��&��PD����

�|�i��I�!�k��B��p}=� 9< ���z�DF|(���!'$���/|P����m3��r�A�
��< D��z��>>m=�C����b���x@���!�!�$�1j�+���X� ���z�������������< �������:
HT�P�����|�D����Z!D�F=jC��)�R*��IvA��J�������7�hT�x�C�x@#��Z�]Q�B=�r�������A=��;>�.P��"�&��0>�x@v���0J�m9E"��|�����A=�2>m=i�������U�Q����O[O��{��B�dg-�kB����'Vd�5���x@S���< E���i�&;*��x@�����z�E�x@w��j$��o�A=�CN���ib���&Q�Q��U��T����Ra�Z*�B���Gu�J!O����f���e
�z�x�IE�j	>�x@����G�:m9���a�< ^��z�b|�z�'��59����`<�!F]������$Un�-T�)������!'�IjTGQ��6�O�b|P���C�-uI������< ��	#E��)>TUQ��F��r
I�������T\Q��:�O[O*)"�.J{�X������'R��*N1�j5�g��T���K����������<���C�/�����R�����u�A=��	>m=9������������*Fu�CNWE��	�����]�#����zK��F��h���������R<��,M�(����uJOr)B����:�z��`|P���^����a|h��r�z�X|�z"LQ��^���h���z��7=5��Jc6��4>��Fc�AP�J+�i��S���N�������F����b/�X|P�����P�<��j9���1+y@Nx@����C
��D��E�MnA
�]AHTYKN�)b��V����<�X��DO�)��y@%�(����VO�)�������z�tm|P��Su���4n|x�@��������"?���k���8����t�j�-�<���C��9����Z�i1�%�>Z��"C��'�T1P�F�h ������C���������H����9 +
g�����
��~Z��x��\	�^0]��>|zpt�r���\�=��N�����x:�/;��e�r���9P?�^��
.�a4	�Q'�&�(.U�'�\��/>��f�*�� ���a/@���a9��O��������2�=|�����0�����Z/��=+����'�A���:���c��I\GA��E�du��� �
��E0����Yg?.GC������l��Cwh������i����i�2�vt!���It9���?�����pt����`��6?�{1�Ws�_|��_|��_|��_���������/����/����/��K'���/����/����/����/����/����/����/_���T/H:aJ�>L�S����0�>L�S����0�>L�S����0�>L�S����0�>L�S����0�>L�S����0�>L�S�?;L)���Dmh���C��H�@������$���<�������]����=�������?���{�|�����=�������?���{�|�����=�������?���{�|�����=���}��Z2���.�.�����z�aT.&QF��n8&�x�?���0`*���
O��71�J:D�5;���gl��|g����K#|�=&_d����'A�C��L?�S�'���4����<��7W�I`n��g�P�$KO�i��j�^�������=�U~���#�'���4�>�c����h?�=V��8�����=���l�����(�F��y����67/�� |�
�����L�g��q��F�g	*����aw�5�M�����p]},��8��l�{����ek�}q��� ���g<�~����;����w�Y)W���r���������>�Z.\����i4���*��p0�����-��6�D�~w����
��,�o����p4�;�����e0���i�)�L�;���
T����	9�=����"���	����q�0]p������
����5��pH4G����*0� "�N'Xj.R��al��������\O���������v����+�~�
���"�?<�9���-�����9cI~��y��x:����Z�?lq6���#��������M�#��Lg�U���K+�'�A����?���������w�$��dA�7����CPb]����6w��l*��<����\q� ��]�)U�GE�%��g�!��s1������3r�����BB99�=<�OfV~�T��4�uo�������,����������3�v�F�~<����<��:��Bmmm}���<Hp:3��P-�"/$�jC�?|*k�F�7-��%�Y�B��a��q$�(��L��7�V�������:?WE;���!5K�����Q����W/�_�%;q{[��\���\����wjam�.���P�i-��U�EE�D%��%D���2<���8���k��+���5�����_��M�����?���4�&�%��&���fP>�l�Ugi�,��x}|���{����+�.���
�S���SY�������.�>f�����+P��7���f���{R	�h���=n���q��y���J~�Q)�=v��O�3
_)A�}�*���iL�W���j<�����d�J���`m��������uD.��J+�	^�V�*�v�����������jF��M�x!���q���1��`��&W��������� �������:�Wr�N������V�����@I��w�6���>��0�ee��tVsC���\�`fihA��;���s�7�9.*�s��9����>�
a����������?�Q����9ER�W�U���2�����f�h���x1������?�E���2�A�7����x�d5�Ih�or
w5��#�
HSl�X�`:�D
O�� �=�����N���.���V,���LW��g������o%�2��9]��S����S��_�<��c�~8p�Bo��zU�WQ�|F��]���b#p%o��?����*�Z��Z���v���t����5�bw�C�\�#Q����������,>���B����$��j:�Sy%}��nUvz����nW�.^i%]�Y���h������l��s�C�?�h�#-�{�`3xwr�v���4���xt���N�����	��I�Z�lp�Y��mb��A��{�������f�V
�w�zy��������?��on��/����f���C��ew�����v����[����Ub�}��w���A �5�/��d�w�L�K&�~���i`f�rnr��{��m����!�NxU��h<��x2���:��~���f��*�{�g��<��D�Q�P�X}/���q�;|�uN�	���I�vF�^��:u��C�g�n���h��kA��vDoT��3�������p�5��l�uw���Z��q�]W��]WO�]��M�\��`4��D�� �!2������w���������V�{��rgvZ����"v�^��|���v]<M��TFh���;������j�5�%.[���[�V~���.]�`����;�j;?����j,�z���b{�A4���V�7�'k���w���\M��5WR�k��n�v~�?�����w\�����=q���T�.�(��:W{�II��i�9{rt|�$!�4x���sT�v
�]���x4.�4�������7�w��{�_�i�9=;9�;{��p&W�4i���3����1m�������%�G%��6(^����6����|�'&K�o�y����~�?�w���������_@*�SU��0J��c����nb�J:O��U���� ���3��������c*���m���KrwX�V��Gm��f:��>V1��=	�o��!�����v/L'�5���
v[���tg��{�7�,�p�*��
nN�|'���������;9�A���Im"��F.k�����oM��H����Fu|j����\<��#��-xv����o�r'�,�����S��dx��w^�{E�;aK�)Lc�[�g�(���<AH�Wdq�z4�����O�'GGo�;�I��4����8��������It5�t��V�{5���I�	e�r���wg�f�|M���>�4|p����Rd6h�
X���Jh2��tI7�&#r{�w�@�������@*��!5�H�x�K��%���2��&��\e�LMDRqEL[}��U��|������6���D�<&��L+6��|0;_�e_"\d����rp>��=�3��_��Z���Z�D"*�f���B-��*�����q��UT��z����Y�j�T]�l�ju��j�.f��#�n�n���2�������W���?�)$���x,�Z��Mc��RE�6����h����\�����!IE�~8����B����MY������e~��I��K.����Uic��Z����w>5�{fCF���aZ�5b����f\u>�h���7�u��	(���������j�{�x��>��'�
����2F���%��8y�e�o��E�N��g�%gL�QG��04�����(df����6���{��G�o������MK��}�����v��5\a�6��@��A��|��YxV�o5��|�WM��H��?/��v���}�<]��3��ygn���U�{��n[���v��
�=�m]��	������	M�$�'G����#c[����NC%���6L\.J�'��*�K���Q{g��d�m����\I�8��j�A��N���$���+�Y���q��Sy�.��e��?�<�>�!tO�n��c���uD�����cQ��|�~��� ���En)�u=�
�����s��yLSK�Y�����l{��X��Qs�T���&hc�1&�b�(&@bb�"iRj�
�")�f�"��w$��4��65�q��VKa��	��L�i����KX3|qv�J��qS���=��`T�#B�����s[�	���q
�)��T�X����6�6���?<�������?������.S_�eno���B�[i��O����Jk
3N���S��u8��O�������U�y�\�
�U��0r1����^o��]
�$���Q.}k��iV��:�U������e�LD��V��Xm=Md����<E0�N��������JFK�HJ���\��.�I9���������-��*Q��p�]���x��h"k�
�EQJiB���#�Jh�G�����:�Ix,���2���8�L;\1�����-P(��pr�`Q;�:��m����&��Z+h�v���������f���m� �Z
�ZG����h��2&�P��"x��w�j�t;�4G��:��~�e�O���(��e��uZf�����F<=^�=��]��F�o!-dz���$�����, �Z�\k��w����.��V�]����8>>��=Z��b �;�\�������k�Voak�.bm�����kK���=��c|�����]R[s������������]2���^�K�[^�Kj�v�|c�.)jI���D���D2q�[��4�����E���hX_a����X���;����s#����^;2�����ja72f��t`��W��c����`���ceV���s"�:��#���a��uN re��J|q����[K��������;���U���.�6��}OwET�ma5L���Y���#T|O{�+
��@������iY����W_�D�+VtB�v��x���U*&>�u��q��JR�?�B�}�+R��N �n����G�t��h�u���Ly�:}�����T��R2��
�^q����p���b�9��u��:�~H|�����*,�h�|�,�&4�
�z�^��1�+q����WV:v�^T[��:�K:t�gW>s�i<~�sE�[��}�#������b�*���r�1W��#����w��']����/usGZ��u]3G�_����K�8���������w��,x2k]�t`�J��9���V�>�oo��V\��\4��Vm�4s�8��Q�K_V�o@i*�n��o�i+����]�(�.������Zt�����P�
�����9��c�C��\��;7�����0�s�p�"������E�}�E�����E�.����	{=�0x��7���phn�l����@Hn��*��Mxgwp�gZ��*J�����U�[V�n+5G�2�����OfO-]Xm6��������`[�s1��T[�
Wk��z���v�I��.�~������X�����%�B�����4������M����ez
�D~��~y�{��z�����;}��V'Sn�~�!�2��}{���{��Yi�6����h-M��������J���-7JpuC���
�a6��������?� �3��p`Z9B+����O���h�(��-���`��Ft/:/&���p�����n����5N7Gc.�W�l��2��F�nt��pw|�����A=�+���|^��	�����,6���&�+F�%QX���R����n��:���Nt>}������h����!F���b6�5�R�&��f�P"�����7�Fr�IU�8x�lqn(
�$�'�A�)27����hh��g@688
���`�4�{�5�8���R�JCt�V�*I�����Y[i����C���B���J*l���;��j�,�W�<	�R�5h�V~n&B:x(�5&�(��G�,��<���}�����4s����e�/��d���Xwe������

E����|�5����S��ve�Ak.��^���u�+_�uu�5_�~}�e8�?�}��&%�^B��`8�Z�[��?�����	Gm��W�5���s=������:.��y��aD 4_K�;�2���2e
����P-A����L�����k�e[���#����e�.�2���u�'�����G}mN�tZ�y�BQ�P���T��C���"��TV����~������>k����O�H��l������f�W���H������EL�v������HG��%v��X���j�%�Q���>/~�mm�����#��kKV-g��(A��E���� �����`��P������a|��h$F`��l��$�Yy��ht5�~�O����}�,����Va�j�Vo$q�r��%�&���U��dn%�]dl/�M�#y�{�����a�qCe^��)wcc�f�1~wh ���+�?����_�}������w�5����y��
�'���P�:�V%�������i���?L3��Ga���5bE:���f���8D+"QY*7�%AY���F��_��b����pJ�W7����U�V8�����^�5^���xA���5vO��l��8�_���ktR[\�e#[�o��|3��
�[0��]�(��7���<~�'Z���Gc;�Z��4�pa���Y,�o���������4 '�99}Q%v��4��D~kkksu
�y�v���(��S��g��SiI��&�QF��y����9�#�D��S#������,cZ����<5��Vo e�&�0u��6f�7����X�0>������{M0���Z@��rp���#�P�9�9�s����M�)����Q�f*mzT^0�q<b����g��]��p"i��<�c�����x�[��[]l$��sY~B��5L�KZ��)Z�-gI��L3;g����N-��\�����"��hzc~T�1���n;�����Lc�����"q�S�>���X�����)T���~J3�g�
vt�/1��
`���{Z8�e�A[�dGT��o0����h�%�=9�����\����,7�&�q�Oe�`�_u�<�����.��7����ye���FdHD���X�LW�hB�����pm��&�x_�����uW�����m�\�y�(���(�o"��[5h|�D#��X���AM�$9�i������M���\��>����,{S`!:�]�����_lG�{)g�,�js���;��e�a&r�� 8i1���E35��5������j/nyM��o�{k�Ss;W^X�],�'��9��\�'���v��W�Ggg
^o�o7�5�U1�$}C����fs��*X�Qj�/���,�Qs��m����K��������ce�@���c^%�~RaE�&zA�������
	"���>G����2��c�����-��'Y�,�P��,{���D���`=�h��m�PW�l�^g����(5�6������z;%?��M3��+������n�[^����s������=���"pp�j��%�u�6+������W�&�dK/Nt5��G�*%�K��m���;�j)���Y��[[�Z�b�^�+g���:���)����'�Z1�U::{��d��i���S��N�[cE��1�1���.�I<�w,�|����a�Q��������0����b�*��8�
�L�t�����1`}'Qd���%�����O��'9�����k�&�f�����^��?w�����rY�
�]����w�o�T��JW�v���jo�+BE�����_���r�9m�_���o�������T����L67����c�O��~�s���!���B}��_�;yE����}y3�� ���D������]��{r��v���!*x�:���S���J��*���C4�U:8}�n��=���J.�4J ���u
��D�:���t��x�OF��3���FVW4��z�cww�nw�~�A��xv�]�������w[����d��`�O��������~����I����D�'z���[�K�E�*]:�pM2���pK��
_�
<L�"�Z������&KQtW47�[�|o������A���)I�Q��snp�_���<���cO0Tke����*:�V�	k��v=
��	�^y���j�`a0��;X__k��7�W�_��Q�
x��W
���k^��r�-q��������zw�@�]:�;Og���t�/�������3������V�f�	!���&~��_��Qw���Xbj�?`d��_�����9��q�H:*�$�Pb*�H�Y���)�:����t�kg��%��S7cuY<\���g��)�����?��D4c��L�����{�i����R}A�-m�N;�~_;��$�]���<�X����	r��~����8����/xV���b�g��
6��j��Z�(��k�J�pM\MW�y��hO5s����)a�s������VD�����i�	�z<�_��9*d;@.�A7a�4�������7�w��{�_$<4�qzvr���s��&W�4 i�4����1"m����*�9�=�K��}X<���J}.Q��o�D�X���&����?���]�����i8�|$�[�L%�U]s�jn�r��i��>�U0��t0���F�&���[�[�~8
K9���^`�(p^c���h�e�/�ms��>���sm���.����<���?����i9&W8�gNuB���a�k#����=#7F����������kd���)�������'��7���������+,���j�>����K^}���h�MeB����o������b]�9 �l��<�\�_<�����\o�E�z��Z�����3����	����w�����F �����U@�rkO_��ZwYk_���(X�����uRk%�:����ZeM�:����������x:����|V9�U�.rT]�Ku���-��wtL���-������#>{R����s����������j0�+��U1Ok��F�5����-o��(��v6�F?������F�YE���}�����3W��37B�\����*x�Y'G��/�lGF����^m�����]���dp�1��m��+��e����;��f�^��G���)f����ho$�-��J����:����uG�����ku��/3���O�����,��4Z\9��*���K,q_b^�|���nU����W���vTk��KjAgn�:�I���Ew'��8�G�IX���x8j`@)���rE=|�_Q��(xG���b�#`L&�Ck����
���3������8kW��j�{����:�B�����MM<����}�p����n���A`��E��m�;=�OZ��o&���������6��F9x7���7��q�����_1�h��\������iD/{�6.v4���i�^������f�E�h���>hf��Au'���7q8�N�{�3{l#
��n��!�,~6'q$�Up�3�MGa����g�����M������?����>`����!*|z]��'�`���[\�V,}���{�y{����~�����=��*a�����jP�(�+)����j�c�����j�8x�=W@���
|��T��=xewr�����Q���?x`��!��5I��G�g���A�W������l��jF}���?��1��db�Ab�~�]�c�4#���t��`��c~��~.���M��'�1e�Z��������,���l��}��[��$��L?/}��$Mz����X�~>
����m�f�j�Aa���g�{u�M'&�S,�Th�
.���F���)������hO��zf�����L@OC���mM.F��@�O�G�P�d~���M�'��d�<s�\kg��vc�f�K
�}_�a���-n���t�=0X��������t�!��m����[�N�����l�����Q\��IP����cn`��f�e�9Y�\�D*�������O�w��v�B���^4@�{��`8�<�
��,�z`.��Q�c��R��y�*�P�2��+���{O�A%�=���%�#K~?E�uh�=���=<<����1���[hx��[�����U�������I���<��0���1'�E�������� ]h�#�F�������?��;|����s����aG����������7�W��1����b]Q�����@���F��3���*�������KM��� �M��S��l�7�S�����J`��n��U�m��
�##U��:��7�b��0��>1�s�I��Pc��(�����F��0�=�@G07�
��R�>xnE�O"�u��8�����I������az��9vi����$��R4�ps����W���������=�}���#F����o\���G]	� k�1�9���o��z$i��<X���a
�����n���?��o�_���@\}�����H�
n��y��*&���K!CJ��
����O�'3!m�V�������_S��@1�J����(��"i���t���t� �>���
���R�<xT�!d��������=&wD��1c��)^*���\��R,�`������!0�g:6���D��"F�% �
��RF��x�.�xb&B��Y��+_�����N��$��tiC8�(�k�~8G��r�����d�=�5�f�M}n~�Y��d�����Zx$/�C-�]wu]i�W��nv�k�h��5��h���G�voLP
��7�FJ����������X��y~��`�N��?2�M�������#�9[P@���J�g&���F98c�WQ�e=�[~�����}�U��?���)68�!`��p*��c��$��R+:�L\�-���U6���A��a�"\J#9+LF�?��o�)�*I{��O�����j69X����Lj|1��v���/���!����qK3��?��!��BT�jJP��%D }gWp�{~����O���M�:�[1�Ayu���'� �j@4�0��.,�4�V4
a�XR��yO_H�/��S:!�'Wj�	�5z�4�����O�*����Aw�1���%I����%���?��A4�����c������(f����hO��fL}�����T�#T�EE/����dX@�@�����1�W4���������������@���������^�������-<�G6�Q,��z
���r"+�c�Bj4%>���3�t�wC?6=����!�r��`���q7]���6R�xj�G�P_�^�0��;���h8L�������L�&�u�H�KsG,�%m?�U�{����M�G�z�����������������@�$�yN����������<
F�Fj��:��G�Ut�3ywex�g����"�2(��e#x�vzv�~�����4D1E������r���bb�����+z)��)�������k��_�o���"D��-���r��,����c����*�{�o��)�+���;�����&�G�'}/i������>��\@��|�]�Hy~�mB��wB�l'���8��\�!)l.�Z���"��C�����Y���cE:�G�N�\2��Q�r�mSh�f�(��+mD���H��&[����������������o������-+H�@�w��|�no)!rf�*�����f�M[���Pqdy�!��|~+V&��r��n�p+������9��)i�9�����,��3�7&�����e:�hI�^M��VvH�����+���1�/�1��������H"������8�I��J}�r@����,����7�,��p�S�Z<���mUm���{dfvz��v?������5%T�]������H��[�[������X��l���=znU�X&�W@�e�%B�D�?��|����~��~�=zC����N��e`��$��>���atm���p�vK�����K��z��H�J��9��=��`\�",���$C��2���,�����`��������]��^y������&i������`���j���+8�����C��up\cLu����TN��C����?�v3B�aVo��������
�srU�u�����������Z�P����V�"��*#7��'����	�5�����c�'dB���B���^�&���^�Z{����N��s~wE��{UD��-�S(���Xb��Gs�K���s�4V�o��(����O{�E8L;�d�V�*x�i��?L�%����QLwD�4���@r���E�ye5��v�y���\��Uk��oiv��3u�Vws�t���J+�����>������x������c|�mN��{���x���{��l������Sr�L5�Yzk5s��zz����9�����q�/��3VVZ\E�����qy���\������1��X�Q�D�C6��o��PK�:���Mr����$����_�	���M�n[uN�t<�I98��������,[t<oO���uH�;�eK�8��CA�<:�h�`�y��Uz�e���`�&�����W��@+��P�w[Q����/����r����$���R���1�|+X��ag5�����_O��p�No[��B.�N�u�m���������6k��QZ���-��E�H!!/�u����`i��i0{y�����h�Xr}Es*������^��B�'����[=U!	�/��_��I:�r����R9}/����u��|.�VV�������^o���������V�t��P�K�V�|�sJ��F�����!��]����v#*'���+�������l8������a|�j���h4��[�>��7�	Cr710�*L����������X�k/��i��������-�JT�������w�RUL����kY>��M�����!�A���Q�����$����@��w�^���?�2�{�?J0��d��hr�c4������;c �����<K�1��]Q���7��������j�����u�w��VF?�
��@-��GIN� �; ��1���T#�h���'�|fca 7����V���Tq��7���',�-�����Sc���@q�=��
^~�������{?�����.���G}���*��#ME4���QU�-�����u�u����L�0�c4
�����
��FC`[2�������Kqv3��C;9�N�'��H/��3QO%���+!�� 6 ��n�G��/���r^
4������aX���H�t;�M�?%��?��"GU����������Jz�Y���^y��Q��U�W�
�'��J�D�H�8,�RsT�7�m���5���_������Qw��A�-lD���G�t��������l��
���./�_��+�0�o,��H�rX��x����~%��c��mu�E���|����w�����������]�]\0)���ek��K���f$���eD9N��}������hb�-��tM�����g�W�
]�d���E
l�$�C���!I��{V
+��������Sc��G��
)p��3��1�2�H��]u0D���}V '}~��������0���U���y���{��F;+T-xU����d����)��CqJ�6�y�c�N����Wi:whY��b!��>=3����b��!(+�=�m�#xG#�����l0��9�-�T��@pN������Q*>�x��M��m��+���w�����_����i�����d4|4o�~^���0���@C�t��[8�U������X������w�J���C��(��+9����!��v��=��j�T�����Y�H�W�V���7��]���*��|
�=u-����Q��c�Q~��~<�]���pH�����]�Mf���i���T-�����u��?�@#�r�'��	5��F�=�������=�Jxo8U���W�!���t�-v��'�8���'qg�#��O
]lr�[O���T�5���������g��r��rr���P�Ey��gE��
}�LK���L��t��?��_b���\[R�0��T��6����x���v�R�R��n���������8v�����x��~�\����Ov"��C`�J�WIlK�u�?=
^�GC��)%t��X�������������FxK��5����g���e��c,�q����^L���h2$sQ�����'���8����@Y������R�y�
gq2�r����>�tt���xu:����>u�'��8�bC���^�N�dP�b3VB����9{�,����
��tb��Lz$���4���-}���t��jnX����q()�ttq1�]��&0�z	�&���F�A'�t6R�RDx ��	�:�%�O:�����if�l	xs*�������7^@���%����f���o��s���!B�~a��d��|x������'s��)>���v`<8dL��dY�C���f�e�%+���Sm�)����r���eoTr�!
�4��h�N�_��.��\b~P��<a~><~��q�]�s���������3Ik2"��[�U�A��s��������=:�+��)<�w��T��s��0�����j3���_g����7�����V��nW���v����;[W(p�V�n����D�$����3���f����f��2'�n�!U�������V�����(����y.�y��`���������.=�v��kH��������?������>����k��������Cs�=����3�BP4&�	'��Fk"@NL:�x��Kn	��'��,�x�q���D'"����8\��kU�p}�\�Iq8T	�4,�R�yP�b�HA�f@��"��+DN��[s]�5{��CF���0���4^�R�rd���2��(�K�t�W�u8�w��)��I;r�r�o������P{��uF!��uK'�6Z�E�g��^��	.����&p�r
D�X/Y�����\Q���"�	�F��+q��qF<t�i��"�����V����'��|T�
���sTnr�����r�rg����R��1��Z�JZ
0���}���H��s��u��,k�4���\����K���o���?��D������\��������fH�lg?v�y���2�?�/�-���;��LO�"���

��rl\����!�~�Z��7T���������X<��������9��t6�
�������������|:W�8����O3/ZX�%�C�2�p�g�#H��a��5�@����I�.�7�Ss��>�A�� O�^�*���.W���z��c�dU����w6:���j�z$�#���^���j9'�C1����_����
Z�W����:�Qo����j3��X9s}��g|��i��n�=S��ks%Y�;C�0/^���d}�<Qo�`CI]��U?���p�� G�6��,T< P3�*EGW��fP�>�QR��{��n���t��rk���{����7�v�~�E��oeT4�po���A�_���s�i7��,��=b�9zd�B�X���.����7���^	�D�} ��	����	d��a���G�k���U��G��a�(Gd������`���I�$J�CY��h:�<bs�"O�Pe����&�uG�e�%w/K�(ww��������#��'�����������qw}]��p��:)�!E=2��X{k��+h,����#��\�QBM�#��`#�F��WYLU "�Y
�Rw�*y�ZU�[�_�!�6E%�B�H$X� #��V�q������-k=���R*�HC��e���c����X���]��Wk��K���1!�3s�����T&[]�A&{a���n'7�,�]�r���%-?|��y�\�R�"���g��(g�,WK���F����Ah����Sk5_<}e�b(4��`r��B_E��_l���
���(6��hu1���~������s���u���8^%�E6t��{>�O1�<K��0px!�Oo����>b�f"K�hp)�����}�R��]��^�*Kh�C�������r`R����m�*���g�sD[-4����o��M�c���
�)�u�N�@SV��We�
b7���`T�����UOZkbIl��%X��pfy�eh��V!�d<��]T��`	g3M&�+�����P�8�p�����|��^)n���j�'}�
��i����_����PYf���JG}!�F�I�5mm������F����yv}�n��/�+B���Q������� G_|�%��ybc�&<���I.�������{���`�pD ;Q�M��]��g������Q���#�:���y�KF�w� ���Q�����Ab�����4�F��S��k�S2:c��SE
�wF�S����Y:�A$-�h�6���%��p2���{F�#�~"6�d���+v���hW���>\f��������/������%�
w������h����}z�����)G3\�03U�w��t���J���(+a��Z�����&z6�8���s5p!bahTQ���NNy������V�"�A�<��<��L�z"C�����..��~4��p%4�P��*��:�	�1���_Tm�9P���'j���Q�%����w$>1[�j9����!lv%o �����	X$�k�
�A���
��$X!�k/���$�?l�������k����D�a
�Y�P�L�����L��������;�]����L5��4���R��X�>����E���W0!�(�W�������R�&����EP#��n�WN�IZ�Ms����
��!��d?�g;����m.g!�pE�o�9�hi��J�8���B�Uf%UV��� w�~[�X7]g9�
�Y+����H�s�g���]guZ#���u�eV�'�h�����1���\��N������CO��e��.90�d���������
��;p15����`��Dc�i`�e�VP�p�a���{I���n��H�iL&��,Q���5.��� 
?E*R����>P�����d+��G�hh"7����J�$���T=��&�L�����A���0g�L��l�	��0�s���N��l�/���V����Tq�<��L���f7�e�E�#�S�5g\���F��`�����	u���a����%�
b�ZR��a����n�
H�%�*���C�����!D@�b���4k9E<3@y�;��`w�X�h�XH�7*a	:�8#H�r�4��	Q�d�?B�)����F�������C�>A�O��t���I�f����������_q��(X���=��Ij�}���+M�ZhU���KcS���Fb�Jc6���kZV�(�P=f��'T�*{����?��(�*�>s���FQAXe���U����P�i.k�:�(S\c9��R�U�R��`�&�����v1�M4�6��O!��Y<g�u,6!���(���������G�:������Y���t���Lv�����S,{-����_�_�-�B��j��|�b~�������*�O>��F<�2�Fz�>�L����8;��nN�^>�r�8��-.���?-�A�������I�kN!|�MI� s�m2���l�M4�U��_I�
~�g#�Z�$y�n<Is+I���OW�9�u���1m�~�H4�I�����$�'R������UF����%��G<����������ug��6&m?�XXK����p`a�������������P�tRQF�L���k�+8H4By%4�b��o��+�r`��7�f�m}�nXm��*������^���	P��]I���e+�1��.�����1��8������Q��`�&�A���������T�T��82	�[��A�l������������m/��{�G�$�D�V��[�M
N�I�Z���0�����,g6��%ZN�;����9=�={
��L�3����yPO���S�����/��O�-�ZI��a�I$r)=�!�ox��+i��PMN�|C�;�.���W�?�Se�\~3[t�i�����}�Y

q]%i���
���H-[F�o/�~^
Q4�y��v;���6P�1�yAS?�B���~Q�K9M�g�u8��!��dP�l���y5Ajh���s�,� =)DB������/���IVN+_�/�)�6��B�����{
�|�,�f����0[�^}]F��e�I�1����+s��L����+����*��y���{�"B���2���i�y��R��3������>xnT���L�*�l�(�%������ft�I-�?eE�S#���(��3��^�����/NDX������32C��M����c�1�<O����x��H3�����.x�n*���'�4�~5����h��.3�Mb���+`
��LG�������%�MHr2�������X��<���D���i�R�Ii��$�=�M���I��;�)�������*�I�_L��d������:4Zc�8����$J��_c�L���j������Id}>}�Ecs���������:�]���9TH���}�Y8o<�!����rS��c(:�->��9IHp�������(��T���P\�Sd������F��\>]��A��A�����M0�.��4���@E�>�-q���F����|#�oz�C7��B%@fl:b�c���	�BL1g���jB���dRCi�e|���R�jB�LF���g�5+����[s�����oV������"�m�,�pS<K|�H������b�J��_$���	��o�?S�r

���vF��^}K�}�(����}P	6���e�~z�/9pe�7���?���B*�����-�J~�_�����8b��0�G2�����<M��������:��������e����Vj`V�U<u��m���zHo���z#s*�����{�"�O�7�����N��%~�O�/uG�CXu�3.���6����{j�B��9`���F���+�
&
1��+���5q��*'?��Z�{
�
�.F{�4��j�?:�?���}����nCJw<����	����o2FqCS[��2�&��"�z}�&yc�����T����Z��~c�)J2Hy����F�z4��x��.��G�����ek���'ow������L S���G����==�l�R�E%IC3�u*Q���JV��?�8U���v������0"~e"��q4�6+e���#�K���������N����?��1Y"�W����	����W*�%=w�t����#����QB2�f����%���M�	���
\]�UHk��lL&���6$*N�e�a�����s��K5�vh�2.=����cxS w����M�xh�Y�q�d��U+A��jn<<y����2�w&{|�u�}��WR����q����s~�<+p��x�7MWc����J���>�[�������_^����-�N��M��!���_��;��D�0��H�i��}��6��F���w���,���YXf���$��",j���/�8�I�;+�e��=}`�e�����N@���� ��N�����W�g����
��rD�AI����O����F/��y���k��,2����:	?o$�Hb�eq��BWX��'�
�$�5qZ�u3�H�v�$7_�k�4(�'i��w~�t��[��{��!s�_v�K���0���W���y�A�.OC��[�����J��sPT�U
����1�e���\�$��$\�e"}8���&H	�ag���$8]��r���(�E�VZ��-�f�j�eIs�*����e>s���Vrd�Io*ju�v�
2��;I�l0u�%�}�~2R�K���8��R�V��=zc����=j�m+���9��g=yd��am%��1��@~�9�~��)n��D<F>D��!jK2A(�d~���r5Cw�m+��e8������2������V�Eb&�2"���kM�i��f�_\
h��P���"$E:$�z��������
��$�0�Gx��njb�3bP�%vc8�"#�����+�����%��:	���e�GfC�e�����zP�B{�<3������`itBdW*���+����^��:�H���Z��1��B�T�
/�,:z|��=��FcoM2���0R�v���m�j���dO2�+�k��zb�Z���s�`+$?%�q����:��s2��QKTF���(���:#�������Y�*5��s,U�Pt�>�z�'��hl(q*�&�������tn}��M���I��BK���w#+T]�����=b��=����c;s���f�����Z�}�����#|_���G{c<��z�#u������#�����O������s�&K���>�������wI�����<���'�A5��i�������o}���:����m�+���+���<�r���k%����
�`�Q�R�yh�P�u��?8X�J�o�����]6Y4�t
��C��
a�����2"=W���g}�\N�hm;z=HqE�Mci�NF3	��Z�lu��(��b.:M����"di�&8W�2��0s7f>jLb�N/Q}�j"W����j�����>/����"���-}��7Wr�)���z�+�R]O%WV�:���`��n���SsE�\�pg&��L�b���=9�Ic���e|�-��H8������h�s�)H}�U�I�w���(��`��6������k&��������%������m����gwT�Y$=��)((�"&��o^���G��'������V�^�"�F&��6h.��5B70�PXh0S39�)��*6��t�I���z��o���	>������s�,9�Q/c��b�[9?�xot5�M�\����S�%�%
'�� E8�tO���N�����n8B-�q��wV�'=H�g��iq<#6/��'�9��Q�(5E�o��;ns�y��Q�9��1J�b{>�]�����Q������ ����,�Te9��ar�4�^���m~��h��G[�6�� ��?������r���B��@\�&~T��HD\3���f��@��A*>=�S2O��)+�g�,<�m9�W-_�W�A���.\7`�
�T����/
�X~����o�H-�Vt�o��[
iH���Vy�\>����2��Ha0L6�����`c:�nY�_!Q����&L��-�Vo.';�������p(�$?�R�K,����NO��e�t��Ws�]���DG>3� ?1������y�N�H�7���"��Bd1��y��8���@ W���l�wjm.�+o�!�:E���m6�pN�_��m��pq�0�w�RI�U���4����������D�iF�1c�O-������g���,k�F��\z��y�9���F�]���],!����.'���r�n	~^O�(�|����������s�L�jx�.*[[�f;�����7������������jE"������ ����
���8$�u�����/5^paP�4�m���y�7k���Y����P�����b�+��L��
hE3h��$hBzM�R`8`��Ulx��s�����.<�_C��;]2����E����$&x����*�0�����S
���=�f��L��;N&u()�����^{p`�n�\��_]Cl�+�G����*�����dL��L+/����"�QP�����yXi�[[���Um�n%EM-$E�5�`[��������Q:�l������p���<�+�������1D��H��%�q9_��O����AyL�u���R��?�H�����t��WI���
����q+
���w��{���d�4%x�=-0������=L�>��X�6D2$Y��/��l�����}U�yZ�������ke!���i��m��{*�J/=�q4=s�_�"n��WN�h�1<�T6F���b��M�
�=v55��X�%��J�dq�"
�7�0�|91���}D)�4�b���'��)��R�0t�h���1fi�� 	d������h~	=���fb,��5����6��:o����vdg��kV������r;�h=��W���u	X(�t��$��)�VnM`��HB�+h���V9I�������d��U�a�+I0���R�t�"����e�nI���0K��%M\S�d����j��\�D�'�~��n�fs��o�B�|Q�:]��THt1c�g�;F��m~���y%o�+��#r[��eN&�;i|90u���NO�F����������&�>��sz�
�+����R.o�D<t+�n�D��&H�{x=2����T�5KsG�o���6�E�K�_�(Y�������g'�G���2�K/���tz���;R�MZ����6WzM�%��8������~FW[����.m$�F����,�r[��������<B3��i��c�.0����65 �{%��m���X�;���2�t-���Y�u7E2���!�Y���w��#��"��9o�@�����B����O�m��u,:��5���t�1��������n�z������T�<2�*���w{��A����������m�C8���E��
Z�%$�Sp�����^_���[L��;�����~MO5��WD���kc�Zx-=,��{^L�=�zIF�zok���G�������A��FEn���>���TtxAv�D0����U�S}2���������
�
�<����a��%�cbc0�Ax�4��f�Wv-�'�0�����p�N5]ScHp�s�{F��r�j{����f��xj����P�;}��hVc��&������o�����S��C:��>����3�/i'���@wN���6�"w���ZT��Z�@�����z_|�����cb^�S?����� v���C�Ztu�����n�q��kh�f��*�V�E���[�����r��S��kv�,����u��=me%M��0�7�pK2w�	��v�����/0y���>�0e~����h�4Iv<�j(����&b|�G��6x��9����>�<�X&'�[��Gu�kd��Y����Z���Up|��$����F���
�]�)���a8��G4O��*���/���&���v�{�����(@��JB�k����fwK�������j�W��-�8���=c�����shb��T+;U5~@^vvE~�@E���9Y���nR|a�2�
B5��s
H�������/$X\��S�����|��S���*d�������%�X����I�]�`�	��Y�g�������������T`Af����JZ�$Z;`M:r��<�hS��K8����lJBJ��E�%�`e���N��������]��)�&�l������m���^��o�4IJT:�9>xu]�(���c����"��5�����P]��35
tx���?�yb����I��5��������H,:���w�LP�B������'���*|��v9���$����i
1���d:o����Q*UK���>s�K��;��R����V&� �����<jI�E%�k�)� �g:dg��e��������N�5.��IZ���r����?�Q�������J�m����l���M3�,���z��)i1�s4�<����[��������"������Y-�{cJ�M�z���w^b��9<������7&J�3�H
?ai ;P�W��P�����5�n��+��e���f�@���l�5�2&�ll�mO �%�����P�w����$Iy����/��1o�T�F�]o�ou�an�n:���#5��h#�~j���_����ek��	fC�gh�Hg���h����h�<��Xx�����W�V��j$Xf�OHM8b�����������:�e����:g����L�;������Ho������_�w��?Pi:G����s~��D���~���
���p�%��d/�H���������R�Q6!�$��������B�v�o(R�%^������*��[AP������r{/��� ����r�V%������W�
dY���$�>��8���[���n���UT���%�8�#d�"gT�G�V��"�HM���K��X���aUg�ZI5SO�
A'Q���nx���� �m�d���EU��C�la���l0�)�T�\Nb�m�Z�/�d>�|�naz���wgPI
�j�O���J���L?��-���������
Dz�;�>����Y�9U&]�T�Y�~����&�Z��w���Dn�n��n����!���f�����ezxN?@j��0��8����j'{!9Qw{=�^VF<��[���z��K�d��u���zB���@p~�f�5�/RA���^�0��"k����u�72�i@����6p�k�����QzI�S8����6-��D�����1�������E[[Q{��]��L�L+�,SO��`���/������+Xf����0��@^P�h#V�*;bk��r\���<P�-/j
9�^M�'�y��m����o��K��Qn����4�D�5f�;����[�Y���,G����t�o�8�L}�����f�
?F��{~k�y���j�|gk�uQ�>�,q�-ld~�Vk��������'���������7��������b�+���d���Bb<����
b8�t���?��(j6����L��A�r��7	��c���,�l�������NN��<�������q�t�p�	^}��e������cq��4;�����j5����|��dP���X@�6-[[�j%l4��g�����lPt$��#��R�������W&�M����/����dA�&�|����W�Gg��v�T����$��{������\���:|��xi���g���f���R<����7^v��FD}�E����Q�_v?M�EG�~��o��Yg3��3������+��m�������H:rv�NUd������\=N:���L��$v����BQm�!�H�����`��Ar3\��&�Q,����L,���$�z4������4��;���tn
��������$�d�q\����T�fk�MN�K��~�d�����l`2h��=��U�3�pr���?w�,��f�
$���7�L2��@��4�t<Es\[iJJv�te�����!hBS%�&�z~�4DK
ic�8�2����\S�{����$O�a��5�_���O�2�P��q�6W���_���[��V"I1)�~$��h�)�mv,)��X'�Q�5�����W
��`���x���qDiK�w���-3#j$������'���#�}�Y,I���J`�n4Q����F'X�n�v����(�F<�9���@oC���XB����f�[Zj0Q���W���/���7�e*�5��l��1���^��d��r�������uQb��4�5���E���Y'�����������]\�����3'�P�G��*����^��xA���_��83 {8`2���t��Ev�����]1I!Y��I6���dd��}6V��Q���	���\_/Lp���oN��6�Y��3=+����RN�2�h�'����\���{Q��9����=�G��3��wnQ����S��.I�6���-����p_��H����+MJr_���36�z�o.5x����n
(���_���j|�c���!8�@��������?�Z��\�>o�tx����!��	P�l�����������+��������h��y%(�JGr�^���\(w���*����G�uJC��	P2��"���M��F�~f�K������Yb+2��*�����sy�RW�
�)=��(5�4�N��%\�������t5)�2Azr�a�K�xE��,#�'Ei���'�a�O�B3���f��)wbE�U�z��\5��/� ��wD)��&Qm����WYx���������%o�j4����N����?��[*���AN����Agr���G�=����`bEc7��O������_E]�;�I����������y���l�7�}k��cq?�p���<�����m��O�v�^���\)?[�
���m�2�U�/x���sP�O�,����@[.k�Z���y7Jt��hj��!SCQ��������id!�O!��Y������^��{��������w{�_��?<;p�o���M��������\���#�������N�za���O���	��
G�?����9���0�<�
���p���W�G�`��5�����*�J#��e�
K,QdSx�5w��08����Jz�kO��QB@���c~�1_wx��7�9y�Y;{��������D.tw������s5t�U2A�i@���h�u��?z�9~
��;����_��P�����{?��������Y����g��:z���kM!�L�4����H(z�L���3�'	��C�� ������4FM��?::8z#T���t�����H�p�l���uE������K�I���dI�htG���rkB�>v���z������������w\���w�'�o���O0���7���'��g�'�Y�����~*~�������
B��u�f�U@��lV���6�����w��r�R���-3C(���T��Y-^�f�o�m<��5������$4�#6o��]�t�00��Ti�sk��x��
���%37��$�����vz�������:��v����������'E4��������&CO��������S3�X%"��JK�������4�E��
��Z����t]��j#��d�||f���o6�c/�b���XJK��lWI3��$����*�-�@��I�����s���*��h�i��TM����
�N)UJB4�[!�;�N�A��_-���u}
��Sl���E��=����A>����S6����
f���"�r&U�h.j~;�P2:A��������.�@�%����#������bij��.���?�n������B��p|R�>!-F�m>1�,^4��rz+m�
���V�]�D�t�=Y��h�_�u�m9���/'pwX�g���M�����<]F��\�X�9b�����f#��c�BeZ6�H6Q��`��~��zz�������M�����[f��7:�K���FJE����)����o�_���K}	��!����>}j��������d��y�7Y������oG��d��V���vs����F��~{������F	��F �-��������^�G�������]���?*'�����^<���$�&����8NO��A(�������m+�3H|�z[���x�L�i���G)�'�P��U`�o2'3�5@C�k|E���u���c_�6$��G�������no���������S��=)�_t�w'�N�.��
�-�W���O���V��I�g���{��$��g������SL�v���Kl����\�U7�(`6>�u��4w/L�6�x��+G/'���{[�7��r�����WM�GjVV-;ilbb�l�	O%����iot=L��I���bsbO�V�r�+��O^�8]��e��
�������dC�h3W���5L$����e�����-���a�����=�.�'�D���@	�*f�$
g������'��o�����U�D��H�&��a��V������=aO)�
)#+l���`������H�����	�r�������
ls!Q�Z+����z��[2/#9���fB�Z1H�@wA�>���nki��4����}���"1e�G�&IL�,�nb���j�~��@��������>w@�L������w���������������rpz��aq�$d���^�����^�J�r��.��~��'f�1�o*������3�=0rY/����?�esa��<���
���7�MXV�R����248�����N�z�5W�AxC_	s	���d�|���W�5�'�����m�����������J�a&��
�B���xbH���1
LR�?�w���l���G��N;#����8RX/�u+~����������2J��*�s���8[i6{����a"��n8,K�`�f�(K�I�)�0i��[�[Ap*�D��]�����=���s����5�"F��z�]�B6FTnY~�1�A���94D�V�����U
o�a7�,���s��������-��h��������_7����Mgl�^����z�X�����eO;�^b��%�����i�&1�f���G������_�A]����:�Xp4[��6o�
��M��3��Bzo
6/F9���f����������DN�g��YB�=OZ�_�U�a>?O>+�_� %����Jr�m}b��"#@a;��{���B������*�t���6Id<��&���[!-�W���n��,'KA��G�}���mH<�%nZ4�����7�"IE(���d%/IcF["`}���
.�����r^�S86R`j�~�7���������G��.��Y��k
c�`"I����IDq����0D��/f��8se��Dt��Ez��u��&� ���f/�z����#�T���}�
��9�1=���:�a�`E�R�7���,��Gy���m/�9�3�L"��L�|�6���I�%�p{-����]K�����BWQ��\LC����_��e~�s��\�n0����F���1���i��QO��a��c�:�y��I"l=r�z=�d��@hS�$��)1e&&����F.]�4|f��K�\�mHh+�����Y�� ���zh��b"�MT~Nb��X��]v�i�l�9����������%��zdn+�\��mG���(������i2�A9I$���i��$'���9�IV��lB@];�
W{00�I��9�i/����-��NG3�����m�e���:Kk:������
-�AHK�W����5�~$?k[��t�{�hm������	a����'�e��h�s5�@(��>����Q��6�hF�7D����Sr�tr��/�m�W���K1�l����h���o��vg��|���R��JfgN�3t����s�"������`���Fwx�����-���M�z�&\_�8p�rdmbr���S�u��o�{�R#w�{������M������*��2�%,^��u_�������D�E������d��	��$5n���
L�=���s����
:���������1/1�X}�����;T������/�8���F�'j�PH��2�&yyX�Vh�R�������$�]��y��r��m��Z^f��k���� (�/l~o�^�?>y��������K��<_������������	�������I���#]0Z��Inj�3m���1_����[9:{��0��g�����"��`�����v����������3t ����W�^S�[36���h�=n�Q�sOB~�Qo.�T0��;�?f�,*�n��1������y�x����r���3�%��Y����ee'��@i�IxU@:�IGK����$1o3��x��
'7���f	e��5��(�1����>� x(�����+sdG�
�����!�a�a���Vw�����d�W�l�=S�gzf.�&��[Yy�0��}��P*�y���k�=��m����T�7?�[���zc�3��-B��Ki����/�z*nL�w����N��j�:>|����}��8��ZK�O��0v`����},���o����pe6�J�slh=�s�p������E�m��@���}�#�e#����uY��,���Z+��w!6k��:�[d�\�ET���FtB�\��Vg���NH^.]�HE�V�x����t�bF���i/�_Sg=�!�����[y!T2�Y��~��/�kB����7����T'��=������
���Gq��M�%��Bs�a���f�#;N"K#h��F
�P����Vlnf����I��0.�54��:�+�Yl���YbO��^�c.x;J�R��`Gi��l��`A�(C���
��9V�
����es^��PM���q���iE�F�c��T�CL=��A:�E���(�nF���4�S��B#����z��']�Wd0��/����=����x�#���������#��8q�7���"s�q:��VA[��^�7%�v�,�q39�FW4#��FSs�S�V��E1yN;q4�H�u���-���x|r�{x��H-sc�q�
����89����!�`A"��;�a����Z{��$"�3��o<��3NV����^d�pr� A���5=�zQT�L�.��p�k����T�x
rKj���$yR����'�v�����26<*��}I�8���p�&�Hu�L3: p��TN^Httm�l&����d���C��?_��`G���X�F���Z�;�1������p���"�YIq��-���G��F�X��$d���e�o��_\+��4�:U�����y1#����V6LEC��w�����b9VB<&�g
��	�yd"�]��~�_�8���sc����qKt���DF��Z5���g83������fl��!b�r��2x~Ns��-���m�U�V"N.#�kt��[�r������	��L#S�QeM4E_��d�T/.uj5Atu4sTM��2@��� ��@���Du9I]����.�~e	j��)�V�p�J6�rTs��JH������!�W����])�������;�O{r��Wl��{����i�p7Zya�����?�![�m\W����J��^��/]��Gl�4��"NY�d��:cs8����C���]��tt��P>��8��s����}c����omS��
)6Y����rD���t���p�����k���5�\�� �������Z���^/H� ~��&A����^��������������K��K\���C��E��Q�S{2 ��|0�"Y��h(��%�$��m��nn��NIFU��d>�+J�A7<�������C���~�Xs����C�s3�f�[�:��6�L&�%��0���3M�?Pp��B"��I��=�EnL��f�{��B���-�Y_��99"�0�JB�eC�/
���l�������?�7�3M��}��Ln��I���@�n��Q8��7s/���A�L]�0��pB,�D�j�L�����7�e2M�L=�L�r�s��2�$������x�����\;�L�E!7^��3��	=W%�1�G/o:�sQ��^G�u"����%c�$���
����C�f�t��Z|,���n��F����	?�qG,��M8����7`�?���!��o^!������7+p�M�����O3����������c�I�@�a�{'kDUy���(��p,�_�Rsx�b�bW&�:b��6r�?�I�B3\4����4��^�Mf��������Z���!������D�������},u�z9S�q�y��KP���t��������u�v:f�WL���d�d�?����3��|��B9�D���tT�'��m�.ooo^����u�^��
Z�B%��E�%�6��������^���^����L�b�p�r�jk����;s���F�����g�O�e�����;>9����L��s{��C_��6�B23�t�;�g�����@��F�:�b7�dV�;��#+�7VMK�`�qAZ3V����Ys���cdH�9g�Pf~�_vd�e�1W��^g�l�V���7�����TE�l�K�IC_��$���������I����]�����#f_�GV�H@F���V:�0���q��]�����9sYM�s�K��\�&�l���R�+��#����O���d�N`;��Z}8���AK_y��I�
K3�U�Q^�A����]3����:�S��$ID���-�"$�6��C[��.���\��jb���������e�p��H�Df�_�=
z�a���~M���BC�3u^�.`���4�W���6��1�'N!�TX*)��e��&�r��E+�
�pH=X�VY�����l>�1��S4�kQ	�k��Gb�
)vo���f7��.$��Clh�t�3x�09K��6�/��S�~{w�m�
@�nc�����hA����6�e}��M;�f�l�*#H�k���d%B@����>���R.
_]N(%�TW�D�
N$s1TQs�����w�-��AN�@�h�"�����5��z�M�_��r��7�2O�����|"�A�<�N��Q��(S-g'�Y����7"g���x�=gc\�oJ���<^}
s�/X��8�818���,a(�x���k3C����b���/U���l�E�\�xXe(�{���^2��t��#���������Y�������g��G�����=pn��v�g���,������>��Eg��y�.����7f��n�d�E��L�d<*M�HY���{�?#A�@K�4�J(G�@mI
�����
Y��4I��tL��X��-B��� =�}���`gE�d�������v�v���T{��s��A�,����<�;�FbH�D!2>H����K��Nl��z&�i%��-�Z�1�E4���(t�'y��?-������.�������'�izY:0��7�e�,���.\�%�u�u
�n�"� ��l����b4M������m����U�y�[�E�0�`�y�L�����Q�f�%���� ���[�y�F�j�O\7�7_�@*�&\�8x[o�������C� m�m��8J7�t��~�e���"�0M*�qx��X��Z�b\���^�<5������
��`�'�44�.�����HBA�b���:v��|
���x�	����*����������4)�kJ��ZQL7��fw1+IY�K�w�FqB_������F���x.*���e��NG	�r�T4���Qvi�>doz�"���D��C*�&�i�F0gvq9�!3�	����J������������kgo������FE�j��`��
�����	<	
&�F��u��}�	m<M���NxI;��@�,����bg��������O����r��
�1����)����,�����E��l�\�zxa������Q�4���G�����cv�s^�I���'�(��)����?�#�� ���0oe��q~lw�2*s�i��ltYJNS]�^��6�||��LoJ68N��)�O)q�74��-s��"]��-��P�b/���Z�e��K��I��Px��;��, ����%/f���x)L
q���J���jhvU�����:]�I��N�3�0k��Jp��@BS�IcE��N�>�F�x��>�fT�J�e�����/Y��_����$3�I"�$�[��;��o^�S�%s3U]-�$h�.4�{2��5���_�,���+aX&p����hHO���	��*���x���j���^�����}�s��fWd��L�:�[���D�c�zm������C9y���9�,�m$���L:�2����$Ve��$V�����G���4w,����)�by:�c<��G`
`�P@����
q�xu���4n4����S$��Bmj��b��<n�D���v-��m�mHL����55#>����!"����oF�W�����Z�����wI�{e���s��/�w'�{�D��(��P����H�X�l�K*fw8�j"�$%/�����c�7���;���'�O�g��V�V�,y��!����|��%Q�V����0w�aZ��*�1?���5g�������Yrn�dW��g���b^��������7��J�`x���|������<��KQ��K�����39�����}j������^�%%����-wbT�)���!RB��lY?��9
U�!��}A�x������0g�O�)�����v/lC%���/Q���d�}'��E�=C��f��a���Y�5��I"y���aR���zi���� ����������V���S?��uN�n�7_�D
��4F���g�+�� �p��$;���{j&#q�Y����Ff����	��4R������������$���Z�d��6�`<�L(i���>1�XDL�3�A���k��S�(w
V����$&�&Z
�S�&/A��9�j��L���J#�v�HrqN�V��!� /���f�����O�������������~z��S��Z1����������l����\�Mo��vd�\&���������A�LL'��x;2S���F0�$���8���QY�����Ti\��i�f�V���5�5���k!`*�-6Rt�%G1@�+<�b*�q�K*��C:R���q������C��sz������&EJ�W�M&9;�";�R]�#u6���'�oN��q���x������'��U����y�4�5]�C7�ih�y���9��8�$y�\�a���kNn�d�]��n'>E���(����F�}�����������MO]?��nk�&KV�H$�0s�Gn��f�]j����JU��(���*�zK��N��n��B�K�EB�!d��9��������f��z���LY�d��W)8�#W�����R15q�����	����^"S��/�9���e�����|~�;M	�zF�G��
4��_e�/�A�_oZ�����h�q6�"�u����l��=P�6uoQD���R+����n��q�]JEf����2;?�2������t�,r��c�^�K����M'���U�<Y�4?�A�L���Z�����.0��Hq�A|su>8�-��6�����}cO%�+��6K��;�H~3�7���I��CC�l�2�|7FK��~r���#�|��:R�A��_s����xq �����'���"rQ�*�|�0�:+����)����n_d��&�B���W��',�
�:��)�����fK����a��������^����g����!�o���L����9�he�f���QTD�G���v��*c�=^x�^s�m����}f��,��j�����r{B�������Z%����I7[�d�I�O������eG/�u��<J+���X!z��:i���(��@H3��l�&��V��j��t�������W�������J�R;nF�u�}��.���.�������^.�\�0%��5G���r�O�h���~�[W���l&��� t�n;�����4T"$�\��6g���D��v�Et�jL����o�l}�bT�^�e7o�RJ�f�#����/Y����7��+	���?~�S����l��dO-P���K��U���;��
������������\e��p@�	�=QMW>��x�u���o�%[1����s�����_��6�,��l�����r���o�w�����������2��{����,3����LW�x\�:=�����<���&�L�k���s�W��l\3����>���F|�5S�d1>O.5����j�?m�Mv=t���F���G�8?n�:u5^�<b�Nr�e��=4�0�D'W��dO�|��m�t�nh��+�=��Z7R�nU7��W"8F�?5~���^�	g|��`]���M<<b
�\s1W���z����4�����D��������)�~��m��u���'3@��A�x�9�y��'�2Tu��oJ[��6�tuf6�� P7nO��H��wh`]��I��fp�_=��U���Ri's	����
	��q.{���Q+����Ma{2��N����)�����_��89�RMc�kPz��W��c@�7�K��=I����
i�2^n�h���rIg3K��@�E��d��`�q�����]��'9u&d=4R��I�y��T������+c�>��1��a��u>aif�fM��?��w1���k��������>�����;���-/�+�z�;cs�.f��`j�
�5K�y��E�-�q�t�A����+��(����Pt����F�u?6	���ID+���"@+���'r#73���r�hD�\n
���-8��#Kj7��_�}�;P�[C&��r�W���^)n�}�Z��n!���x�{�����H�<4*�.a.+�`~�Q�����2A]��)CM�k�Aygk��r���S���K�OtV�6@I�{~��(u��a��,C2����"�S<������]�f�8�&/J=�n�1��ui���w�qE�-��,�B�	Z�#_B���7���$����h����N��+�m
!U6�p������'�$�q��o

���Fn�{�%�m��]�*sTk����\V�����?.#
v�:��hSz�V�,����[���5^<qIX��� �&P��
[�@��|��B<���g�nuv�z���Sg�����.s;�{��%s/:�ff�}�5*W�n��K��Q�\C��I�9����LmKdT����d�����u�H�_�������=K��}�u���-om��@���#�����1�A��y~��TrB	���k�4%va��`6�"�j�H�)���d$�[$��������������C���w�u���k��En_B�4��;E���l���@��Q�J�����~�������������
C�-��6/4�s; �`��?#z��?�hbjRK���m�0=�]�%���2�v�s!^�h�����{��&���
�^�*��Q����zQf��!l|�?�4A5~�#�(��6��X-��.�����P���Q���"�XFv�91
�v��&�[(i_4�����l~/��1Y����n�
�7���$���.��N���3�k�/F�t���sf���/��$��}��~a��?������{y��x������(,�2�]�1�`����0��6���l�n��9���_��-�It�%-�X:��+�|v_�������%��lQ@L�������u�����$�56���,IIe��� 7DD�DTYR%/��.d���ofV~.�wD�����r�j�g!H)�x0
�,��?0�4���D��i%�}
A��$[�H�V�/�b1d��?'&��^�6b�Q������c��m�C8��XG��"a%�?$����QoUG�p��6gTH�����hql����J�Dt)��E���"E���.+I.���&j�KZ#^����md^X)�Q-l����/Ipd�s�5�w�F�#7�����,��L0{�H�.�&\�k��7/%@�6b���Ka$���?k��eK�S�$g����wH������gX�H�q?����0��<_v�e�9s���.D� �����^����T,i�����@����}r��'��.��X���p.��>�7��}�8�Y�����f�1�InP6�U�E������#z�D��H�%G��2�3PM����Uw�����[�����������q�����5bA����J�P���K�K��dms�N�`�M�	)�������Tmn�LH�pN���}��8�`��^��������V��B�������xp>��[�"?���qb�!1���4��y��$�$$�A4��~�r�p�U��^ro2���[f����/�'?�:9�����<=a�������@�P\�������h����D�D���Z�n�o��E	���jHv���&�������eu�K���B��h�{�m����\L�����������s�-��%����F��6�<�f54sbJ�f��� �����>��>CBFM��M�7��s���Qz�7����=��)H�� ���*��f�>/T�����u������l+�X������4
%���]0��L�,o��k2�&��5^Z:p;��t�R�Wi,yR��r�_H_����(�������1}{3e"��
�R��g����j\N�!q��
���+&�]GNzw=+V���.��
�������^���p����3��dH��s���������_�K�!QWd�w����$
�L6
ZWC=�;�[��f��������Q���H������A
��ePqj�V�������L�����v���:���i�;�5�d}T���b���|���8�.���O�:�L��#C�7vf\������wA�6�?�|�:�jI�-�K�FW&0���v��wo������U!I�%��D5���Qk0�x��dX�=�����'�v�<0�5��k�0�YV����`�a����!����;'�����3x��������_��z~������	4��x�����\a��i��hR����|��h�����I��dY��3�}��8�[����g2��~����M����(p�����o����&��J,l�4����(�h�h����G��?�
����-k�z6�gT�L7�� 8������m��t)���w���U
���4`�g�8|3�.{�CK�g��g�O
�G�T�o%\�D��
Al���$!q%�A�KG`z��d����l`���K�Sz(�&5�y+
�����������.������$L_���e#K�rP`����X:�5�:3�m�����{�V�c �K2�$�9�S]�2x�{d�r���}<W����AQ�cg��qL����Q$�x��LY$�h�?� v&���XS�|�
���Fr������_���w�����p�MA��+�%�3��H ����09{����D��W�����Yl�����f��9�8��@�R&�o1���h0��
Ta]E4s[��pq�>spM?�$�$�K��rm]n����%elH��X���� Kr*���J��
��$�W&�\����I�|R�8�$je�N��pF�������P��r��a�=�4A�,1p�'��d
���~
��A�i��x�;��l���9�����@��Q�YG �c����R���	v���A
/�)������!F��z�����Po/;���rvx0u�&61(�����HSQ��L�W���E*�V��<��D�Au���9�v�������M{&5�_�g�R�f���$�4'���[��X�A���(�x��*�z�}|!���0}��m����O��=x�����6%��6��w�C��	Pu�����zz�����\��&��]3�$�T���c�HS�N
a��N�?�\�$������V����y����N�B�d8��
�/{?���������D����S�7�����R�R���U�5���E��$a	?�P`�48�?�?Ch?������K�W�����I�(��,Su+��c:�L&^���4����\�B���]z;�������������/�H�;�\�c��3w���09�Q?,&6KSr-H�[p�
�K����&��X>�q��P1%hX��I*�����SC��	B��aE�7�gx�aR��hb��M���S��E��<���^�������k����c����i���&RMU������6����X������.%��.o�j��r���^������>W��w���1S�[;
�T`������$����d�����3��?����-�&�Q8/��Ln}�����
/��T3�0��d:�ui����]OL�B'KN>I����������0�F�&�����Ui����w��!���e�KB�[���J]��}g���)��2ll���**_&|X,tnOr-u�������8[�&�|y��4�79e1�������([;�nb)�����n%�/r/^��������;)���Y��N�("������������&�d]
�"����� Z���w�~<9���v��*A���>��-S��{<Q���q�C���b��>�6Sw���/��FrC��NB�����h^���F'�g�O�:�v���-i�s��P��)������6C�J <����W��F����7*q�^�*a�����Khh���]����e`���6���fU�+KG&tM��'P������{�aze8H.�&��Y������ �vL8���������<w �����[&�f�nt��I�m���z����������K���^�����\�+�,& �+�*�T�'����7���`f��p��&�2����*1�����r��������$Lc|��������Ws	x����{���j`h	���o4'I�e���T�M�]�|��7��Q�-�I�o���'o;o�n�q�s�J�V�,���X&��
0�����LF�
�LRMh�����S��C$��k����m-��(��t&Q�-Z�����!T�7
a�1A�U���P��&����"%S�''���:�J5�&nJT��������0����;���$���i'����l4�I��������2����4r����
����gt
��
Z�L�/5���5�d�5�s�w�����L��):��gI&������J3c6���B�����(��t�V�!��+5X��G���_LF�����pht'b4���FY�~������++G���*���d���U6�I�����������]�#u
4�K�MP��u�:��Q��p��/��i@�1�
��������hkA�TH*�������
?}���:��jab�QK�r����9K���+�<
��$�@)�Ht�^)IFU�Ut����$�vP:"�����Wcug�f������7�F^��\R%�`
���[*�V#m&GE#y��V�iM6���u��8�t<W�&����yp@s�j<��!�/����%Jb2�E�T��TT�g����������DZh-���jMpI�9�������z��X������L
�d�<x �������b���i������sa��l
VX�(/�'����p|�!�Pf����el=��S�8���������2goW��^�r��m�@h@L����{�yw����Q����aG����)�����>Q�4L&�8?RZe�T,}���������	�V�a��S����wc�+�
�1oE{��A�W+�9
7y5�S4�����
�����M<������H��l���p�������et�anK����W|i�m�aJ�e2�]e-�wI^vex��M�2I�	��R/����9wky���Ih���!�i�_mdO'GxJ-va��255�����.��&���~��Nj��M��^:����zv8��]�2�k�w���t���4	PQ��e���w�k��r�#����D����V�������VP���X�����&����6P�9��`���62\y��X���Z%^Bq���}��s�^�������K���=c�]W��Dl����o�a'��nR�����&���#Dx��m�]p�y����I�o�+Z��#e��L�|�$EsG�d�!��n�$+�Y)��	������4F��T{�v���#T��l
pMw�[�&����^�h�����n��F�r�{�������J���n����{���K�.gxc��z�S��{��������h�����S����g%P���"m ���~����������b4���i�o��v���C�^n��%Cs<f�WE�����J�}��D���� =P4qs���3#�
~��0SA,�Wc�%����Nz���.o�?�$i�9���6r�f�����M�b����J�-��h����$$�i�Yd{~&�i.����HC;��R��"�)8����!c]R��L<	r��{v�B�Y������m]�pd���<�?��{�f����l�/��H/���
�ni0���|iR]�~����C��!-�1A'C�o���8�d ��vC�WQh��^��|��/�v��7-f1�����3�b��H�����������k�ss�a�`Z������5��X'QL%@�q�J�B<;��F�������H��?��<�&;D�U����&���S;q�����o�oRb���}��L1�ob'�lv2�M2�.a��+�"��P'�A���n���fY��iv
�J_h����1p��[�R�{��p&�������z����D��Hv��V��`��E?�h�y���F�7������Vss#�� �����K��~����,�p&�c$>�����:��	L�'�Q���L`SD�����bfcH�8%����G�
��:��rV��5!.�����s�������j�����
�N��`v5L���S�L�]Q/�������:�a9����?�I/
5_�n8����v�T���Z�����q���t�6���EJ#�?�,�4�rYF��������!��WQ������0�i8����8x�^=y��|��G`�C?�Db5B�(,��w�9�R�N�{<��?S�^��z�����z����q"|x��<��8���r��?^E���B=y��9l��d>�F.����8�h�f(,�����7�D��E��������0
R�a��+�|�)�$!,d/��������P�+��?�2�k�A7�����o��!�:�����8��~/�c�
���ey�]�O}���N�O����j�l�������}
RnE���k�� 
�}�M���N���LVm�&6^��E{��#�$���������.��`�|#������ ��*?3@���LR8	���J��\����N�v��0
E��)��Dw�?�=���s*>iz���y�{9X����!�p�7���2���O����$��v��'��'��O:?������{�f_��vP��+*(W���^��������W�|������W��W+T>{��p����,X��`/L��oL��7Y�:��1#��XE&6�ftW�KR$����Sm�ps���N��E�3���\/�&��e'!8�����J
a�~o#x�=�@�3��
?��|,aEo=��?S�����y��]�!v�ite�=��K 2�����d��t�����@���(�`�&���K�9��!�/�"aIB�/��,���7!�1����&}<�������m+��$����s��L�%���a�����Y�O�w�{���<����
.SY<�L��D	��������Z���#;��E�.a�SpGb�����p�����e��v���'�,��D����;kF����=9m�H��h$�v��l�'� G�SH!}G������������L���*"$ui�,��J[�u<�~N��+�_G����i�z�@O��=�������W�%]�Mc�1!}�$��E�N@�B=�5�[�Y��OIM:�h��������1��2nZ5�WT4c�����k�[�3��;���h���r_��
<m��#��
?��fW�j$�����b�-�L����l�a�AeW*����H����FkW�3M�����aI5q����6�������lD%��\�X����g���j0
ywX�$��o��%�MJ7Uc�������8�s�5���03��E}<���F�Bb�P��I�"wP�-�B��"���m]n�ZgUW
���	�������^{���3�=�Q|�������x�/�F��r����S��1Z����+��.$���C#S��������%�f���Q�i�kQ\>D�f�wl���j/nyC�'��2�)��v��p{�����Y����V_�|�8�W��ft��2L��<�_�n�]�y����W|~>�gn��o��s�6�w
�[�����I��~��i�ZU/�\�%��I?�@�J��G�s^��qg:���;mU�0��xx�����P�c�������6�,_�^E��+[!�E�=���<�����?�))��Z)��z^�s��2Rv�L�����,���XN�8����D�A� �J���k%r�z:9���x���y�2����I���2���q6�������@������t0���Lp*�U���!53������F���yyYO�\����u'&�-�������1O�l}��J���x�S
{�#�v���T7w�P
���5����
X5�w%c���,��#��f��k+�I2J8��W��3����^1������zI�fw�����=���S1�/������+d��IW�B�{�E%^�[=��������}exw8L��	f�~�����{'
]�p����P��.��waw���������������/��+x�E[TB�����=;\ZB�g�;F�h�;�h�d��\�hWZI�26c����d�N�����d�.)����f���w���;��M���-���w��@6��c:������Gc�}�%7Z�����!��l$&r(t6�-��	��w�P�{T�!R������\��|:<k��<����m��f6�����B�N�
�����DJsl��
.���fs��=.��~���4����m��������v�iJDS�-y!��5&�9�X ��E?��uip�p�9tn����S�����ob,%��]!��,��4����F�����G���{y���7n�J���<n���m����v���V�4p������G;�����!-i��?&������bJ�����mX-kY�YmeU�Y9�K]?T��.n�3Jqp���3����|��/3�z�q�	��)�Ly%��qp���
�skMuew$�1����+����IoT{�z6�4<w-�e�f6�!�����e��� 3�����eL
����s�Y��d��Z��%t������9��3���A�%�=4�@�fBL�m�������?6��G���O��P�
q�*~����]�6!ac��)�G�i�rD�G:q�m������Ap��\9��*�%{J�\�c�;�L�a~�^�	�L'#�3lL���|%��d�
�2f�e2d�6�������I��L�ft����i^%�Z7$[B��F�4��#��<t7�.i7���LWj�d��H�=Fa?���]��y�9`�����>����S�E~^��J���=����]{���������������=����n���# ����N=����a�"��}u���u�_�������)~�~��:[O��W"�[�L)�����|	����h��M��:����5��0�!��%���
p�S\Q����Z��d�s�K���%���� ����k>�m
�3dF��s�~��9+�s7g���s&��x<l���Px��?�Nc76�/�z������O6�-�0�~���a��C
��d��[E�����f�����q���A���<bx����H�����T���"~��,w��SZ����4����k��v{�o4=y��r�Z���F�E������[T��c3�"ezR����d��HW-JNa9U]�w���h�S�&3\���1����~{�Yk����a����#p�����D����X2$�8����J&��?�M���~9~��������?T9�%�*�r
x�P ��Kw�W�i��e����Ehg�~M����d��b�lnn�@:?��S�>;�}��LM\MN=�9��s�������`R�`����P|����TI�id`�dY�{O��/�<�	y
�dG��$��L�5/	G
��#r(i-��=��&�)B�������4�|U�A�����?g���z�.J�7���g���
$Q�B���������W��fy�nQB� [�t��A���]���H"�����1q��
6OD������?,�!�dSB���h�.z����nb1D�`!�3F9���QL�8iI�Tt��Xi���F}!��'J�wT�D�8�WT0���w$F>\�0���D4��Q��y��Ro�{�{������)��C���<�c�'\(�����hyf�iZ���]�Wa�2���,/3
n�����)l����uN#�A����8�d@�����)�+C���xP�M~'�em��H�
�6�e�F�o��
�;��e�&�[���,��h!���L�40;e�L���[,�WA)X[_MjU�8��fdL^iFNd�l)�C+I��j�:tmNq�8�0dvz�g�*\@U��R5jR��h]zv�|<q|��\	5�D!K�.w�G�v%nQ����O=��R,C�We�O�wO�n�����d��
Qq�B���rY���|��>��)��^o:�����g��9�,S<8�7w5�^-�0����)�:�G���U��{����������L����b�����������83!�j�y��i]��?�qg�%�������k��
S���0 0I;����g��[�����-��t�Q�qc^ ;+���m����J�����^���$��}G��3���)��R�7<D[��2(����I�y�*{[�TT
�s��q�����
�Z����]
����a�-�e�&���Cl�W���P��T��>�����hN���C>%�e�o)15��>�5��!���H
.�Q�������sjGj�	~����*A�#�[��`��/������)�C���S{��9�W����_��A�f�0��Z����I���C&(����$%�%�5�
���G5�������(<2�xQo(4A/�_��tI��nZ���0&����C�q��
��:T��r��P�E�jI�.��*�q�8Z�b�V�hXz��
�����k�C�����N����6(���������XS5��B�"���-QI�La��*;]z��qPNe����?D1���e��c�=����+R8Y3&E��'ZR;\lq?f���-�9G�@�0U):i�}����UF@p#L������R0M"i�T^I3���>��a����H�K��*c���.��$3��O�X�9��l�Bj�q]��P�_"#��=�"���]��Krry`����]eWwPc�+������3|w!p)���2����~����(��7�x��Q�1!�7�CW�+�f���t��O���d��9�W�)/5R>�
r���B�Q60�`����%���@}h�e/}9�(��6�:��`�b7�[�����m�5�o��d�:Q6V���'V��?�=�M5��(������>^�z��N;�i_�yC��NUj^)����������|_��&(:4���[�J����k�'m�?�N���Wp�7N��[���FC4��#'�K�1�kU�PM*��#�q�!q�7y�T)]�)�P�l����&2����� \�G�p@N���9��\|idL�?����c`8�B7���E��t��NM���D���Kkw���1����%�u�*��.b�u$'�b���`���jS���6�3��2Z��a[���Z��G;���G�u�J�iW/��,�2�W�v��K��=qO��u���<Q�t�-����r>j��v���`f��$�l����.��`i��,���I����������y����}����>��C&(x ��H���E�a��y3�Vy�PxI�M�@�e�Z��'H%���,U"��|�q)ru/���^��P.���������V�Di�J=h��(�+�JY�8V���!p������"�7�9\ux
 Fbh�U8���f"���L0�G���0��F�
�LLq���I�sP�p��\�'X
���lTxa0F��"a��������P�Vp��"����9��zqn����^�<�����s�������]]���h�������Dl0�;��+����%�N�n�C_haP*��m�����Z�\j~+��w�p�QD��*�+����	��t:���5p�����4~�~G�����+gC������� ���F*uYN����#�0���n����6�������dp�N"fAp��� �!T�d���R��A[P�f��g���!���A�]��m��s���������
��K.��zmCq
��4nLQp>�+��UP�E��5V
�X�/�T��������,c��)N�i�A�������(|A_����O �J�NQQ$w��J|�[V���yI�k��=Xk���** BM���i�VC��K6]spU��K�iMN��:���4.�Q&��9����}op{���w�h�u���Y�Z��P�K3P���_��v"$�|���@)�Y����@��e���Y��j������QMk�
��U�����`�t��$��y�v��{9H6��V�c�62��Vn��a�D��#���z�A5k�1{�H�f,�+B��#�
b�7�X�r>X���Px��b��2� �����@�.r*�<�Ty�
��m�w[���A�G���qr��sl���a'oK�6������y��2��DU�1Q��F.��0��	x���H{fkm�������A�{�|/�������J��,��X#��u�H�K��X}X�������F���zf���
���:�Jt��r�FFSu;���JL{r�GhPE�Y��];{>�����rBU;�'}r�K1��
���,�M�M=vZ�`E����7��m5����������'iL�n\�����Q���8o����EO�"G~��N<uP9��4X|i��BO�h�+'�
�����	��<a����J5�V�����w���l�@�Z����]����zXA��eF�h���5�Z��b!��53���!��s1�* `I�20�z2��NV��m&�r��n_R�g?.�Z�*���Z3���%~:����	�f��!�8�e�g��"p2�h�9�}U���[��� ������	{��i0|�R��T��z�al�����-k�\vK���������\P����m2�;O�)��k't�.(�LFe�6�1�$�0���:B��'���6�w�|=I������G�8����T&��!�Bs���tf��)b
`�@�D
��P��+�Q(��Ky�����N���f/�Z��-�
���b ��	<� ��������d[�Y'�6��.<X:��������: ���@Go~L�Q��B�����E�\��@�HbJ���{u���Hq9��M[���e1c]�Tic��������9�6p,�p�%���8�Y�:��?�Y�G���l9��Nm�:�P�5<��	������mDazO
Y�.��,��E�-���jZk5�������u�.��}X&�A��SC�s����ww�&���	��-����
�b��,�DR�b �*��~��I��+���$��Y	1]g�H���E����T�����U���TD*l��|��g����N�&7����.�PJ;1W����\���S���Se^Ar]�5��6����o�&��b�?I������3L�=��My(�(|�����G�th^{��-)��n.��EKJ�aK�J��[��i<vb�q ���PGj�c���g��kz�7�W�u���&��w�(�o�;��F�[	-h��7�f\-P�I��hS-#�6 �R����0U������3<#���Mf�at"�f�
���K���b,.�\pBB�!J������rm�D�TwC�d����a8<�������kK~__`����Y��a<�Q�5��#z�����,�s���+�K(�Tw��
)9K����s�3t�`��8|��U��9-��d,�?���S��)2`�
	��n��k���.�k�W���oY�K�J�Y�/t� lv�yLm��u��dS���5Gp
�N��.�>Z5g�sp^�]
�����8��Y��Y&�e�]�b���8h��	iL�����CMo�r;�����
���JN��->�dC"�N�/��^X�����r���]����t���hr
h���F��tsu�P2-U��Q��I���Ubq���v�����������{Hw9%�2���6�?�&:2&���v����D�Vr���E�9�7���^L��	i)=������1�b���b���Yl�]���Y�\VA'
F��3x@l��O]�%~�.�8l�#r�J������5�W5���s@yk����$Zj�^���|���Q�#��a���8��m��C�^����_����<�$1�K�$#���t��;����"$.�Q���=d4'1�����dg�H�����L�(�T�M�b��nWn����&T���d�{95B0X�����AJ���J�������6�����'P��j����M��������F�OiC�R�#���]Ho����
�T��:� ���W �!M&-ml����S�B-�<��#��D<3Ax���xp$�W8����jx��>������P\:��W#�Lu�k���@�����6����6�m�Ox�O���MC��1��$�����!���wI��9�.:���l��]��	�+��\���hd4OK�����_j���_�
Q�!�-�L 9�e��$Z���~�!����`"���b�B���� ��N�Yc#<�����P�C�%� ����� |��)����b����)��g�i@��\6�U��p#����G=�,������i�F@r�gA��M���s�R�f�G2����D>����Q���]:��\����6\F,�UKq�R^fc�[R�6pMx�]m��h��;-�-VjV�����N�������e)���/�#S�����oK)g����VS�����A��������u�P���K�{��9�J�����i�#��+h��@���PboQ2
e�����)�� M?�<����leHqe�#�Hp����LsIWx=�1gSD=���K
�: l��(������C��BnT�����8LNO����f!�~��"I�6D����n>�������A����#��7�o
7�Mv��p��N��}�����rw����gb���	3�V6�
y����GV3�>�����H����S��,�>`����t�{��1����a���|U�6��,�)V�������K�`s�)����p���������.�,1u��"��s���j3���Xp�F�8'j�$�1���{�����j�=�M���.}�z�8��59���x]���K����A�
4����:s�B�>i���Q%�i)��=r���}}�S������ ��Tb���&�NK��I� ���N�5��
s���c)�c�s5GBp��Y�#�
meK�8B6��6�����-���<��b�g\YrE�P:�E�kL�f���~5�;G���'>��a��w= zhz�����:O����`����
d�eew�b��L���e�%hO9������d��#�����!����	�Z�J���Z�\�����8����3j�-c�!j�y����]g�� D�����/|]�
��%�A�o������R�K��k������Z{=������A��k���X;�t�?>����}4���]/�Fk�f����~�u��.Wm������~�V�6���D�~��O:�Rb.�z(�J�({�P8{&,����Q}rr�9`B�z�W�4�8^	�5��J��"�����\c��~fp�|�>��T(k2R����&��l��0=��1��<�*����yM~1aZ �x���KA�86`���������[���`w�aQ��,����'1v��|a�cf�M
m���������X��w�����\Pt�=����t��QD���p���Pv!N0x�������&���Ub��.�����������o<���V��'�-� h^��Y+8�h����iu�	>KN����O#m���M�F.��Br	����i����1�D��)��Pf�d�X��ek�T�A��+\EW�vo��k��T�(*�p�pDE2K�eC���Y�o0�xGn�C?�DB9��{�����9�J�=T��3|W����o������_%K.�E'��M����nj=Iy;�L �:�r��R0�k�M{.&����&��JDB�Q�v�AwDY�YO���=�Y�D����K����&�N����;������m�>�q�>T�{��/~.��~�F��!P��e��;����w�Sr�|S��$��4�����(yi8���g�V�����',����E��H��fwW�M�jC���G�b�i�l���x�Q&�`�+tX���y!��%���aNa�X�w:���F�J&�D^_� hFh��n@0N����tSc!��cw���\a�7��>��T-qPh?$d{>qIw��D���k~������,/��
t�$P��aA��2���fYAk*�lw��.��/�#T��u�G����k����;!���7�d������� ��?B���]{w�l���6YW���A��x�J�FKao�\�H:Lv,��|�3���������c���MC[�lH.��/��[�����f2�T�Bz9VO)�'�����Su��.6�;�o��?9�����>H����J���L[�y���1��y��I����z�P5�D���x`P-f~���`�����z�E5�]���1E����j{����-��M�F��J��C�<\I����j�-�1F9m�O��\3�%�����$�Mi6[�}mT@}[�@�n���� iE��2�q	��N��*I�O��jMu1@4�;���NU��1�%^����WP�(����V����-V�n'{��9��*�������3�G�ep�^e�����:�)����cx�����!����q����P�Tzg�0}f=��P|yc�#�����(�����k=�8��)_QP��^��&�>
�H$�����o�M^	rG	��n���D�
8/��c�Z��G�J��=��������S��R�`��=lJ����L�hx*��{P���e3k()H4���%
"���b�<�[6��D���+��%f�t# ��93|�zl|����!��G9��^6LJn����'��	zQ��'H�2A�Nv��L�9�M��&D��H���j�s���Hp���s�Qk��M!0U�a���`�r�f�&���p��rw��cd����0��el�~v,�c����7\����b�I���@��P�D����kIux�	��H�4v$����UA��i
�p$�t2�����*�vj���Uo"e��i@������Y�([s�m�@+�C����R��E��?D�8�����^?�
������PW����ZXC��[h2���Po�����B'`������`N��T�����6j�-������L���#�dH�3�E����$ ��Y��J7�u�dK������H[L���
��A�a�������1RX�<�>6��`)�8�����W�x���?\*����v}�HQpE� Jl�[`��~��)�Aa�}�V�������SrJq�q	5�"j��j�7�<xU��C�qF�B�����zst	k0k�	G�t2�A����������F��zZ�:��R�������l�)"����G=t8J����S�`^�;���[���
M����j����e�@���Au�����l��d
A���\�mz��I�����HA�ImR�@�8���-�����J�"!u2�+�B||+R�D�6��weW�#��X���(��}�!.��_�*��\X-����d
�eH�����R)H'G�a�E�QI��C��
��N��������1��W�.>(;�t�*�8v��~�lNe;G��y���t����m�i�wf>6�[��w�����8M�q�q��hfM��[r���C�C�_�e�R�p����mk����k(%����,^0`�"���A�^F���>&b���a� -
�K>�~g�Z`��0/���!w�t�)�v���
�.nS%�/�v������il=W���6��F!�r�E2��Rf&wo������O�����UyQ��N/���������6�N��4r�i���rO�GxAtI�)���ue��{X���UH�&%��C�����J�kc�J�����%�j;�b��8�6�����\�S�2��i.[�MY��[�G��_KJ=��h\�W<u���Dm�N�NS�}6�_T5_�Oz�o��z�<�)f��n{��~d���������-\���K�Q*����*�W��p�����_�AT8�?����$�:w�@�A��Y�Gd1 ��)��I�8qiq�\����SR6��O��7:|�\�;l��������[#Et��-z��k����faF����\XM�o�-���lm��f�f��.0$,��o��J��7������ G��+k�Z�����^:7*��4�7?��?��0+�%Fa��5���W����������R��`/��[�y�f�+�/�����:�&2p�14��E��P�*u0���,PL��:�WSk��:
���*
^_�����~9��o�'��Q6L����y���z����4�I�"�F	���]���k�Rx��`<���S%G����!�ZX�A\�c��
�2�R�V�5`�� J��@yR
ZO��{���:��������o�rJ�MkMG��bwwo}�te����}qP%x��X�/�)C���E�}�]X��x�
���Q���K�o������������;g����_�i�)
�E��Bzm�T��C����-��%���69��������i����u�i4V���x�@}@���?�d��5Z�������.������X"�C{���ZN9�C���I�c�����S�w5q����������������pl)T�����b������HV�g�&P�(���p�W��_�m�J����{�Ch�M	����D��?Ma�1��Ox�g�X�t�\��b��E�b���
f�-q�|�
�sc��n����N������7���^P���_��(�����0Y�X��3���8&q���)L��-&-��Ny��d<d����bY�>f�E�&y�:�?���T����|�����8��"� �2%����.�]09n�����%���_N���Bw>~�?������������}p������/�i% �����l"�lb��^�h��(dm�6�9���bM%����h8��:�_�(�����b�+���q9�q��9��Y��2��^�
!��W����>��b_N����G���	Z��r�kO�oU��z���71�gw�
dm�%��ps�0��.����*8ZG�����}h%�P��t��*M�%�ww+����~T7T�'�j/���~��>���q<���v��{/.�
�,�kz�|�o'�����g������~�?�Y���f���
���%����C0���I�K�W��m�Q[���M��c���6h��|d8\��7�	�}���w.��W	/������R�3n�x��������&����F�y\A���,Ag�!j����$\j3�����X^'��q��!��,����9������(a^�zubtKD#���ws��+�5�*7�Q7pK���W)88��/�Q��\*���_���b<�"=&���x���NZ�.m(i]��Bcm�,���y��D>���}_�!���Z���!�%���%(�w����������X �!�:��)#�lA
��P;��q!e������{wZX#��+�A4P*wm���s�}��f��Wg��%�@Ial��bn��}}������r��By+R��N�)AB��)l������SPa���o`!
+(��������s��`��#.�.�oHT6�E��W�n�u�[�
o�
�����hx/R���hS/��/���Z�B�b�#�	���(�h�J:�_�2)a���=a>���B�(�$��6	~�$	�Y��9XK��?���4XWCJ?��"�C������E����p�����Gu�e��>R#����rq����&���������&�#�%���Cg��W�B��������5��.�]�_��w��>�fcM��'{bM�&T��7���(�;�aL/�G��Gg�<r]8L!�&.��,�/������Y�XO���p��q��`):f�W��C���)vK�t ��bt�r&u�D��c���.ZXB1���C5gR���`IP���g���`��X$�`����^�Q(D�5�>��q9=+�a���[�T�
h+$-��LFr���PW��f�V��h�)Yw�� 1��5b���#��7���}�lsh�4��S9�1~�t����_�3k>�4���<��d/%���'�o�}\�N�lc�eb�F�6�Q�� ����0�o!����[q�0��KS�7�$�����Rmx���Y
���S~>X�j����?y:�lM`�L�,�~A������j�L����;����J���?TJ�%�E�ZAaL��*!h�F�$���=���	�$��L:��nf�\L��f�N�",����,Y���yK]v_�l^`�����\m
J1n�r��
���.����\�����c��x#%����lQ?Yd��7k����O��{�-���e���9���������F������m�>��
�=7m�>�`B?�v�&,-jL���L�Dx�T�6��L�V��s=��5��wq�V�6�����Qt��1��r�!��
w�����|�J���q�}���U6����Q���U�y^||,u!\���+����N���0��;�lK��&�{�M����o��!��'%���SNEf�O8u�����]����5	�s�R!�|P�;�K6c���1���O�I���������U���>�l�[yi+G��{i�/#}���"���"���:+��i�����j���Y��1"��N	���m��Rz7C�"vR�p��F��Flc����<��F���('B4����}N5e"t�1�#>D�uB��z-��Bm��i�jA��B���0#L���qN�����@�'C��6�'9�{'t�=�s��v/�c)|3��g~��<F3�yH~�G���H��^>j�����Z�����������|*���b.b=32$�pK������!���{5t��F*�W����i4��7���m�1S�ce��T��~�������%gN*-L<6����gN��F��9(+5�p��~_�@&���">(w)CSvg9�t�!�b���������c���i�dU��X��TNn :�]$� ��D�G�K5	�Xd�����Gr�<��}�r��}p
T��_Z���9����M��M)Z��C��a�(.������0� ��4��1����b�@tG����O���X�Jx���e�����W����WM

�O�*?D�rG���W�����]�48�i���`��SL���%D��6�8����91 %�r%9S���{���4�6"��0r��Q��J>f�Kr� �dj" 61f������9�]k�C�9�Ksr%Tg$�����^rv�sz�@����^�Y�����=k<&a�}z���I�����{'�������Uq����K�1����^����3�p���yA��&c)o����Z^��?�w�{���f��%��<������mzL�Zy���y;5B�_�g6��'����*^eM�GM%�h�{;g;�;��7po�K�����������d��t/*�|����Aa�|�����Z�:�����:6b�1�c���1Q8I��5%����R����;��w���`����zOw�x����}�{���y���������c)�eZ�����v_&�S<�d�^�@���7hq�F�u���$�6�W�����S����-�M\�������7������������{���YZ��_�F%,�4�)�����?q3~^�������T���~q�x-��k��f���7���9I�-0y�)S��)y�`���F�(�xX�/$d{��T;���T(��m���IiI0��~C�����.!��Sa�]6��G~�K.�MOs-7��2����9^��3�?�~19���j�K�������;��A�q^dc��5I	b��l�*a;����V�{���yL�y��������]�%�|����-'�2KG��p��������]+���6^���������U�d�00�����J��x������-�k5�����Aw���?:�8g����L���a}�v8�A��
}��Y=��*I$���A���'f<?L\�8v�a*��W4�%��>��@��b���lVQ��:�z2��(���w��C��>�'����9�rQ0"���B
R@�[��(�*������KwG{ ��TX�4f&����5�����N��������A�����-S���U���^A��)`FF��������d����
�a�C���oY��U9�zQ�������1��s
#6w���_T���/�#�:�����P��P�DI�u�kcP�Q������`
�n��d���cr���p��������S��L�G#.v�)������xyde��gv&��,��IZm�Qw<|�@��nG�"�@�J��5�+m��0��0>�%�k�a-������Z��9��i�^�!����0��F,qkK��C�)p�y.F�����N)���.����t��<���FH(�B����N����HPp���!^�}z����.}���v�2q���M��n���3�'�*���V
Q����y����d����Y�=����5*�������7]kr�2O`��B#��,��O���;���=�h�����'�����%�g�;5];X���%���5�:����������=��91��a9���j�H��=K�N��l����(5��CM[<���Ha#OLt�CTyr^��@��&`-��{��are�_��hm���p�x����5�����W���k&5S���=y'�8HA���;�TK%�d��{
�(kR�R{SM����C|�4��_����x���^a�3��������M�t'#�;�2j?�'��g9�^1M#&�0��-p:�
7��(q���0G���X6���oL�ZF�s����8�9���Z��a]Cd�L6���Z_���*��E�����qS���W��9..x'Mx.C%�f��nTB�U-���(4������5�p�C����>���#=OU����hU2{���u�w�/#gOt��v����[�X����
��g����KO��qNFd9��m��H�Zi/�WI�&�D��4���t��� �BG_
G��80P��%G���Z�g�X���NSo���3�`5L�B��y����&^��m<�mEC���[�f��^���;Ki�%��R�����*��
V�����d����s������0�=;�����4}3A�H��n���_�i9n��O��`�������X3������q2�O@Lk���pl�����PgWlT�sS��g�7�^Y�����R����2B/�o�h0��H�S�/(#�>�7Fm<�����1��:%(�o�H��+�V������+��m�nH��QLF��di�����n/����?�F%�,�9�E6qN���j9l�,�R{I����GY����4��<dV��q�jdfk��4���S�)��������aq��j��Y
c(�������Z�m�)��:g91�����>=�9�t�\�K�r2E�[��A`�h]F�-�H�_8�>=�aID�B	Q�H�;<�O+<�7{�g3����(�0�	C�RwZ��PZt���^��|@�XU��H8��vg	P��Yx�s^���w�4�a�!�� i��b�/>�s^�����M��)
��IyM���3�E�n.�NU�����<%{~'%���������S��No�"ok�i,w�G��r]$e�Q^�?�!=Jv��F���
�0N�����e�P�%�� ��gja�+����P��Ha�&��7%�R����V0^�Li�TXtq�zCGD�h�-��t�[�R�=�br����%��Q��d~
���'���]S<-�X�:T�fG�5c'��c��%\q���a�"�����6(���6l���x"]����V�Y%��-��N�����>r��?�n�J�N���tV�s)��Q^T�M��_�[,�xTr�R)7Y7���q����S,�N��>z @)�N�!���a��:AM���+��UB}�i�uj9wZ[�����7w����DK���PlQ\/���D���������9�/��PT���k_�+%��TFS
qH+$�V��Q�e����y�r��"�4�O��K���� ��(��6s-��*�������.�C�9\m���\�:��|�>A�&�H��-�6ZZ:��N?@��H't����G�g�O�i�^^���<�x����\����S��B��S#]xo�)[�=/ ^�:���}���z�1�a�N����_tH�3�m�<;���������^���H��Z��~�����x���;���@���O�[�����v)?�R��������7�����o�$"Gx�Jez�DM\��5�:_�T��-�$��s�������Jg�����fu���$�m?�K�P��(��:
���������5L~�fBR��������*�����%C�O#���*����
���V��8�s���
4?)�����v(�����R���h�9��n�������bZ��h+��&6'�;*j;��'}���i�g5��Cqm]uCvA���I������3HD��&���� ��x����D���(�1�n�~
��X����UL��hAS��O��G���V!J��4efn�`q"�*ok�%���n�a��b�����\�/���/��|���D���o��N���G8���t���]���L�j�Tu}��O_lQ�>���g��l�G[.�PA��`q�>7��`)�Q&e6(3�|Q~$�C^W��D�$H��3��f�(�R��.Z	�/�~Z���z�}p"�q��9�mE�^�),
-h��.D��$�*�&��}����k ��_��'#����8�.e}@�&��W��e��{�H^�An�?Syf�9��Vg��v-5~���;�A#8��>��{Q5Ux8��P�@�v4Jo���a q�G��`����*�� B��/�\�$HI���9jm�/�A�a��UR�V�b���@���-I�oq��*M9M�H=���v���,��iN�C����N{hb��wAs��G��/�V�����:S������r����}pV2b��J���HKj(�7���������n��*+Go����O�����8*��F��?�����r�0����c��k2���t���9|�&xp���f ��Ou����	{��
�~qNy��4��t�J�	����O��p�?&nQF@8��\��Dr�=��O�uf��"ZE,���t���l{_��+�d�/�c�k�����B��c����]�s�
�L];��y������.��c��T,a��k������\����V	&+�n:8�vqx��`w��}������~������3�c�5������^�3���	��H������!�3!�:N/^Bx0�#����r{<l|;}���Xw��uGs�����t��9�5�3�w�r��+�z��G>nx8-�O��[���+���J���Z�aZ��F�5��u�@H�H���qn"�F�
��{�|��J�a�28�r��'
xVm�r)@�����y%��aU6��Cq,�H�H��9:
�l�CN�~6�_��0:�v� ��X��k�����M��?���
�WW1l�Oh4�����9��W�������`�Gzo&�94�NABI��-7t~��E�������cB�1+�7Q����	��f�h0?�����41��\: ��n�����pH	���S~V�bX3�u�n����o�qB�%��\��cq����JT��J��Y�����[���=�/*��BRw�M�Lr	4�7`�W��U��k��4�X2j�>7�<���mi���p,�I?��d�_c[��+���]����5�i�"��<����Z1|e�bh@�MW��4 <�'�M_�X����p������x'-K��HS'��B�
���c�����>�2Y���.�-9�:�*~WiN��/��{B�����
>���
��W�m-)���R"�JX]����mdL=�� 5!��|��������b�rlS&�*�O�< �1Ru�!����NK1u�3r�sG���p) �I�v� �-���k�7	Y���c2f�]|�������Q[$�h�I���|�����_��'d���������L�r��$�hI���U�u`��VH�0��^��XG����b\(���F�
��E�u�G.�y��Q���-��Q��Gz�!������\[��������:�O� �>��R�ri������&�EZ/}�a������gO�,�f7������<��6��kkk�z/���!q��������=Y�hn$������%���xC~W�8]��;�;������t4z"�P#JB�1�#��@��� +1�N#U%�F�-��6-��d4,8��\��^�����~�aA�@�$�+��:0����Omt�/���vD�G�r��&�Kn����"�8.���[jI'd��H�!P �'<��������W��U�`l��Db@�yGi+��$BQy��g
$�|�yw�>v-��_yh��@#3~m�7q��l@�f=/���C��$8{�u�o;�g-�=�#%�Y�����a�;~n�����Cw�����E�)����Q5�������	$�Ze*��Kx���/C�~������Q���S�
~[���@!c'�iC,f��zE\��&K��U��4��@���M��d���j�v�t�w��@,�y���HQ��GD��	�����(���@��i^:��#����J�j�h�@O�/m�S�E����Q�����[�B�r��`����n����.�^B���v�E�Hb����kh�T5��m�Q�']P8� �e�
`"�%�0*�A��{�W���aI?��r�V�X�=��]��
�"��G��2��`��������"�������][�t�>u�<N�#V�I��,U�_�4Sr�{VjY�A>Dd�I[p�1�0���nY�M����n;"�6�9P�����s��������9�{2�����v(�#uKl�Q1 !�l��n}"l���XF�{zB��>�GcH}��=	��K�)���-�d�k��z�;ywh����X`���m��T�f\���Rs�pT\`��WH.�2�0��_xL�+ZE�dJ��WwO�2��RZ���mB�����?U��J�)p��1`��z�@����U�OG���Gf7��������N�O�I+�A��������+���������I�e|O_e������0��0�����	���I*A�5@J���^��_���1�L��j���&����4��K�k����4
&_����y��2wWZ�)�_��+���W�T.��`�r�_c\0Oz�s��.� K��[��{y�n�,S5�,��|�q�����W�y�S!��}H��Wx1RAc�:�n�!in,��>�i_�
�1m�R������h��f"��s�u��E�����F���,��EP0-Z�ujx��s��f�kQV�J�/��6@�k��b!�2���0EQ�c�Ij�D2�wJ|�s�n��@�:�G�\�J����g�@�.zzj`bg<��{FY�#'��qsz�]���@g�(��"d��	�P���v�3'x��oA���~>0�0�����gn�[>R�;������x��/j�u���	���nf���>|1J����$���Z}lU�Q������O�{�{rf:H~�?������yO�?U���O���2�=W����o�����>5����rv���C[b$���w{?�/���(S���H���;�k6*���>�Y$���s�����Ov,@t����.����y�n�r�����7���v�~������l��O�o?Ex2�]��	,��|�&�s�d��L�J��~��@G�'G\HT����&���b�8��A�������#T��x��R,mh�u����`����@�y1xP�Q�S����v�Yy�q4�=p�����I�0�T��%=�J��_9���,{�mGEk���h#t�$�&2��R��lT����	D&L
e�[6`�t��\A���IIi> ��������M0X���`��V���E�1���Y�q%~�����T�U#�A0m��O���E�%�u������b58�����a���<�&�ge�J�bR2�gN%������+R��;Z�0-�c%�j$C\^ma�(M��d9H|��52�i�)R �n�l�����t��������T��"���"�Q�4�Fw%����Z��<i&�r��&��E�C]IjR��r�=�����;�_,��:�x�,]����I
�7F����C�G������Sy[�#Y�._�_c.X|?�;i��/��������-���g��
�����I������
+=G��n_��og�%|�K�r�L�����A����������p`���������p���G~����3��`�P<k���y/x�����A�;�'������:Oa]�RD��_.3K���IW/
�an�V�&C�9��5�+���a�f�����=��&d%��Kr''����+�>�nOJ��bCLi"��*G6��\����H�&��6���P
��.LkfI>J��)���q�G�W�E%���D[
�����
>�e�xY����<���f�n��n�z������).�d`��ho�!u\�{G���)#*�.�r|�O��w�,FnJ@��.
C&�����';b���x2j����w+�T!��]����'���So�x�Q�V���	�J|��E��AE{��z����=�@�DC����g��S��l����rS�qK�"�8u��pN�H�K�����D��.o"�+����c���B��; �pBO6<�0���H1��8��E����m�v|g�E���l�����sc��Pxr�q|����A�{�E(&��S�(�@�"4Z���.[��>
H��l���c�n
�0}�i�
<���u�[K�x	�%Y��p2,�#n#{YAP.K���[|�������H�W+�{�j:iE�k��[CR0�NI��h3s�����>�!/4�_������S��C�nP�sQ8���������� �Di�k��&����1��n��)u)d�y�M����� )t+>f���|��� �Fs����1A��I���+n*���(� Z��y��r�*�m�=����|g�j|��E�����@�Hw����������)��������#�	��c��������kR�=VL��[+�(6Kh�{��,)�����F�����C��n�B"���#�2\C
5Ki�����\~;9y�=�"g`��l16���iBvI���������G��������cq���������>�Nz�C����������%
"Q?�2�t,�3
*&u5!��(��}����c�^��'m^r�{�Nt`���;r�2��~�\�|���;9�x)��_%r��qC��#���F��(YS!�������Y��j�Dx=5r�Y�B��Al���bB�.DJ!C������E��F/��G>x�B���/1:�[�1:o��jN���y\���9�<D><��,�V�Q�y�g������f1b��%t=@���(��q�q�UO9��cl���A������|�Mf$M����"xQ��~
Kw6:�9��
S����?���������
g	���$���0�^�=��>�G�/�7�'�H���^eyR���~D*�����5�Wt�u�%��4�����KX����mt6�4�ufR�<�����������t���z������$cV����$��2�c=9�zxg��h~���������H�g�����z�=�>:�������H���W�f���!%�O��!�*�Z5���{T�\"
��6����5Y����%���_�i�6f�<�������NB��
�����<����4M��3C���:��z$�0��
r
,���6����������K�0����luZ��l,���*�l��F�VQ��������sxx��h�{�ow>��?!l��6Gg3}���@��[����+>����-�^�e�*	b��6v�>�_���Gu��c���
�I��K(>��x���9�H|���aUV�k~f}mn�`�.ur����DK"b�=�*����W<�5���VqpR8�I����`�u���Z��Z�r���Q�m��=�U��86����[Y]D���`�!}6Dx�f ��,����T5]��� D��h1Iv�#cO�v�xR�^f�����-T��V}1)���mP�Q���EOZ`vQxX������S����2
��:�)�����O�K�Z���(��<���O��=�h��	�����;'$����4u�^���S�#��8F�b��v�������wvas�:�[t���T���
���N�(<@��P}��e�6Q�S���Nc� �l�%C���Db�#O>Z�)�`-�nKK�2!*�]-���|����,���� ���@�w6H�q�7�^V��%�
�5����"��?�2y���E����9�����
%v���,'�|��xA�p8=tBRt��5m��<�d��/�p�D]���/��4��W�!J��1��p�4�8n��d���KH._��_s���
Y�AM���Kr��lf�F��R�M*��.��iK`a����i�a4%IBv���O���1��������fD����6��g�������=����%�a_����R��'o��
�c����:��Gp����49�^
+���1>���W��N����U��LBT%�����z/MN1��K�?�lN��
�~�[4v�t����S���!��fRFX:��G���t�
)��� �(����t���y�����ZJ�R
�Rg�9�vUG/|OIE*�:�(�b�q���V��J����]%g�C��4��h�y��X����s�P����F'��h��{�i.������R�zMf���Ux�������E�d��{�#'bD�G���5+�2<��u�MDX��lgu�)���bA*���"yL�R��2�(����SS���MC?�'����wx��y?Wd�1Q0�<�";�3s�K���F����E����}�}��H7�!o�.�3����,A������q06���<j�1���76A���Lag�?�����N�<;�$�i��Sc������A)�C��Yj�
KN���a�:d��l<xy�z2�����n8D�xP/E�����+M��W�/Y�@HC��=����6����?�o
�eBz���`�P\S�OviHQCW$i�������?&{��S��p7
����*z�&S!b` �Z+�(��J<`^������
G�a�����!�x�X��NQ5�?`\.>�-{�}��y�����G+I����+��������
�5����k�(��Z�,8�W|�S���X�l�����'�g���6����^j����)��2A�
���w��T91k�C�8���WF�]�e�@V������phQ�KG�N����E4+��������l��v�D�xCa���D�	���+�W�aU[
Z�������� TJ�hU�8R	kK��(q���%g';G�;��{��#��-F�*S��@?ZA��5[�$S�s9�4d��8���[Cp���H�D���"w3���1�������!+��O���U%��h+5j�O����
!�)��a���8[\&5��D�n�G��}��F�t$����~�X��eE��~�E($8��~��]��|k:i�\�����j��/c ���"z�k����/g�QpL[��B)��Y�l���.����2�x��D`T��N��n?^��P����=�q��K���|��>r� ���"�v������pzlP�m�����������WffF�u�k��B���)��Ya�����������
�����k�eW?<����|<�H���,8l^uP��u�J>n����9�ys�w����aS��;f\#t�m������#�F%���er�$����0��WU3�0����[fpF��aQ}��	�Vrh��KcC�+��Zc5Q��x����+g��@_c4���fa�"b.Wo���K�!������e�U��8=��C��${?��'���P0��s�hT'")���e��D@�zG�R81�oo�Kg��Y�|K����Y�j��jln
y~n�x3������!������ou?�*�_oiQZ���-�t�����P/s�fP���}��E����^k����oEE�+!!U]�����E
Jl[\u~�I3����~������u��"�ce�Kr�*=3,��������\��?ic'�5�U�2k#_�C������"���������V+��_���\'q�d����S�U�Wj��FZ������)"���Q,3�� ��?L��`��t.qH)*G������83�������+�S�BjU��Jv0���5!<,K�	����*e����*�c�V+�2��k��e5����
���h�8E���t
?I��}^) M�<��=�1�������Q�\5�{�4�|2�^�����^���P����W�T�g{�HcV��d�����H�=�+I"ZM�
�v�D��YQc��������pB"9�<�
j��U
�"0�0��=o��an�N"q���\��J�*�(E��e�J��T�'�Wl6��
��s������|#�m6&;fO�9�>}��$
�O�^ {$|�r~�Q!P
0R�'�����Q��W�X�/e���45O�	D����R��]sk�t��)y3��I�z@5��P~C�HF�hD����Z�S���c�O�\{M�^:�V$��d3j�x	��R�$��(yR
��vP�x�gx��.��#�X}f����~K�y�@'���
0�P��3�F�
�����D����f���kd+�D��*�Q,Do�r�"
4a$
�\�VRn�6��&���@Z�������7^�u��H7|�\!u��y�z��&>�SWc�0D%wbw
���`��FI!+����s�X���k�@�,j_�������Ip���l
���o@;�-�������c�>�L��7�}b��H>�7�G7}��\8f]�����v�� p���t��~
s�RW],��-���'����ZJ�s��qR>2�����-k���t�z���`A��B�a\����b���������:���[d�>�x����&�F@C��w�_�����Y��)�{�r�G{i��#�?��c����7��F�����2������{��J������Pb��.gj�}�N=�<~���(|��}��Dh�����|�j��D�F��
��7y��U�P��Z��ISj&#�K�O	U,�0�L���"K��2}u���b��pw����,���@H��������Y�3��r�����������}��Hfu���������ZX�M��1�8�Q�Z;�,G�Yo	�LlY�A�?�[�j���-�a�m�]����������|a���d�*B�l��+G��Si��1
����&&�Q�B8��#����$�,�o��h�[���2f�aIRM�$��O�S�Lp��4
�����U.0#�DQr��1���8�R||��wzC�ap^?t����A^�)�����lh������oBm\�(����2=��[3o�9���Hi������o�,���Q�~
T�1�^�G��Ih���d���V\��|9�����T��s��.���II(F��5�5y�i�y���� ����{V����~�Xt+��H<��i�<ew�*�^�&G��
k�����=�q��~Lh��]��(7U����,����L�6�C u�����o���A�	����%���p���[�@)	UM�n����aA6����ds]����	�*�h}���wY�D� ����l�P���
 �EZ��6�r1���I���<���R4.����K��HGV��q�\m����,iw�|���[XuQ�I<�L��	Z�~����g���~�Ic����V�U�~��g�[�mX��U�v����,
�(TTp�i,������&�c5+�O�����vk��2WP|�)�B{wMe�0��3��(qX�'��)���},�V8+iyVr�*���BY�N���D���l�u���u�T�^�)��K�`Z������(C.��l�Xl\B��	�{�L,��������;���cf����Q�	
���-�R�i_��|C	5!{�K����Z�~���w�!�D�'(�"��_��dQeJ��#`���]��G>&d�������V:�L��t?j
��2x�M/�Ic��Aj4�6�y
?����?G�I�@���U���a9}��
F��H5�\��P��T)W]Em
�6��h�Ii��E1���M�~H�d��[W
q���V�z�f�(W���b�z��$tE	��?G���������r]�tPh�x�[s����k@^����6����-�R���]���T��q��]~�Kf�C}�C����$��&^�dm7�����7�c�Q��Ww�����%M
��Q>�7?��e���L�X�qoW�~
@�����m;	�f�*�6��E���J�1>Bg�F�;�k�Y �68��U��I������O���oVWuP��M��#�������2r�y���\���n���
��Z%����3z�r%@��\���(;�ZSl,���������p�4��6�r�Y�$(		zb+n��4�!I=��J1���^�8�o���:�pm^�������!�{�r����R��Z������hP&�!��j�:'��1��<�.�J���
y:GE7^�C%���U�P73�1x!&k��(A`j
��t���8D��v�����51<g�c��=�b���dI�NR,���$��j$�5�B�Z�p
�HR�@L�
OxF���\�����U9(]�9_�9\��������4#����&�2E3'b���4Lo.m#qG��2{VJr�F�{�k�����7;q���W�~�d��m�f0�7)E�:j����B���V�Z��nB�2��(r�������X��|�����;F5aY�nY7|KpG�d����$���)���������U0���K�
�JV�9!�t�Av��M�����C9U����5�v��s���{��a�%\|����x�����W��SIY�z���0��b�2��������(��A���_�:��@$Ik�!������qE�@u��;��X7������G��3�:������3�%�z#�
��B�p��r9��aK�t���o��~���N?3`��1a�jFL��n�
CE��*!����_���x��Y5f��������
��e�����kr+��U(�Ej��e�C�K���+T�d��K3Y�.�Uu���m���D�����Q`����x�x1P���a�gz�n6AIOV�p���]�1�����%q������J��6Tf���G8]��{�8X����6��nc`�`�������hBc	�v$m�V��k����*�����p�a�����}�u���]p�"�i�zQr�R?M��H�S���")�@��H����{j�w�_#���f��1��-WZ��>��P�#H���J���o���0�J�GLJ@A����$9R=�T���-��|?c��q���fM^A�0z���ye��S������G��T�#�}R��������p>
��F)1L*���#�7��"����h���
lZ�b���H `M�W��W�g�f8pa����745(��-Z��s��Ui�dx��V$%h��".�"���t�`��\���q�=��W�:��Uc���T#��M�)A��	[y�O0@13'X��9�'����L����o���t��_P�6��������T�U���]�
�dQO�������sR!�Jf��xqw	.�����#�VB�
������N��r��s�*��u��=�.T�$%�`���~�i���D��=.�1_
TKHo%L7SJ��4hQ��-ReU�]�SK���n9���M��m�$W1�V����>�0��A_RN<S.�o�x�Z�iJ�h���_~c6����*&R�#S<Y>��U�Y�7�!�������e�����_��@��/j��k-��B�m3A���a��I�SZ.�E�9%�G�W�����o4i�$��+�
���a6B��9��&Cv]93\�w^M_���
�L��;L��	Y�������H-����A��8��?���c�D36A^"�p����b�)���B��q�Q����)����#*�EY4+4�zS.b�����KEG!�*�#}��Ot��i��@i����>��).\`���d�����#j�L�E=)��#%�`q��������\!�$�Qb��b
^�!=�p�a:���P�g�����P��k����;Y;�����7~��ge:���).���W����)cv<��\���v��7�TBl�iO?�}#{���;�\��O�b{/��Q`�$"0w�p�����r��0���&�������,d��w�N8��N|�/���A�J��� ��e	1�;�8�x3h��Y�1�$�K\1����tM���|��R�#b�e:��f%�
o!�`�]����#�s������n.��w&=P����X}&�Y
�����������N"����X�22���R���i���������;,5���3\n������*�9$�K�O|����������a����,0��W�W��9r��'������c �T����ek��E!�A���_�.3E��1��������a��i�k]��$r�AG���%'y����eO�z��t�����M�N�a�e��Bm��K8�y?�)$��1D�rX�ZZ�b��R���v���M}�tQ��s�J���z��cQ=�4��N����m��_VA<��tH�:��I��|*���/�����+���X�����f[�$��V�"�0���������E:fDGU�W������|�����hV��r����'O8@��7�t@K��(o3X4��g��������H����dQI�M��r_�?t��6�1���^����WWY�f��-�uGfy��c	k���0O#�Ns���Y!����lr9�$��"�����
��&�����E9�VI2��"����m����9{�I��S�y�{:bI\J/��L���JSo���e=�Pj��6�y'��B~q�a9���2��(k���c^a��Euq��C���x:�M>��S�j���5
9g��^0���h�V����
���gh)�`���:�Tle@P�3�-����I]A����-
B�T�.��
m�`�Z6���s�9� �|s~��3��YM+0�����^^�6+p�B�����t:U�kT���X1�y�ku�����R�0Jqps&�������p����T����rLH~�����#N��N��L��N���k�����@����4mO�4��o����Q��Y�k����,o�#�n�4T�Msb��+k�\�D��6�Y���Li`����k�q��f4Wm�K���#������1�T���5Z�	���~=m?�O[.Z���8Y��p��0^�����x��_y�d����=@+W�����f��H���=o��T|�{J�����mp42.=�w�a�U������Z|��3�vr�8O��Nx���y���1�![Q���X�K��#��NS0^q5�����"n\L)�2������=4�JC�:�!sA���z+@�E!B�/Q���N�J�\iE��{q��p0�f�GBE9x��K^����`c*��Z|��^�9(���L*\��
�N����g]����$PJ?N���>R1��EIl(�n<�[|&�\W��>j��	�$=�H��F�:��F�����������5Y�2�\�y�k%���/kF8-9������j^�'=����^����w�A����{�d�#��[G��O�5{�_7�6�&�>�Ok��
{&E������a�.#7��7�����k@��8b��{�S����VA�W��|�1���R6�X����Q���D�w�������+�YE��\��I>2�2�&�l��r�`m]Y����l�]��������{p��UH:@�H�����4iw]�$�%*�pXt�����������dO@e3��$�!u ���?OGT�X7g�3�jqD��&
4hX,k[K�%nw�q�����*:�����E��Zf�%Nm�����[��ZO�\ZN�xV�����w���)yF�[+�vE�9�hN\.���v�O���m���'�%��3�.L�o`���>�u1��0���0��f �d���P<\���p���b�=���e��3[�#is�4��#\4jr����	.��"�"�/��Q��v�^guq
�Sv�ib��f|M�#LK�F ���*�1�
-����[�_E�;�����
B�kJ����y}�����r;fb��>b�C�%��"��I�����ca���-��	�Y���L+�&�^�n1���44��Jm_G�xWvN�=�j�x�37���w������������X���ON���M�����]?,R'�,�=z-/>��b�5#I��)�Pi�GRS���f�n ��E�YI�S��gs��R���]����`����c���R�.���"��P}����k���E�������+u[4���C�������q|3J��l����W��\b3J������\�#2���/��<*=>���&v����=�`i|5����~�����������E~��z�?���$�?���p{�O��n��j���������)F�y��O�"��n��>D��s'8YA�1�u:r<�J-t[�g���-��=���>2.�G_�WG��Y�%.�q��
st��Xr�O��dL��6����S���Q�4F�xa6�>,9����x"�
�S���a1�h��H���Lm[gV����+:;1S?R�TL�@��q6���(	p���Z���QLd,��^���la���8�?:����\1� ��sX�����X����3(S��)X:r�7�@!��En��ur	���[��hns�}`*"�Kz�'����Fh��P;��S\quP��P�S����ct�T8�1��
�B|��E-K!
��n�7�S�R[�G�y��i,5��X6���jz�fx�lDv?��}�E�U�.aq4�$��X]d��v��xb+,S�gWCZ#��5g�N!��i�c�����%�$��'k��7$W�5u��Q^��SD�O����8+6���������9M����C�}�?V��~�������s�ii��@�������`���o��������&@����m��	b���{,�7f��$�����iW���*�2�Z	��IW�Y+�	��E&bJ��4�3������/����$��]�i��J�l�vh�+�����(�>j��^'\���n��o�j�g��R]�OY�Q��5��A�Q�o��f�����1���~�����L���OA��X	�4�{����5�7��:=~_6��v�+	S�"����\'�n��kq`p8L@��-K^}T���*ey��bpx]0d!+A4�{^�����Z]��;��l �t�����,��0�"���Kb��$<9�/[���fWb,u�7���{�R�K����F�K�����z
o:�:��(Z��WW ��k��`���ISu�����������V�������������6V�
z�����������B�:����yz��`mv?������
��8a�\��e>���H�1���a�zN�X�(~d�t��[ZL�V�[8w`]�$����c��
������[Y-�!�V�2��3����EN���<���b��3)7�}Hk��~��a��O��M�L"
����`vVX�dz
�Q\R�����%�^�_Y���<1#�-47���
�:�����%��������������������o�vN��>r�>8�tz?��_���!z�o,���tf�"�s�f	/��5���W���b��������K#GU���vp�3���*�
��$WH���I"���Y����&)�0(�2�P� �����Y#0�=Vlh0�!�4�+�����B�_M�M�v��p���3�S���De��\Uw���:v9*\��G�L���i���Ml���7�wi�����0��w��Z}��e�fERi���*I
8$�x�&"TZ�.E�)�&����z�dH���D@��l4+�VBh�uD�s���������g�Q��3��~9E��� ����DX������`�y&�(�vU��
W��c$gv����
�����lI:b�@��M13��V�&oi�����Y�=�`���� s�6����JE��?�t�����J�P9!�v(;���:/���>�����(��_5�G����������qVN��&�~�55]�9��Pe���\�"�������t�>��(��
"VK~�i�a�1v�!�,���p$�a9D�s]�i�;b�fSy>a(�[���&L���bU��st�K�9�EW���SB�&��m)�H���u�;�*�[U���L���
��+��MS1y*��#�����:Y�#��sb��c��`I{$v>P�s��ka���WS�'�1�%6��(��������i41Yi�2u*�e�k���b����Md��`��NB�^��6*(���a�F�)-<w0��P\MCZ���^�N��C�$�QS�MsN�D�T���p,Du��)��M&!��:������a���j��3X����Dvx����ga������M)��Zq�P]#2v�����(q��n�����r����������v�o���%�����q���?n|t%f,8$��&�F(	��f<n[�k�?�Fa.�� YGo��� ��(������$�, �V/�)c
�\���3���)����B,D;��-(j�����c��� �/�JE�Rc�i�E%_
�!+��O�QM�pP������9�kvRfD����)d��������s�����D73(��tm8m,�_�=�'P	�J4��B
(O%�����@��,3h��|M�~��nW��MRy0���6�|���)�B��_���j!�&;6��"�WT�B��+yj��o��(I���Q�+)0�
�}�q�T��^
�6����Z-����a��jx�'��~L��l=*bwy�l��)�C�I�vL�\�,�������6sA���N��z��c��.eo����rD�����?o��t����c�������B�`=���4fX�be�f�`��:��
�0}gb3��U;�
�K1_�����^����`��6D	,���OF���qnz\��gm�6N���m���W�8������U�d���762���=��*�
���
�T��d`��E���>�����A��Mh/D�G�a�YN���+������O0q]�M�G��3#�,�f������7��uZ�$
�����"�;~N�eU0H���s�
k�sB�B��!�������5%-H ����2��13g����K�������u��5/������<�
j�rL��~������l��;
:=� U�+V�g��.�-�t��..����d������.n�N4i'�!��v�l�8KEb��[��W�;�S����aU��9�\Ltr8I�U
��=	�&�G3~��+1=z2��Ox�����N�,�-
A���zdL��&�S�/�Ck�/��[(�	_��@���bo:�;�h�V�T�>��|4�9r���4��2�v�������N���H�*w2u��:����6�N�o�_��r��o�-9�V38����C�����?�a�l?���|�������������"p�
�V�L��Kr�(�����Dkz��~��?�j%?��-�IHZ��E0����p������E9>�o�����
���R�oW�bK�f��: �����x~����(����{��hKWAl�@��D������Eb�j8*���K�,���p�1'�I���1`�����^���~Yw0|*�x�4�����)�G���~&.s�O��������j��j�|��"����#����W��?{��\�+�O?�|������P����Ca���wv���c������2�:p��� Z��u�������v�����y��
�+��K�}9&���M�z8�,��R5�.66Gd�@�+sQ!6�����-2+u)������\���N87G���YV)F�mcEp�#KK���CJ�VC[z��{�p�G/�]_[��@��r���uGX���M:3,c��M�b�Y���F���t�<{�,���x��������w,����~���{���q�Y�
�}����/'�����U'��N����}��g4U�Y?����0����)��[�}9R�!>~��������&�2JN����	���|�i%�����+\�Z|�
�0���	���%� +@�C�.��T���2?�_��%U���;8-����B���N~�'z�p��0��^3X��~zQ&^%��������Q����a{o�x�����y�N�{��wg�<���]}��9�r�~{�b�������$�J`�q�M=�ncP��"�L:���n�V��E��1�[�����R�dy"���P9WC��Hf�Q�fI���Vs�E��t�Esk+�<��8��[%0�������1����dU�� �38��^��ja_���I�6�<E��)�pi�So��������UX��������n:�A\o��c���������6G��oN������=c�N����5����������R_<Y��
�TMx�Au�hA
:���I�����s%����k�;�K�kR�Y�
2(1G�n#������Q�0�
�����>(=F��+3���j�{&��R��{�@vH�}������>�S���Q���.��Ce�]w���n��=����y�)Ie�+LX�4:���)���i��E7�9=��f�O�H�������
o�=�?��J�%;�����,�l�1�;q��}guU�!����/Iz�����9h/;!]�g5~y��sHz��^���HL�����U�JP���e9$��6)�e�dk�o�$��#��I����MyW}�d\Pw���@�������9\Xfg^}���I\j�8���He����B�H�"�p�96�6s�)�.�!�����^j��V����T�`QWm�un��7 ��l�����*R����B�X��6�{�9��-iy����mx�`���F������0\f�W��#v=��{p+6��1f�5����?Th��%��^�kUN
�����Dnh	��+]B�o��9E X��c�d��L���qRiw
������4kq?!����;�:7���>+����N��7�9U�����3x%����5�c����I[
�zV�(FLh��z�(N�m3�S?n��	��"�W�>�NY���*z�v�D
��?#"� c�n�(�G�f�k2m�����)�"-��d��w�].��	��#bp������qW���3���L
�6���J�s2�
�p&�7S��5�#P&�T����M	}|	c�(p�S���BX+����@!.Q�S�LeidY\���K��_���&bNmbLd��l����F_	�V���<��RJ-�.�D�61e���l�	���?o>&s��
u��xZ�S7�'/
8���u��^���$���Sz�r��;c�����+�RVM�$�/�M����R���uru$E�<S���s�FB��57b��F��7���ZH���-d�4>$�Y\\x��O��a�����n*��sj�-L]��i������uA����3�|����F6H���;�c������C��%_�$��
t�P��n�&��[h�Y}�|�M9�(�L����p��������A(6�H%w�cHiCP�a|�T��2��(;��T����W�?�O��7mnml47�
M�Y|��������-Wf���Gab�q�YS����[���a��������g|[��}�D/����a#�Q�.K�Q���/�/��������4�{�|r�d~��X�3}o�Jp/_�/�md����[/����p��l/��D�|I^��rz����V����w����v����;'�N�:����j���U�2��?��$~==�9k��?k��<�G-O��N������3)��4|A�9�i6>���Q�1��v~XI����E�	?�S�3�eew	�W�5_�Q�����l��|����N6��L�o��`���h��s����O5�3��S@��@J_[Z��
F�_g�?�����`�����j�M�^2�yRqf$qF�
����������9}���*��W.����z����?�0�t^�.1��������#����(����K ����+��1�s����$L���K,��iS��Xu�m�-Nh�����^2k����z�a��<��stEJ�/����fE����f,����+��%�������[O]j�8V�C��h�
��=%a�]6>�n�tf�<���t���V���Tg�v_M���G��y3�<�?�����8R�w"����8��{q�"6+���W�,�����S&��_�}��W�|��{�mU��� c`4'e�����Y�u�K��F�P7�}Ma�v"�d�7_>B�g�w�b>!��i������#MV�_�
�/i������_���r\N���`����1�@��a����:��s�soCa��:=�
����V���[J�3����kZ��Lm%[������m�Z/^ln����{+M?37��d_9GTB�����`g��bqb����Xct����V2�9�����+��C[V��$��x��4�Qu �e�DF�����?����W'B�����V���g���t5:/v���tkZ)�����|�i����z�K7�I���*�����zA&H�/�x�|����VK���H����������b�Yl�^�������J��4$I�w/��)|�WcP����o"�������R�����o���$�vMa�O���[��A�e#I�C2B@�7�s���B�q����HC�������q�6�z�c�b��Mp����5�w	r��u�c�K���3�@@X��|U�����g-PK����#���K5�N=�&�O�i�:s�+����������~Qp�"�}�{���d�����D���b����`�Q��5P�g�z�A6����������}|��Z��`+P���p����!`��i�yg��_P�wy����#�e���!(Ig_�l�����X��QI�\-3*&�a�nu�~q&M�p;tRg��z�D^u�	�3��yg���+aT��J�a��tKR��y6��!�C�	_A�f��g<w���R��0��jE1�w�1��G����F���m^��/y��o��.$��d�au��65�A��&�!�(��Sv�r1��.��2$�������"#��C���� %/{Xn�x��8&��;5��B�����|�	e�H�����[��-��g�uu����$�N���b�����#@�Mb?�t��,&��s��pq�����D�#�Z.�o�$"^8����sOK���T��q�jmr���I�1�-U*��7�����U���(�Z��:q�c��Td"R(��%���WGFR:��������&(Q%pI���]L�8�	So�7-$�A��[L1���5��a���[�
����;��n�*��;`��r����V���E�s/�z����,!�@�\-�_>�5z���J����R����zw��z�����L�����%�7��t���c+��9�)��ZY�O7���>~1?�u��#�m���s2���o����p�����6x����9�]��Y�p�og	
�ZC~�i�LW�z�f'��bI1��T9���P	N"��H��d3Z��A���L��Z����T������*i�Si!�*�:t��Pz��="�*s���?�b����g��YF�?�|p�r�zv�B�(�%��!����f����AL��y#h2D�0=��q �����I�����.p�)`�Pj�ud�:�@y�c�Z��A�C�$,w����JS-��2�R�����"�
A��9\��� ��4��b�h��K�����E��s��(������:C���)���}��R��s^`�
h���_�cr%Z����0��2���2#�w ]J8��'\�/&�m��D�1���)����'u�0(B�{��;�31D�����J������Y���c9���!|�!L>��l�u'�88x0�G���h�i�����d\6�1�(3����k�2d$@��
\b��P+98�R	�S��('��/�Y+�g�H�>�|�
�3,�c���q�:Db��l,.�%*9o�����\M�^[en~�J���]�q�`�����t��������������x
w���OW��l8��D%9�yg�������M��\�j@T��NO��:\�i���?��r��jt��M�-�c.�����x��������-���Vxof��j��4=�����w��Z�������2R
J�<@��)&N�{�sqF��W����N����w�
����s��;��>j������
�l����C�L�)�����k��B�����V�~�^��OP�c������B���# meebfR*�$�8���x�����j��*���I��^�c[�]�fp����Z*�4�@����H��"�eny���h�����I���[�e:���.�V��xu�",-?��R����Y�N*�^������P�(�v�\9s��[�\���D�d�q�	�O����iu��q3�������O<z�w���G}-�|�������I��d�������Ep�;A�,�J���aQ�L@�J�Q$��g���2T��F�{���0�(}��a��G����[����
�&�p���"�{F�J����yf>L��m��*7G����+��w�<0o����*��9�x�w��ef�A�law�]������T>������l��/K-834~������N�:�cF��2�lt1S�ybJRI����<,2N�L���R��B��x\����������p��7��)��k���5�i�X�&�JTJ����Z?����[�js���N���#_��5���O8���Q�k:��K�LJ
=���9��9�K)��sp�0)���N�8���`�#|`��`��H��'_����{��l��m�=MEwI���~��z�b��%�p�������d�W���b]
o�?�����%`�e���%�������gD�#H�*E+&��X�x�$|�f
�����QMQ�t,&9C�Jjd@����;{��8�9���y8��>����G�[�+���/��*Pn|��e���l�
=�Q���W�v~�K��Ii�1��FPa���k�Y1������a�:,��2�J��D��k�0�*�A,��0g�@?1=4�4X���b�qg/���@��_�cT�e,`�L���]�@�)���<��:���h��dWI��I%Y6�����t��l={��|L��H���������Kx�����K�{8B7M&�Je�������R���n-�PhP��NKu0^!N��l����f�j�,g�1;�Nm��U����x*���������w�l��`��_=�����n���7�����rIal����N/��9���x��������w��o��Z�l�qwkc��P����P��bC��l��4���-������P�1�n1����5���I��sRa�����ay�n)t]��U�y5�P�eSZi.�;�g�b�H���
|qO�h�x����*�%����;�a������	�XT2����|��F�����\�{�]����t�l6h�<U�F�y���q-M�
��`y���@�n���Y�d�p���C����X�b��&b�k�[k�t&>����!7V�l�Z�1�~u�A��I5��� ��.���
��z����D*� �B���'[����V���A=��Q��V��������e�_`E��2	n!Z�.�,������
��k8���?)/�_4��l
����mA����!V��$k������^��uA�q����k���-�K����PPD�)/�^��^��"����?���U�e�,	�S}�	���������5�"]V�.�������4 uK�i�1��/�tf���-l�Y\���:y-���n	�o����<~
�����'�����t:w*�cFc�d��3W�}rb�G��*�5������2�a#t(^]�;(oKi����A%a hRc���c!Mgw��_�0Q�Cn��I��]�8��4���H<n�$(���i	��u�A:F�)~�[x!2����
���"_<��%CO���g��2��S��>^�������
��}-������S��0)A,�Z�8,�S�0u4���o��p^�~Z���}��[�D~��xH�\�����t�?����D�L��#I�z��h���*
0�{�����Q�~)Y��L���`����,$�4����i�������B;������|��I��M�dP���� 
���AI}�7H�F���FOqI�_d�#�Q~�|g�M�"�7�hIQT6[����v������_�/�-����@��X_���v.�~����Lv�3��'���H��)>x`�'�fK$�q�U2N�z�I�3�7�7_�a���������Y��f+�gt�>
f-������j,�[E[��C���[Mz���O��L�n:�u�E
�������������H9('�V�8�&��1L�E�w���WV/�o<�����S6������V�/�;"t���^$�~yA:�����O���;����;��(�9���E������T��B�y�S�p�g�iL��<�I�OL�TL��R>���'Y
L$a�j�
�����^n��eI�����\9�q�<��K���P�vI�@���m��%#`*���840~T<
[iQ��*M{�[C�/��Qo�E5���M�
�y%~�b����;��J5�kt|������i�;��Q�/#��y���$���R�}�.�����)$�:���A���Q.���>PH�3MK;�����A_�H��������^��BJQ��0����$�����s�i(�����X�n�!���|���pKS�;t	A7���<!�~����oW�~ �#g+�����R}34�U�"�I���a&a��ft�E�jC\_:qj��5l��������N���x/�4�����J�n��������;"]�(7a�����q��v����������/�#�*QQ��w��n��3\���1�dQL#�x��Y���s��$�={�����*��[�ad~A�?�Q4Hx�����Xp.�&���i^�^9]��<���s�FN)t����<B<GGY��s�4h���T4K�D�\j	-�T�h5s�rtg���t�G�o���X169N���As���ug����(����y�L��@�L@�h�������
���39���0K���E\�{��.u�{���W��RxP�J�G�%��VfX^0V�X�v�����F�m�^��|���9��tRgs	�.�������^b�����^%�0p
���yV~�yw���x'�p�
z��v�n��c�kz�NV��i�NM>r�T�88�����Y�^R���g���<uL�`�A���K�qg��T������m��������
5
 k�b��s���%�7���]�#n�5
�
���������l��+���U��X������/�4�%,��"�
n���vaT�[��z��5��81�3��I���
KGY0=�`�)�N���h%�O�:=����)�d��G�8�?�>�%w-���HV��[����W��+A#�}F�V}L ��V���Kdf����r�����_��E���K�C��n������a�T���L�'%��{�E�=�;���W��d��3�%`����2.�M3�}���)��4Pw���g��>������O�ds�U����J�=E��gJ�����:�s5�;���Q?Z������q>(�?�r�)�yo�G������|K�h�{Q�=H������Q����m���c��gEZN��g�W�+��n��Y_���@- ~T��	�^o%y�:it)��{����*��H�y�����b}���Ps�,p���PriCU���m��W��{��������t�?���7�9P���fR=c�5��������Z��.a���2J�m���Pw'���=ad�^��]��2��l�V�M��T��}�������qF
5/{O��A��C
nj����F�����L�R�AB�`��R�%a��|!uZ��l�����������������
b�FR���~? ��P�N����e�=G
��,r�$GV���X��=L�B��bdj��vN3���
vq!��|evbZ�-}����d�N��'T��_�ARt�O��g1�bj��Z�������?���G��}�"�'�&��Zj=�3���r���pH�rN������La6������ �������������+�p�R���J��}��h��w�Av�w1�3-%)��"`i���� 
�3	_2$����q�b_
��bB��PK���4�?8�~��?�'1���	����"y\�B�x�J��g��4D�E����G�5f�E8J�R��DY������1��j6������<��>��D�:I�?�o�Ak�9gW�������������X�����{,�1)9�h�\>$�&�5������~?R{����H�5��29^m*mR���t 6�E4�����8Z+�����:�x��U�]��r�El���a�Mw0���l����8�������|�F��!�Q�YE����"��t�J��p�b7
T����`x6��6L��:Bp�����������#�%��Wg�N��/�h
9����t��4Jw�������zQ3zF���Q�S���e�$�9��tl����I#gi���}�����
Ew}Ll�c�����W=u'��V����LIK�7�G��}�����7�[=(t��i��1�/�2�+0��9����;y?��kM;06K"817
������	�k���d:op�1+�Z�FPEA5�� ��cd+����%���U�n���S����H��R�u>���O�Xo�-���}T�b�To�a6+%K1.;��+wO�z����<�g�S�c�����!���:u��5JS���o���$�Y��J�����:_�P�T)�/�eM!�(���O�l&E��������,@�Pz�L����Dux+#�UZ~I�H���������;�{��r��}��c��jK���[3����nO���������/�1��_��Y���2�U��s/�5�o	�1�=�4:����u
EO��w�(����IB����>�������"C�y��9V����������P����P?��ulv��d�)�Fzsq#�KtWU���##���C���F�W�����w�3t>���
s�y�C�Y78�\H�������E���G���>k���2"s����2q��1xG�]�>u�\�������gg�{�\�xeU�w�jwn�9_���7���DM����@�:
�p[#R�to��d�{�R]����%�hPX�3rK*&&�a��g��\zR0���r����<,���6{�v0s��4F&�a:S���:$*�[''g����8)Rp�4B�e-S�x����`�z�F�������[���QY����3�A��sL��L/���+��l����������.�b���y������3�$��0����V�K/�$�n�j��WEm���?\����&���`�65tM�PC�������4'�����aF{d�d��<>
$�:/�B��j���oy���PJb}3{��-*�
��W)c���st�)�n��Cw�!@�e�/��B6���4�pz����� x��ql���n���#��a��y�g]91WV@��%����s#.�����n6��%t��R\�R�:q���,����fQx��6��k|m�s���^����<�29e#�:B�:���.-���q��� bHU�l-@���[����3�:�}�e!������Z����J�	���8N|
��d4���d���\�cJ$a��`�%[�@/xo��$FZ����Q]�dM�e������.�P��RWN]V����@*��n���v��f�Crq�{4T�hJ��3�ig+��������
u����D�����+l��| ��h�����^)1�����.��������k�u�B�$��!�������o���Zx��Qx��H�Q!��e�t�Pl�o�]�p-�e���s�G4��T����b��e��':��pYK���N�6��<";�a��`��s7��Z����HtM>X��^G��a5�_�������������N/���D�ui"������V�����"�������^Q�}`�HO��A������/�]�'v��?����}X$���|
�����9
��'R�_N8���r�.!@x_�W��m�����D�������i���|������J�S;�?�����'/L�-g��2I*30����������6��{�$�|x���<��a���R�U/��DP���2�6n66��aA��X�����������#���_O�998�_Z�>��H�����#�}3�;�����nmM������1��g">�L��/�����)=b�]���A'��M�F���(��������n�b�\�W����T[H�Y�gXZ���^A���M�	{!M���@F�5��T �<����{�c��[_4�a�]
BS}���yz�]���������6B	��d��
��t���� �2c�6-�kzp���-|r0���(�1��hr��eD�k�v�]�[����:����l5g�B.����(!���E�����^��k���q=�������]X�O�8o���YIV���laY�����wz_Q�8$(��+"v^<FJ�l�P���O���]��+v}X�f"#�>
��Uy����/!����Lp�^�z�M�i ����������Z?���O������6��m	Q�Z,�,��y?���Ai2t������%{_�KzS��5�h���t.�l�q/�����Nj/ ��O�X�.�f���z�^��zVlQ
�`
lhn@5�:)gu�X�b6����rv����v���N�K��>��EI����o�B�������Sl��<�MC�s?y����I��D�}����a��[��Eo�}��1D~6�w	l[R�A�h_����b�}0`gB�1H�'��������Y)���8M�����Qt����
��o�K������t�7���/Q�k{y��Q���4n�P:��E����$�WF���"��\�0��lk���^B������Cc����������Z"p�5�j���W����O�����`����P��)�k��DZ��G�{s��Z&�9��;���
��V6�����+�����5�Ea���p�8��Y�
�VO���PY��rF�c�����l�K�l��m����������:��VFS~������Yr^���
�������=�_����������C�o&R5XX���:r�����8�Y�{���n(���N/?�;��Z�����d�o'�A��d�Pj%c��M���l&���!k�a����H�M����J3�_�I�+I�YK���'4%�2@ �Wu]p� 
f����Qj���RDEL��L��J�,(�Z�0�	������Z;U�����f��)G���B�����q|�������`v��rz_-M��w�v���U�w��������3������[�TU��JV�6�n?��J��M*f��s�����&��J?�2i$d�����PL�!i�����G��'x���4�������}~�B����@^��/6���Q1�������}�o����H�o�����~����=��TMF���E���������y�RUy]�T��f8�qR�7[[O^&��'��������Ys�Ys�|��-����o�����I�=
.(`�MN�k�o�L�s�~�Y��p��g��;ww������?�t�bx���ie�p�zh���+4T:%grBj�_��������;�-���p�����:�/y�i!�f�-j���7����$u�[����BY�~��B!1�Y=����R��o'"�}��9�U�`<cX���b����&����������l���pW�k@��zE�,�������c�r��z���l�Xkq������v�:� ��������[�`�s-"?s��|]K����k��7�����QK���=�_�eJ�M`��������Z�Q~q��4EV��3�V�}[���������r�rs�"{��8vw?�[{�q�^�����������/���t���opAK��]���{0�||�������@������:��J���"�?�x�t��on��s��_�!"�W�0H��;�mTm���=��vt���(�>���2F�N��_a�43��U�
�S;�����|������2������v���VNok��!W��0Ph����y�0n�~TX�c]�!���
��[ Dx���4��u�Y��bM�
�!�b�����Z���>�=AtO~]G��PP�HD�
 !��0���h�{��U�U��B?��b����!E�R:!K|d01R��V},F�j�[oG�YltW�����5�����%��${�T)<�������:7����4��������[�����(�Gq��c��Me�Z�k};Y?j!6���#��foR#�q����������V�P�/�?�en>b7c�B���\�����'�������������z����)������p�{D�?������j����X�D��! �E
h��	\���;|�E@�D�����x$-������/h��W�����^�<���L�?�o���{�����8���m��/��xs�>���?r5.���p�,���A������q�o+����"">Pc]���#��|>Jm��a�u3/�i��a��0�����J!���WJ�T��	gu`�!u��������
�N�5�(DDr*)��>mM�?�A��y��0�f]Z�i��x��c��G]�k���h_s����	�jf���B���@���!�Dj�1�mO{��_22����\�o�(�`p�#�Nn�!����+���7��Q���x���^�`�%McT�;���)��������JODC������pv�"Z���o|i���r?����'>K�=�/�����]�_[���=�,������6r������H��:�z���7����^���,N��(��^�O�@������H$8M6s:�E��4o�|��q�>�x��@:qZf�O�-F�+�L�
��S;;a��$���}����i���k�	�<�GW���z�r��I�Y�E�rX���==�����E
��8����?R�.�d.�k��$��t�{����isB�9��xA`d���q�����C�b,UB@�5zR(�d���0����9���f�
���*��D����7g���K���y|E�����Jg�G���w���5���L���o��C'������1��8P�M�
A��xP�������B<(|�����C�P��*�k�/�,��<9@��<�f�\�����Og������l�������J����<52�{�}>��Y������h��/m��Y��l�����C���x��N��*dyXQ"���O��dht������'3�E�p���=��;\~��	,���������m`��"��f���
1�1�"VZ @��?������#X
i�1��������_x��yK�y�,W
Zc���v�����Z�,N���A�va�M��I��F�E����}�3�8�>W��@4 P�E!�����,��ib�6�����M��1�O1@�����>�2�����|N��v�T�M3�M���Y#U��%��"��Z����]B�s�o�Fv�����NW�y%y�')7�*[h�;��y��0�R��h��B,�Z��.��~�>%��7�����8i��D�ig��lv���0��|b�*���=������������kE�/���r�Jzw��{� ����{1r����<����;r�1pc��}W����������%��v��Fr.%$�@I]NN����.w��]*�����)�����k�i��B����k^���zS���ljd�am����K������yg!�>|�#�?~�)��f�-�;_ wC�[�Z���U:��J����h��;5_�>�?>��?y�����W���qoa�h��T�={m@[��yYu�i�Y����9���q��U�R��
M�9b?�8���K)��OD�������I�O>��N��q.i�)����C��+&\�)�hI���Q@e��	��$�M�s��`��J?^_>��P�������,��f#����'��M��-�i)�R��!���rp��?E�k�@	����v����o������16���?�?��I�wO��3�Bt�M��B�@!g
J���?�����8)i�^�V8�
S��[������L)
�I"7�lg�$�NF@0Y)U4A�`�{�n��T�Q�/sL���x�F��l/�����nC~���6s2�����8m[����P��Y��L��jA��J�:#�J`�;�������}w�^[�2�PgS���5�s4	�(������.��[^k]_�������U��x�*y$d�S�oL�2C��eSB1�T���7�x:�����Hg}[�r��L�A���o�����#g�"����^O<��{���=������W�Gr3 \K>f�����D�B5�����.0W�P�;x#�;�������7@�N�b�����s�����A�
�����7����~R������2�*��&����5.�(�e����!�vfH
6�dI�9�i"��T��o0{,z�[��s��g���^�<�3[����w��o�f�	�����U�S���\���`v����\-�c[�p�g��
�m���'�{��lS�b:�&~g�����!+�����2�%�(taao��]d��Cu��'\	��w~\�Q��t����@nhT\G�����XJ�1��X��+b<�1RI��]����������`dh���b44L�P�J"�G
T.sWB��@6�#�)?%/��S�-��Q��!'��>x�]���������� L��4+VY[������J{��=���\��:YM6�������T��l�~m���/|�c�a�H�����X(�.8����C�JE�r�-`ka�;����c�8�*sa5����\8����~��($C����]6����q����K�]o01��l3�9�FzAb��l�����:�
��jL���G�O��\	��7�$�!�M�����15�Y�(]=`G)A�+8�T��D�� �L����`�(�uVM���+4@�#v`NG9������/�chCW=��c���*�2g$R�%,$�)|c��.r)�7&�fK��D_n����Wz�K�-�C���S[3X.R�jb���Z;����l�����Mw��5��t�S�%������B���vM��`����Ge�=|�pyA	f�`]��/�HS�����J��p�1c��a16j6j
�i��d%3o��D����_�^d��VK;/&��UH8�G���(����`�2�Fh���/�C��6g�\~Xh���3��e(��v�;nf�Il`�[vc�@rEv�"8�F�@0U��f�����d%�����q@��K����@O�#x�|�!+������8��k�)�2�2,b��U\�T=�w���G"��t>nv,�L� ��k?��#����{�x(D�F4�"�W
>����cnd�"2������8�|���fZ"������3r��b�#^
�����[��
5����S	S���B
�T����B5���q/����f�U�����_WVtT����._�D�!�<+���p��W����6��vg��U[|=O-���2�n+�
�$iw�����;���Y;o��*B��5��n��Un�7O���������6~����`�?�2�A��J5��M.#V�#g�mTYVt�w���lQ������;|�*��Xa�j�Z�i����%��6L�%�>��	,���������!�8?G�v15�� ���I)�i�����L��z��*�b�-��>�4��O��C	�B��i���@�g2�;��tQ�s�F@_7���
��
,)=�3r?��(�D�[�E�
���s��#�P��Y\���|��rkVEsj�v��d8_ {�����_��Z�����@������`K�������'���+��>MmV'�T�~Z{m�V����%�(������k[�6�o���YR59t��C�����2j���������$���0�{��1�R�������_hD�G�Q�V(��L�IV��w!x���IQ���{�r��W!*x#��}�1�$�i�f<;�2�^����y�/�/��N�.�qd��c�Q7Y���i]��
J<u����;�&��i6Fs��i�a'�R�p�e��{�?�]I�*��6�|�! k�B���w���{���z��I�5������W����Y��]�7������UyQ6�)�l�ca������s��3��w?$�P�T]!c��b�&2B��}Z.����8��Wxc�B^���?���8G��=���X�%b\u��zO8�����0��� 5n��n/^v6���ZO�me��'��<�.��I#B��j�LV��[[�
A��G�J���rB�v:^����J�S4b�v���7?�)�*E���Q4��l�5��$���C�?�`��@��f���<�]#�E�V���uJ���{�H��N	��S���6����kqL�`��T����~�����`��|�������$Q���k_�\���g���V�/T�c�6��?'����g����m�D��eG�A	��z��n��]�w��8�������+��H�.;o����dU-	A�UHz��Q����u�%��
p�����rXt��2�m��G����,�/f�l��+�T����]�������������� !�H�>`��_�����
�_Q�3�I��$)W�����%l��w�������u:R�����=N},�����1a��Fbp,=����k���������V�{$67�!���c�������>��/{�h|���]�e�\-D0n}���,tdx�n�(�����l��<e %Q��8����Km��)����\�=�s0�`{�����a��N[�"�������@h�^���X�G:S�C�2��;#�={���WA��I�+���u~
�0t1�@���L�*l����_<�ndO
�w�����x�G��r4��F�����t�*���;����B��A����G;�|:8�sc��/k���iYlu���n���s�4�/$����Hh�"��t/Q(s]��N�v(�����Lkj��TJ�VL..�x"��8Z����vl�����j)J����E��-�a3>����aK�<
l���X$��N� $t����JZ�x�1;=�
*�����\��0�&��	?�qeWu�����a�<},�[�M� Y���dS�EC�l}�k����V��+#MR�^���F������s ��%�8?'G	'�����26���������#��6PXRG���@��c��}�"��KV����`��dQ��*����GV�n�x[�����r�==da������|���"�N��J|���m
U��"0��ef]]rP��j���+kD�w���"x<m�=U�9���������A����^�=���(.�J�j�3��2�y�/"c�����S����,q��*��4������C������L+,Zu�e���K>�>����A���f�v$�u�Lm1�r�����S?�6��K������f�_u�>wKl\�`�x��I����=�r�8\U-"�	�$�r��X�Y�!�J���/?�F �����v������:2��|�Ja�@|��.r����N��9��b���q����CUH��!�u��{�^�v��.���b�T^,r�|��3W1�O3J��4�P!���i`p1�`@�'V?�<8��D�a���������F�h!����^_K��x�pLZr�YQ���L�d�R���`��@]B��P��e���g��G�1�?�����0��������'S�����{��a��z�������C�9���]h`i����n�����������O�>`��M�z�Da+&��k���}�FrWP;8j����3��2*C��_o�=������_���?�������d�\����c���/';wN�?�a-��&@;:��9���u��y���LD��	t����kN�	�
Z� �����D������N����{�O����6��n�p�Wjf����e��%�%�^�7��Y�Xb��0#��B�������/�m$������:)���^:����t4Jo��0i�u^7��/������'��O��w����gM[��{��VA��K�&(��Z�.W�F���]�!�@w0�(��F��6���oES����q��f��^�$��bP����@;���;�����7�����S�~��5O���m4���������$?`��=�mL����27�������=�n����D���}"�=�w����;��y����:�#B_�"��_�zN��D�4��n�,k��Q
���BnY�JD1�u����Zg��[���Z��w��������C`Bs�M��;'';�S�T��>�?����f/67Z���N�������tP�M.wM����g!Y���Y���
��\(�-	B��i����Z��#P����{P��OM���}^���o��d�E�1c��j��G?c-����&��^z��Fv7�l���h��m>}�mL���?]�E�w��>���>
7P���IG���y��x+@����t8��������\����=�� ��}\�+�t�<
��U�m��!<�R�W��g�����:�<�81E������*�S�^��[Q���-&���C!�����gv�G�!��`<�{G�]��u��h�Y��5��k�k��_���t��-I{�T����vh�Pr~������#x���������Ta9U��QvT|��H�G�M��H&������C���|���d.:�}R�M�7���Iw�E��hw+{|>����:
���~��~��~��}|�wxx������i��.�(�>�3�]��3L��r����P9�;�����|i�� ��J�)x�m*X�H��XJ���������^�e�����fc�%@A���9�����k%H������
�:M@�\[j�/�^�p5��h#z�*��T�-�����>��5��&>�G0*���k��������-���g�Y^�hn=/D�l6~���O�u)��8?�d������<�Wi�%&��~�%f��53d�`����W�x�br��8�T���=����'%&�U�[�(Sn�h���V�i15�&�W|'hj�W��x��9*���+U}*G�i0os�v�i%���)�fg!���}��=D�����J���W"(��4�|� �����42?��,�_�]��w����*�;C�q�o�@����W�/�7D�(�2D���x��j�E@�Ga���!E.��&��K����\�[[���\����;��W/�Y��+xVK��?{��|��k����E�T�!��o������Y2l9������o������K'@=�d�%���U\�f�&�R��J��u�Hz��c�HO��V�0�A�[��:P"�����=	�i���7R}�����!�s��xLS����:�x�m�.��7oO�?$���������3H�Xd"#`;�W0���X�
'?�=�e�{��M��nc�g�II����z���!���>S�/������*[�:1��������63��^>�x�4��M��9m���Q{�d_�g�T7���y})l��D�_�������������!�-�����o5�9����'��Kt�5�L�/�0�u���R*?k����q?����������4����,�����|�yw�+�OI����f%�x8�o�����(��l��i��w����j�:9���a]>��K��1���?������������81�	��SH�I��e���O�UD�>��� �������Q�G�������������f������^^~�vx0��^��O�&	����d�����{5�/���4��7on��1N�����D9��
!�S[���&G��t�����K���?e�x����������v>��?��/�_�����b��$�_|�l������B�����w��N�����q��P�vo��x�dK��M���y?*�-{:���hh�����o�����������h��}�j�����4��Z><�"����v�a>���,g�~�u<*�c1u���f�M�c��=�dk���qu�eF)���9B
f/���L���L�s<B��h�'A��2��=�j^��\=��f�E�ik��j�0_`y�����3�
0002-wal_decoding-logical-changeset-extraction-walsender-.patch.gzapplication/x-patch-gzipDownload
0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gzapplication/x-patch-gzipDownload
����R0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch�<�S�H�?��,�f��O��l��#�`���$������,): �n����3#�d�Qy�\	X�LOO����M�M�����6�V���������V�-����Vk}�fksc��z.�s���X��K��j��.�0���5�7�]��t��p����;
������"�[�b�5\��^��������j�Z�~<����]��wxu�n|f7�30��3mw���� ��k��#��e]7
<3q�����<-3�5��
������l41�1��z�^f�7j��O�f����8�����w�����l�`|5�_��Zc+�gv&�;��e��p��vq����1���������\�:�[�������>oBn?#�����o��3�d	�X����^'��;i��.�(��4�l']dU����d�v���$RT�`"j�!"�s��J��n0�;\��W�l#����Fks}}!q)��s�e��,V��T0�y�0�P�]�c#�el��F�=l�l��$J�/��Q�����W���^�m�������7����9v1�bqhAn	����p��e���i-"/�m���O'�W��?��S�K5��g���-[���a�t���
�	�m�4[<+�v�Z��i�5RSW�S'��fddf��G��������Qj;f&���i^���L����d5�n�,��S�'.�!�E�lK|�khnno��6M~�tcg�T-�����h����z�<K������ H���~<�c��(���04���n�mv����c
��1S��%";r��>Lq`$=�������7�	��p�=�����fz������v-��0Dp��]3EO"�Sn��	��AN�W��8��G���1���oQ`�������o0l����@�dl:t�������}�w�f  $B�
�#�u9�j^
��t?x�D,������|����S#�����O�`)��[��C;L(8�����;��e��V��(##	:K�<����G���GK��C��o�K��`,�m�&Zd�S(��$����a�W��^��~vq�=:<��%E���p�rUM}��r�$,���/t�(d01���fa���IVPppC AIC��)DQO�V'#�
R
���)Q,�<pT��@�t�E�B���L�N$K���"}W���`j�w�������S���P�ZY�$��b��
����0���vJ[��9cA����� �\x���n&�h"JAV�L*������k#�1��PC!%n���=�	����z]�j��H]�����Nf��9�������������-}>�-����n��H�A��M����#�q�D�@�
�\�+;j�+�\DZ��$Q�!	$T*�N�$�E����!���n��73A���l��c���FF=�=�9PDZ
$��a:����,���n>�Phm7�c��0��v���HB���Z����[h�1"\%��9�����$�L��eM�Ci�j�%
K\��x��@�jX�^$�'����J�H��L
�!��=����wHgJ��H������\Y�3�O/f��	�E�"�U����	8�����cFD����4�4=X�a6m�6i�`��	�On�m�!=�����{�dHq{q���b��8�������:Z=��m�$�`
H��7�1H��, �(��n�I
P=���/���
r��������)���pHs�"A4���s�//}�1�8�8���`����'�3b�SI�
pV�����{�
���p�-���q��:���j		A�&C����T���@y7h��y�N��� >��; ����A��L��)�o�S�� �lh��[��ka���e���ia�r^�_JB���m��L�Hs)�R
`��MH��z�!��
��F^5���{��G���������PN���Yj���'�03��$�,� �����m����@��"����i"�����s�T�K��<�Dk02n�����2]�#9�Sl��p7�A92�N,����j����#8�V�pE,�
O�)����Ee&TA.����t�K#��������o����OdS�����@�����LAo�6�fF��h�����6��A�0��
�.3��4�d=���aD���R<E�k�5��������zG_�?��	*&��<i���`�F��)X~�b�^����yb*���_����}>��?4K����T�&��u�"W�}RO����d���-mC�Of�����A&�r'm/��ee-'�K$��X������S���U2yN�� 2
7��[���.%� �v�4$��7H���"?-�~��EI�/�<�BT�#U��^!�<@"�x2f�zM���I�S�����������s;��� �����nPU������1����)(���8��Ab� �D_�B���q�m�u'�����P�N�~�Y~�N��� :�f�8����a]�<��3;O���'�-o����dT$��|�>�yH�y;� *�i$^�G����9J�����w��~�v3�L��R�T�I{P�V���W�=���E w $1�-=�iI����>��YX����D=F\�Hg� )�fI���4��.�;���A73������������o����l�akX*���
Y�7�+Qe ;r��yN]C�I�z��,BM:	��U���0M1MS�3����q�o^��!�/��xi�a�p�*/B"��0XEp��U�vNyx��T�E�o��DL(�7m��9�dE�o����Ry�����I�?c��a��O��l�:����#w��1�g�'�
C�B����\=S!�d@�����	���bg�ez9���{Z�����:��������|�7������qw_�>��}O�]{�km�(�_�QZ�}������k���\k�{D�_2���8j�T��W��[�*��Es��%��=��{�H��������h�
��
k=K�{�
�;�sk����N$��z���v��o(�-B��G}�j����h�m -�776[|Z$ ��D2���b�B?��,��zo�O�l�����+T<�����z^-�2�x��~GkfW=�u��������])��R���4��;$�~"���MH �U�/��a�[]�A�Wc�Y�Y	�wD�[�K�EL���c9%�:8������n�����GU�~��������7���n����(�j��J���\��Cp^��s�'��R�/�*�T������=�_��
z����osR� ��������q���s�u�93ly.8�w���[&
���t@}�2����]������A��2i��6���U���B�]E^�LY�z��_@�{'��w�p����H|�b�+��u��[�K���/��������-�u!�<�J��2�14M"����y�j�7�y�g��F;�52�Xp�
|���h��?�B���?O��3Ii��R�m���1F�7����r��~�����8���U����#��
��$b�Q��wv6����jL{c�����������4� �Q����J�����U��\��}WF?+����vGN����3�xc��}����{4��B�s�3����������V��,c4�����2�������s�L9������]n���7�������m��ad�M�Uve������gC�p�/	h'+FY��D������]�`+�����vr�\u���
	T
�li�y��=��������~v������dP�TR��k������>���9��z� �}a���W_�h��JM�� }����@���3��^0U|��]��pl3}�.=�<�T2���a���a�=S0���7��1DU���M�vpcu��)r�c����`7Q6O|���/e�)]<���u%�2��w1�^��x�A���k����|?����4�yn��z;~�9�O��k��Cl�����M|�q�+����}�'�FU�O�����,��k5�ByE[����-K9VePYz*��1������O�'w�ZC�R��+����=.��s��>^���~n4k�O���bHu�����������(?�^#�\����a�S��&�u�J7�~h��d�!]#$�����VU1�����
@���,�Hi���b��"@*Y��YD%|t7�O�Q�y�N����h���>?|K,*��,�0!t����.�W3���$����\�G���tz�W	�s0��y��{���;
���X;QN`��bh7R������P��(\����Y�v4�����V����&����8�P�@���j!�/�����!b�c�����'�a4Z�[b�>}"��:�%�jN��p��4;���e;E����
����%�w���{���X13��gS���8�"J������W'���Ev��
l 
?����9���L�p}2}Bn�g�>�f����sS��rQ �*0M�\^�VWn\��.i�x�M�,n�&�#�4��Y�/���k��h�Y,��Q��aG��y3���7��J���$^1q�2��Q����������h+#.���z�Y���xL������N/_��+���������P}�����T����M��������O��x����V�w�����5=�B:�0�a���L,dd�w$��%���rQLY�G����f+l;����B`���.�n�����"8e��;���*��K|/9F�t<��%��b��m	v����:��������,�b�,&i�M��l���?b<�,AK��*�D��Is�_~a?��h���T�������XR6 ��A@Aa�D�.�B�H�-'',��/�h�����a��<�X%�k�U
��7�G	��d}�$����������`Y�L[�D
�C�L!9��r�KfjU�Z��@$� �
B��n3��Xx�x{,����8���y�e�����l���3�L��<�OE�T�z���by�����c�|��*��b���z��v4����O��D��s`�N��L��]�����#������4MP�[���.]?���\w�h�� 
���$��V�S���V�h�����VVeU�����S�����4��2��)�m,@&
��#L
n?n�W?'�p���I+%5��?2 �Iq)�`�Y����4��aw�v����}����(�i�������HZ�u���(�c(����>��=��L� "�"��B��:�P��Uh.jU�P+�jfD4��R�V��n�
���vd�>��?��8�IP�=O;VD��������n��+�j�uxy5�<�����>?1>-1�'G����,����]�r�0�7}�[�@�v������H���=p��wGM9�s�,��g�����DE�W�Y�S��,G#VO,����#��M�	��>S����Jb<�`#��R|%����T���D(u�2��xS���E�0H��G��#l�%[�~V(���Z��m�2f�[����@xk�U��0�������=��d����������2A��w�
�O�)�Un��f��?��G��"\�(�'1-����%b�@�G�i-~|O�]�y��.	�?�]����@��pL��\d��D�V��*��	�����������o�t�����Vc�V����P����"%��{�����c�8m]�q�!���t�f�����o&x.P�)s(��J�;�^�}x�p�p+����I*��H_61��j�O�m������)��1R�f��B�O:b�fC�2�Pd�2��y�RT&]���!�(�0��S�����S0pP��
����c����'�F��-$�Q 5a���6��Mm�~���+��K���M9��8��$��� ����H`��g�m�g4��%A=���}���������JO4!���J��an�%���w��T�����)��n\XZ$����MQ��y�`��6��nGmq���T���&>V]tYVS�_�EaP_0�;��{�.��~k�RJ4�L�vk$�C��m��A�L�H{8@���a��: ��pW����]���&�9�`4&���o���d��vo���0'�	�1����e����N��kvU2|9;8*���������^�8w{+����Hu��kS�9�.��H��,��L���3@�H�o��Z�3x`������/_�)��h�.��7i4*dz��u���u�!�oZ��8�f������E]v`�;$
[����9�'���k�v��{���U�K_�4���A���$ej��i;t6�T���o���Vb��G���F����(�$��$/�>�2��2b<aG��)M�Nw8�����"�
��(u9f��\��&�IU]"��Tj�8\/�������x3~�X�	�;Ow���7`���Mr0��4�wD��p�*b��]$VL�r(���{������=�����6'����xj�|����z������������
�ZY������*��|��N������+������h������w,��3�L&W����q��_���3�e(���d|%*qg7�!@JS{�������W���SYQ�#��*�o�5�5�w=��6�k����.[�n�c�
p,��<vq�����1}L�Ut��B��Z�4���c������:�]�a���Z���L_�F��1I�]�4��=��uhb�*���o��'�Zm\���3�3^�+��N
�f��v}O���"����H
�0�1������Gf��Z������"�p��d��w�����~���Z�G�x9y��@�.J���V]�Y���2��')��fD$����s<���L?���>�xn�#�=���=+��@	�H�H��Q=m4��d2LB�a�UGH)�9������8����^�9����u��GS3��$��L�T����1h�;,5�����8z���:G��:l�:3���"^������p*���V+�qQP�,R��q���6��;�|<���@���������������;�������_��������bH�:k�~>;�����������erprd!!���&���Y�2��`��h�P
��U��t5�M��*��N������]��T����)9���tFr�����Xx�$��:��s��� �������cA_4����7���n�d	��C_4���8fJh�i�Ah�;g�����U/x�dP����a=�0���,��)�������G������w���KS����M��6�
o*�n-�W���T�|��7�b7�
�?�>��'�����tos.���{��e�<'������.A!�K�M��Xp��(G��d1�z��H$���!Yr�"�1'_����_LnEN������ye1��:�����������l1�N�GU
�+�P�{�[���AG�v8@[,��Q����]�g��:��AG��P,-�kj#��|�h���s���\������I9����Z��[�+sUq._E�8Yod��"���[��S��l��owJ��,�F���,�=�3�����Yf������U'�����������{NY���Ev�
�i�
�@�gNnl$���'�r�Y8�Ud[
���=s �������O���f���{#��4t�T
W��*����kt���E<S����hR�$�������1yM]���E��?�H4�x��K
1�6M�K]���������z{xT����n�r� ]R�bV���(�R������BA����6Y��$g�!>�����}�lGF%0#Mg�N��(�f�L ��ZE�|pzvx|�2�;�@Zl32tlb��9����]wv������������h�l�qNpiwY��;ac��r��f0k�1,T�J�m��B���x?X:��3��3LR3�V�)mG��	���U��U�(�b53��t���H��%���M)�f������l<�
\{��i���=�8��<y�e��I/�y��2a�!�Z>[0P��%������M���5�Hko�yIgc��53C��O_��B��Q���tH@��������J.�������5l�����5:�]���-���V[��(@���F�+������F�u��@�����
���Y�5�T�Y�qi2��������_/���W{�<��R�}�dBPs��H7M����c�����T��3y�C�X��^l��s��D)���QO���"��j
��6�%���Y]B���U��|����pq������f������P(bhbT���uMc�1�"T����m����&����hA�$�nW����063�*n�*���c[$�q}!*�}{>�%<H�o���%?'���X�]
}�E{���I��M�������_1�#	���'���jA�^�r��*���dv�ga�o��xp�Z<
�|9�as����i{@In{����	�h,���)��W�����5e����a���#���;��&�L�^�
��G��I�J�E��%�!|�R(.�"	F�G,;��bl� d��^�jlnR���`���/��ElW*��n<�w.��o/��&����|kO����t����xv������|�+6��TC�9~��jckFC'F�����6<R/��d
���Q�}����1�5�T3!�V��>|��|��^�)V��O��J��l:�C�Pz�! yJ���ECxM���= ����N���#�KS�Q���EA��t��������o��z�\�k�8���Fr�2m;��O~��i'��U?��+1�L��P@�e���F��d����s����"l��"�]��tp��n���.1�V>���(eeL^��a��?�rl�d����d��vI���w2����y�� '8��b[�!��&�A��`r����8g��������A�M'�P+����
�Y�N�'&���>@���:�E���������
5��b.�y���qI����3F@i����.8teI��G}���+��?��=������<}��/

����
%����7�UwK��v�{c|��Ip:9��|�<��	��h;��RB���e__�M'h+��:;C������D<c"����~�9��g��M���u~+��yn�mFy�����c�$$�t'TS`����$9f�d��bJ`;�If��zcd�9�%���!�����}4�cv6�8����c-#�����R@@E��E�3���ek�+0��
�7��L.�s��*�����p���.O�c'�}z�c���4�����u^U��������<Y��n��{���z�QW%�W�%?����k�3�������W�T��pc�xC���n+��s+����h6���g�Y����.l���9l1���t�z��(/��������5�r�'�+n2b�8����x����KdV�_�W����3	~"�o���I�@����Ey{6��Fy����_��5�ZE6��v����m�z|&o��
�y��0c���J��Oz�t�S��
d��5��Ko4QrS|u�X�n�.)V���SO�9*����y�e��%����#d!/[�0L�:����91l�B[������M�&4[NUT��R��������x�
�XG��N���6�����=��Sg��������9��'�����8[UQ�����a��`��yrp�|���D���3��T�?0\���Q��RI���aiJC��K����a2
B�s=f("W����p�������b%��j���)>��!�{������BBVc��J��ov��_�{]���8V��3����P����k?
��[I:)AW����,\Q"�T\�A(��������,�*����Q'�m��|{X���"E�o8[[)K9�	I���[K�L5��t7*�R�N����J��:Sr�G��=}������r�N��Mg5����u�����<�(��`|\{7��Wr�W�i�V�����-���n���.���n����>���pE(2����>�w��t�c���84��{�$�H���������]u�� ���|`QM&rD9�QD�q�l�g�-�(%�L.CI@���]y�;|��`�8����%��C���>N��nly+J9P�-��O� ���H��!���/����
��SfFi��G���!�j4��m8d�:����5l��m�P�N������i:���S9�0��N��=��<��G��0l���8��?��;P��+,�94uKw���r��89L�5m"y��#k��O�5���x�^no�;h;����G2�b,0k`���I���|�����NF�+s�b�KE�����%X5���`8�_r|Uf�'dT1>��OKf�R���,Q
5>�� K���z
��j����e�Q\v��=*�����T���U����������+�����i�L~Z ����Q[��$��j
|.�U�}<�>$��*�2;�s�;�%���s��3B�;������p�8�$��!���|l���Th^w.�A]�����2"��Fx��X��I`�x
k=�B*���?���udy��}Q���_��lw������W�K*i�y��}y��f��&]�3e)��N��J��q4��jk��~�o�^���U�[[���/�<�����WQ��uV[7�������5�����uMW>V�k�V"���Ha���y��a�G���;*��$��E������DPJ��;U�~t^EhQg .�f��x���z��A?�`BU}��������`&XY��{z|t��,����;.��^����@e��Z�]��f���4�n&�
<�����b���x</`(�J)|�}`M�)�8'����kJJ[��oy������id"����Ab��$�+�!`X�px����I[f���Y���j{��RN���TV�=��;��_}q�K�|Y�x�x�C|c��B�F���u��@j����-��:@D�l#G�E]�,���>��� �x�A��
$c|VbP����hJ�1$U��V���j�x�A�z4Q�H�u+o�i��x�46k�F*dI��g�&����t�_x/���F��c]J�7V������*DL7V
�Z�I ��")F�M-���Z����Z�W;�����>��.���",�����r�X\�-P���kc/��RJ�X8���<x��X�}e�X��`i�d�YJ�fF?4��0HW����4���$��W<p�6W�{��m���{�
y�~��R����"�2L2�tSEb�A�A|S��7U��q3h��b�LQ��%g�����'�����0SxDW���)Jq3E��.'���n%#��tj�F����6w^�����)��`�����v���1��\`�
��&K��M�"/���
3&���z<j��8����%��o����:m���e!F�<�Q�v������������7\����������a��XS6�}��V�P�]Q+���������v������{�����
0004-wal_decoding-Documentation-for-replication-slots-and.patch.gzapplication/x-patch-gzipDownload
0005-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gzapplication/x-patch-gzipDownload
#75Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#74)
Re: Changeset Extraction v7.6.1

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

[ new patches ]

0001 already needs minor

+ * copied stuff from tuptoaster.c. Perhaps there should be toast_internal.h?

Yes, please. If you can submit a separate patch creating this file
and relocating this stuff there, I will commit it.

+       /*
+        * XXX: It's impolite to ignore our argument and keep decoding until the
+        * current position.
+        */

Eh, what?

+        * We misuse the original meaning of SnapshotData's xip and
subxip fields
+        * to make the more fitting for our needs.
[...]
+        * XXX: Do we want extra fields instead of misusing existing
ones instead?

If we're going to do this, then it surely needs to be documented in
snapshot.h. On the second question, you're not the first hacker to
want to abuse the meanings of the existing fields; SnapshotDirty
already does it. It's tempting to think we need a more principled
approach to this, like what we've done with Node i.e. typedef enum ...
SnapshotType; and then a separate struct definition for each kind, all
beginning with SnapshotType type.

+       /*
+        * XXX: Timeline handling/naming. Do we need to include the timeline in
+        * snapshot's name? Outside of very obscure, user triggered, cases every
+        * LSN should correspond to exactly one timeline?
+        */

I can't really comment intelligently on this, so you need to figure it
out. My off-the-cuff thought is that erring on the side of including
it couldn't hurt anything.

+ * XXX: use hex format for the LSN as well?

Yes, please.

+ /* prepared abort contain a normal
commit abort... */

contains.

+                               /*
+                                * Abort all transactions that we keep
track of that are older
+                                * than the record's oldestRunningXid.
This is the most
+                                * convenient spot for doing so since,
in contrast to shutdown
+                                * or end-of-recovery checkpoints, we
have sufficient
+                                * knowledge to deal with prepared
transactions here.
+                                */

I have no real quibble with this, but I think the comment could be
clarified slightly to state *what* knowledge we have here that we
wouldn't have there.

+ /* only crash recovery/replication needs to care */

I believe I know what you're getting at here, but the next guy might
not. I suggest: "Although these records only exist to serve the needs
of logical decoding, all the work happens as part of crash or archive
recovery, so we don't need to do anything here."

+ * Treat HOT update as normal updates, there
is no useful

s/, t/. T/

+                        * There are cases in which inplace updates
are used without xids
+                        * assigned (like VACUUM), there are others
(like CREATE INDEX
+                        * CONCURRENTLY) where an xid is present. If
an xid was assigned

In-place updates can be used either by XID-bearing transactions (e.g.
in CREATE INDEX CONCURRENTLY) or by XID-less transactions (e.g.
VACUUM). In the former case, ...

+                        * redundant because the commit will do that
as well, but one
+                        * we'll support decoding in-progress
relations, this will be

s/one/once/
s/we'll/we/

+                       /* we don't care about row level locks for now */
+               case XLOG_HEAP_LOCK:
+                       break;

The position of the comment isn't consistent with the comments for the
other WAL record type in this section; that is, it's above rather than
below the case.

+ * transaction's contents as the various caches need to always be

I think you should use "since" or "because" rather than "as" here, and
maybe put a comma before it.

+        * the transaction's invalidations. This currently won't be needed if
+        * we're just skipping over the transaction, since that currently only
+        * happens when starting decoding, after we invalidated all caches, but
+        * transactions in other databases might have touched shared relations.

I'm having trouble understanding what this means, especially the part
after the "but".

+ * Read a HeapTuple as WAL logged by heap_insert, heap_update and
+ * heap_delete, but not by heap_multi_insert into a tuplebuf.

"but not by heap_multi_insert" needs punctuation both before and
after. You can just add a comma after, or change it into a
parenthetical phrase.

As the above comments probably make clear, I'm pretty much happy with decode.c.

+ /* TODO: We got to change that someday soon.. */

Two periods. Maybe "We need to change this some day soon." - and then
follow that with a paragraph explaining what roughly what would need
to be done.

+       /* shorter lines... */
+       slot = MyReplicationSlot;
+
+       /* first some sanity checks that are unlikely to be violated */
+       if (MyReplicationSlot == NULL)
+               elog(ERROR, "cannot perform logical decoding without a
acquired slot");

Can test slot.

+ /* make sure the passed slot is suitable, these are user
facing errors */

Make sure the passed slot is suitable. These are user-facing errors.

+       if (IsTransactionState() &&
+               GetTopTransactionIdIfAny() != InvalidTransactionId)
+               ereport(ERROR,
+                               (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
+                                errmsg("cannot perform changeset
extraction in transaction that has performed writes")));

This is sort of an awkward restriction, as it makes it hard to compose
this feature with others. What underlies the restriction, can we get
rid of it, and if not can we include a comment here explaining why it
exists?

+ * the xlog records didn't result in anyting
relevant for

anything.

+               /* register output plugin name with slot */
+               strncpy(NameStr(slot->data.plugin), plugin,
+                               NAMEDATALEN);
+               NameStr(slot->data.plugin)[NAMEDATALEN - 1] = '\0';

If it's safe to do this without a lock, I don't know why.

More broadly, I wonder why this is_init stuff is in here at all.
Maybe the stuff that happens in the is_init case should be done in the
caller, or another helper function.

+               /* prevent WAL removal as fast as possible */
+               ReplicationSlotsComputeRequiredLSN();

If there's a race here, can't we rejigger the order of operations to
eliminate it? Or is that just too hard and not worth it?

+begin_txn_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn)
+       state.callback_name = "pg_decode_begin_txn";
+       ctx->callbacks.begin_cb(ctx, txn);

I feel that there's a certain lack of naming consistency between these
things. Can we improve that? (and similarly for parallel cases)

+pg_create_decoding_replication_slot(PG_FUNCTION_ARGS)

I thought we were going to have physical and logical slots, not
physical and decoding slots.

+       /* make sure we don't end up with an unreleased slot */
+       PG_TRY();
+       {
...
+       PG_CATCH();
+       {
+               ReplicationSlotRelease();
+               ReplicationSlotDrop(NameStr(*name));
+               PG_RE_THROW();
+       }
+       PG_END_TRY();

I don't think this is a very good idea. The problem with doing things
during error recovery that can themselves fail is that you'll lose the
original error, which is not cool, and maybe even blow out the error
stack. Many people have confuse PG_TRY()/PG_CATCH() with an
exception-handling system, but it's not. One way to fix this is to
put some of the initialization logic in ReplicationSlotCreate() just
prior to calling CreateSlotOnDisk(). If the work that needs to be
done is too complex or protracted to be done there, then I think that
it should be pulled out of the act of creating the replication slot
and made to happen as part of first use, or as a separate operation
like PrepareForLogicalDecoding.

+ * When the client has confirmed flushes >= candidate_xmin_after we can

candidate_xmin_after is not otherwise referenced; incomplete identifier rename?

Nothing in patch 1 sets PROC_IN_LOGICAL_DECODING. Is that right?

+ProcArraySetReplicationSlotXmin(TransactionId xmin, TransactionId catalog_xmin,
+                                                               bool
already_locked)

Maybe Assert(!already_locked || LWLockHeldByMe(ProcArrayLock))

+void
+ProcArrayGetReplicationSlotXmin(TransactionId *xmin,
+
TransactionId *catalog_xmin)
+{
+       LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);

If we need the lock in exclusive mode here, there should be a comment
explaining why. And regardless, there should probably be some sort of
header comment.

+               /*
+                * Acquire spinlock so other backends are guaranteed
to see this in
+                * time - we cannot generally acquire the lwlock here
since we might
+                * be still holding it in an error path.
+                */
+               SpinLockAcquire(&MyReplicationSlot->mutex);
+               MyReplicationSlot->active = false;
+               SpinLockRelease(&MyReplicationSlot->mutex);
+
+               /* might not have been set when we've been a plain slot */
+               LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+               MyPgXact->vacuumFlags &= ~PROC_IN_LOGICAL_DECODING;
+               LWLockRelease(ProcArrayLock);

OK, a couple of things. First, the comment for the first chunk says
we can't acquire the LWLock here, and then the second part acquires an
LWLock. Second, if we're about to dump our PGPROC altogether, why do
we need to update vacuumFlags first? Third, this isn't actually
called anywhere.

+ * At some point in the future it probaly makes sense to have a more elaborate
+ * resource management here, but it's not entirely clear how that would look
+ * like.

s/how/what/

ReorderBufferGetTXN() should get a comment about the performance
impact of this. There's a tiny bit there in ReorderBufferReturnTXN()
but it should be better called out. Should these call the valgrind
macros to make the memory inaccessible while it's being held in cache?

My eyes are starting to glaze over, so more later.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#76Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#75)
Re: Changeset Extraction v7.6.1

On 2014-02-15 17:29:04 -0500, Robert Haas wrote:

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

[ new patches ]

0001 already needs minor

Hm?

If there are conflicts, I'll push/send a rebased tomorrow or monday.

+        * the transaction's invalidations. This currently won't be needed if
+        * we're just skipping over the transaction, since that currently only
+        * happens when starting decoding, after we invalidated all caches, but
+        * transactions in other databases might have touched shared relations.

I'm having trouble understanding what this means, especially the part
after the "but".

Let me rephrase, maybe that will help:

This currently won't be needed if we're just skipping over the
transaction because currenlty we only do so during startup, to get to
the first transaction the client needs. As we have reset the catalog
caches before starting to read WAL and we haven't yet touched any
catalogs there can't be anything to invalidate.

But if we're "forgetting" this commit because it's it happened in
another database, the invalidations might be important, because they
could be for shared catalogs and we might have loaded data into the
relevant syscaches.

Better?

+       if (IsTransactionState() &&
+               GetTopTransactionIdIfAny() != InvalidTransactionId)
+               ereport(ERROR,
+                               (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
+                                errmsg("cannot perform changeset
extraction in transaction that has performed writes")));

This is sort of an awkward restriction, as it makes it hard to compose
this feature with others. What underlies the restriction, can we get
rid of it, and if not can we include a comment here explaining why it
exists?

Well, you can write the result into a table if you're halfway
careful... :)

I think it should be fairly easy to relax the restriction to creating a
slot, but not getting data from it. Do you think that would that be
sufficient?

+               /* register output plugin name with slot */
+               strncpy(NameStr(slot->data.plugin), plugin,
+                               NAMEDATALEN);
+               NameStr(slot->data.plugin)[NAMEDATALEN - 1] = '\0';

If it's safe to do this without a lock, I don't know why.

Well, the worst that could happen is that somebody else doing a SELECT *
FROM pg_replication_slot gets a incomplete plugin name... But we
certainly can hold the spinlock during it if you think that's better.

More broadly, I wonder why this is_init stuff is in here at all.
Maybe the stuff that happens in the is_init case should be done in the
caller, or another helper function.

The reason I moved it in there is that after the walsender patch there
are two callers and the stuff is sufficiently complex that I having it
twice lead to bugs.
The reason it's currenlty the same function is that sufficiently much of
the code would have to be shared that I found it it ugly to split. I'll
have a look whether I can figure something out.

+               /* prevent WAL removal as fast as possible */
+               ReplicationSlotsComputeRequiredLSN();

If there's a race here, can't we rejigger the order of operations to
eliminate it? Or is that just too hard and not worth it?

Yes, there's a small race which at the very least should be properly
documented.

Hm. Yes, I think we can plug the hole. If the race condition occurs we'd
take slightly longer to startup, which isn't bad. Will fix.

+begin_txn_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn)
+       state.callback_name = "pg_decode_begin_txn";
+       ctx->callbacks.begin_cb(ctx, txn);

I feel that there's a certain lack of naming consistency between these
things. Can we improve that? (and similarly for parallel cases)

+pg_create_decoding_replication_slot(PG_FUNCTION_ARGS)

I thought we were going to have physical and logical slots, not
physical and decoding slots.

Ok.

+       /* make sure we don't end up with an unreleased slot */
+       PG_TRY();
+       {
...
+       PG_CATCH();
+       {
+               ReplicationSlotRelease();
+               ReplicationSlotDrop(NameStr(*name));
+               PG_RE_THROW();
+       }
+       PG_END_TRY();

I don't think this is a very good idea. The problem with doing things
during error recovery that can themselves fail is that you'll lose the
original error, which is not cool, and maybe even blow out the error
stack. Many people have confuse PG_TRY()/PG_CATCH() with an
exception-handling system, but it's not. One way to fix this is to
put some of the initialization logic in ReplicationSlotCreate() just
prior to calling CreateSlotOnDisk(). If the work that needs to be
done is too complex or protracted to be done there, then I think that
it should be pulled out of the act of creating the replication slot
and made to happen as part of first use, or as a separate operation
like PrepareForLogicalDecoding.

I think what should be done here is adding a drop_on_release flag. As
soon as everything important is done, it gets unset.

With some small changes that'd be highly useful for pg_basebackup as
well, because it could simply create a slot to prevent removal of
important WAL. Hm, maybe name it release_on_error, and call it from the
error locations.
You previously (IM?) argued that that'd be problematic because of locks,
but in all the error handling situations we'll already have released
lwlocks. And we rely on being able to tacke lwlocks there,
c.f. TerminateBufferIO et al.

+ * When the client has confirmed flushes >= candidate_xmin_after we can

candidate_xmin_after is not otherwise referenced; incomplete identifier rename?

Nothing in patch 1 sets PROC_IN_LOGICAL_DECODING. Is that right?

CreateDecodingContext() does.

ReorderBufferGetTXN() should get a comment about the performance
impact of this. There's a tiny bit there in ReorderBufferReturnTXN()
but it should be better called out. Should these call the valgrind
macros to make the memory inaccessible while it's being held in cache?

Hm, I think it does call the valgrind stuff?
VALGRIND_MAKE_MEM_UNDEFINED(txn, sizeof(ReorderBufferTXN));
VALGRIND_MAKE_MEM_DEFINED(&txn->node, sizeof(txn->node));

My eyes are starting to glaze over, so more later.

Thanks! Will address asap.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#77Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#75)
Re: Changeset Extraction v7.6.1

On 2014-02-15 17:29:04 -0500, Robert Haas wrote:

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

[ new patches ]

0001 already needs minor

+ * copied stuff from tuptoaster.c. Perhaps there should be toast_internal.h?

Yes, please. If you can submit a separate patch creating this file
and relocating this stuff there, I will commit it.

I started to work on that, but I am not sure we actually need it
anymore. tuptoaster.h isn't included in that many places, so perhaps we
should just add it there?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#78Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#74)
Re: Changeset Extraction v7.6.1

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

[ patches ]

Having now had a little bit of opportunity to reflect on the State Of
This Patch, I'd like to step back from the minutia upon which I've
been commenting in my previous emails and articulate three high-level
concerns about this patch. In so doing, I would like to specifically
request that other folks on this mailing list comment on the extent to
which they do or do not believe these concerns to be valid. I believe
I've mentioned all of these concerns at least to some degree
previously, but they've been mixed in with other things, so I want to
take this opportunity to call them out more clearly.

1. How safe is it to try to do decoding inside of a regular backend?
What we're doing here is entering a special mode where we forbid the
use of regular snapshots in favor of requiring the use of "decoding
snapshots", and forbid access to non-catalog relations. We then run
through the decoding process; and then exit back into regular mode.
On entering and on exiting this special mode, we
InvalidateSystemCaches(). I don't see a big problem with having
special backends (e.g. walsender) use this special mode, but I'm less
convinced that it's wise to try to set things up so that we can switch
back and forth between decoding mode and regular mode in a single
backend. I worry that won't end up working out very cleanly, and I
think the prohibition against using this special mode in an
XID-bearing transaction is merely a small downpayment on future pain
in this area. That having been said, I can't pretend at this point
either to understand the genesis of this particular restriction or
what other problems are likely to crop up in trying to allow this
mode-switching. So it's possible that I'm overblowing it, but it's
makin' me nervous.

2. I think the snapshot-export code is fundamentally misdesigned. As
I said before, the idea that we're going to export one single snapshot
at one particular point in time strikes me as extremely short-sighted.
For example, consider one-to-many replication where clients may join
or depart the replication group at any time. Whenever somebody joins,
we just want a <snapshot, LSN> pair such that they can apply all
changes after the LSN except for XIDs that would have been visible to
the snapshot. And in fact, we don't even need any special machinery
for that; the client can just make a connection and *take a snapshot*
once decoding is initialized enough. This code is going to great
pains to be able to export a snapshot at the precise point when all
transactions that were running in the first xl_running_xacts record
seen after the start of decoding have ended, but there's nothing
magical about that point, except that it's the first point at which a
freshly-taken snapshot is guaranteed to be good enough to establish an
initial state for any table in the database.

But do you really want to keep that snapshot around long enough to
copy the entire database? I bet you don't: if the database is big,
holding back xmin for long enough to copy the whole thing isn't likely
to be fun. You might well want to copy one table at a time, with
progressively newer snapshots, and apply to each table only those
transactions that weren't part of the initial snapshot for that table.
Many other patterns are possible. What you've got baked in here
right now is suitable only for the simplest imaginable case, and yet
we're paying a substantial price in implementation complexity for it.
Frankly, this code is *ugly*; the fact that SnapBuildExportSnapshot()
needs to start a transaction so that it can push out a snapshot. I
think that's a pretty awful abuse of the transaction machinery, and
the whole point of it, AFAICS, is to eliminate flexibility that we'd
have with simpler approaches.

3. As this feature is proposed, the only plugin we'll ship with 9.4 is
a test_decoding plugin which, as its own documentation says, "doesn't
do anything especially useful." What exactly do we gain by forcing
users who want to make use of these new capabilities to write C code?
You previously stated that it wasn't possible (or there wasn't time)
to write something generic, but how hard is it, really? Sure, people
who are hard-core should have the option to write C code, and I'm
happy that they do. But that shouldn't, IMHO anyway, be a requirement
to use that feature, and I'm having trouble understanding why we're
making it one. The test_decoding plugin doesn't seem tremendously
much simpler than something that someone could actually use, so why
not make that the goal?

Thanks,

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#79Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#78)
Re: Changeset Extraction v7.6.1

Robert Haas <robertmhaas@gmail.com> writes:

Having now had a little bit of opportunity to reflect on the State Of
This Patch, I'd like to step back from the minutia upon which I've
been commenting in my previous emails and articulate three high-level
concerns about this patch. In so doing, I would like to specifically
request that other folks on this mailing list comment on the extent to
which they do or do not believe these concerns to be valid.
...

1. How safe is it to try to do decoding inside of a regular backend?
What we're doing here is entering a special mode where we forbid the
use of regular snapshots in favor of requiring the use of "decoding
snapshots", and forbid access to non-catalog relations. We then run
through the decoding process; and then exit back into regular mode.
On entering and on exiting this special mode, we
InvalidateSystemCaches().

How often is such a mode switch expected to happen? I would expect
frequent use of InvalidateSystemCaches() to be pretty much disastrous
for performance, even absent any of the possible bugs you're worried
about. It would likely be better to design things so that a decoder
backend does only that.

2. I think the snapshot-export code is fundamentally misdesigned.

Your concerns here sound reasonable, but I can't say I've got any
special insight into it.

3. As this feature is proposed, the only plugin we'll ship with 9.4 is
a test_decoding plugin which, as its own documentation says, "doesn't
do anything especially useful." What exactly do we gain by forcing
users who want to make use of these new capabilities to write C code?

TBH, if that's all we're going to ship, I'm going to vote against
committing this patch to 9.4 at all. Let it wait till 9.5 when we
might be able to build something useful on it. To point out just
one obvious problem, how much confidence can we have in the APIs
being right if there are no usable clients? Even if they're right,
what benefit do we get from freezing them one release before anything
useful is going to happen?

The most recent precedent I can think of is the FDW APIs, which I'd
be the first to admit are still in flux. But we didn't ship anything
there without non-toy contrib modules to exercise it. If we had,
we'd certainly have regretted it, because in the creation of those
contrib modules we found flaws in the initial design.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#80Robert Haas
robertmhaas@gmail.com
In reply to: Tom Lane (#79)
Re: Changeset Extraction v7.6.1

On Mon, Feb 17, 2014 at 9:10 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

3. As this feature is proposed, the only plugin we'll ship with 9.4 is
a test_decoding plugin which, as its own documentation says, "doesn't
do anything especially useful." What exactly do we gain by forcing
users who want to make use of these new capabilities to write C code?

TBH, if that's all we're going to ship, I'm going to vote against
committing this patch to 9.4 at all. Let it wait till 9.5 when we
might be able to build something useful on it. To point out just
one obvious problem, how much confidence can we have in the APIs
being right if there are no usable clients? Even if they're right,
what benefit do we get from freezing them one release before anything
useful is going to happen?

I actually have a lot of confidence that the APIs are almost entirely
right, except maybe for the snapshot-related stuff and possibly one or
two other minor details. And I have every confidence that 2ndQuadrant
is going to put out decoding modules that do useful stuff. I also
assume Slony is going to ship one at some point. EnterpriseDB's xDB
replication server will need one, so someone at EDB will have to go
write that. And if Bucardo or Londiste want to use this
infrastructure, they'll need their own, too. What I don't understand
is why it's cool to make each of those replication solutions bring its
own to the table. I mean if they want to, so that they can generate
exactly the format they want with no extra overhead, sure, cool. What
I don't understand is why we're not taking the test_decoding module,
polishing it up a little to produce some nice, easily
machine-parseable output, calling it basic_decoding, and shipping
that. Then people who want something else can build it, but people
who are happy with something basic will already have it.

What I actually suspect is going to happen if we ship this as-is is
that people are going to start building logical replication solutions
on top of the test_decoding module even though it explicitly says that
it's just test code. This is *really* cool technology and people are
*hungry* for it. But writing C is hard, so if there's not a polished
plugin available, I bet people are going to try to use the
not-polished one. I think we try to get out ahead of that.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#81Peter Geoghegan
pg@heroku.com
In reply to: Robert Haas (#80)
Re: Changeset Extraction v7.6.1

On Mon, Feb 17, 2014 at 6:35 PM, Robert Haas <robertmhaas@gmail.com> wrote:

What I actually suspect is going to happen if we ship this as-is is
that people are going to start building logical replication solutions
on top of the test_decoding module even though it explicitly says that
it's just test code. This is *really* cool technology and people are
*hungry* for it. But writing C is hard, so if there's not a polished
plugin available, I bet people are going to try to use the
not-polished one. I think we try to get out ahead of that.

Tom made a comparison with FDWs, so I'll make another. The Multicorn
module made FDW authorship much more accessible by wrapping it in a
Python interface, I believe with some success. I don't want to stand
in the way of building a fully-featured test_decoding module, but I
think that those that would misuse test_decoding as it currently
stands can be redirected to a third-party wrapper. As you say, it's
pretty cool stuff, so it seems likely that someone will build one for
us.

--
Peter Geoghegan

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#82Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#78)
Re: Changeset Extraction v7.6.1

Hi Robert,

On 2014-02-17 20:31:34 -0500, Robert Haas wrote:

1. How safe is it to try to do decoding inside of a regular backend?
What we're doing here is entering a special mode where we forbid the
use of regular snapshots in favor of requiring the use of "decoding
snapshots", and forbid access to non-catalog relations. We then run
through the decoding process; and then exit back into regular mode.
On entering and on exiting this special mode, we
InvalidateSystemCaches(). I don't see a big problem with having
special backends (e.g. walsender) use this special mode, but I'm less
convinced that it's wise to try to set things up so that we can switch
back and forth between decoding mode and regular mode in a single
backend.

The main reason the SQL interface exists is that it's awfully hard to
use isolationtester, pg_regress et al when the output isn't also visible
via SQL. We tried hacking things in other ways, but that's what it came
down to. If you recall, previously the SQL changes interface was only in
a test_logical_decoding extension, because I wasn't sure it's all that
interesting for real usecases.
It's sure nice for testing things though.

I worry that won't end up working out very cleanly, and I
think the prohibition against using this special mode in an
XID-bearing transaction is merely a small downpayment on future pain
in this area.

That restriction is in principle only needed when creating the slot, not
when getting changes. The only problem is that some piece of code
doesn't know about it.

The reason it exists are twofold: One is that when looking for an
initial snapshot, we wait for concurrent transactions to end. If we'd
wait for the transaction itself we'd be in trouble, it could never
happen. The second reason is that the code do a XactLockTableWait() to
"visualize" it's waiting, so isolatester knows it should background the
command. It's not good to wait on itself.
But neither is actually needed when not creating the slot, the code just
needs to be told about that.

That having been said, I can't pretend at this point
either to understand the genesis of this particular restriction or
what other problems are likely to crop up in trying to allow this
mode-switching. So it's possible that I'm overblowing it, but it's
makin' me nervous.

I am not terribly concerned, but I can understand where you are coming
from. I think for replication solutions this isn't going to be needed
but it's way much more handy for testing and such.

2. I think the snapshot-export code is fundamentally misdesigned. As
I said before, the idea that we're going to export one single snapshot
at one particular point in time strikes me as extremely short-sighted.

I don't think so. It's precisely what you need to implement a simple
replication solution. Yes, there are usecases that could benefit from
more possibilities, but that's always the case.

For example, consider one-to-many replication where clients may join
or depart the replication group at any time. Whenever somebody joins,
we just want a <snapshot, LSN> pair such that they can apply all
changes after the LSN except for XIDs that would have been visible to
the snapshot.

And? They need to create individual replication slots, which each will
get a snapshot.

And in fact, we don't even need any special machinery
for that; the client can just make a connection and *take a snapshot*
once decoding is initialized enough.

No, they can't. Two reasons: For one the commit order between snapshots
and WAL isn't necessarily the same. For another, clients now need logic
to detect whether a transaction's contents has already been applied or
has not been applied yet, that's nontrivial.

This code is going to great
pains to be able to export a snapshot at the precise point when all
transactions that were running in the first xl_running_xacts record
seen after the start of decoding have ended, but there's nothing
magical about that point, except that it's the first point at which a
freshly-taken snapshot is guaranteed to be good enough to establish an
initial state for any table in the database.

I still maintain that there's something magic about that moment. It's
when all *future* (from the POV of the snapshot) changes will be
streamed, and all *past* changes are included in the exported snapshot.

But do you really want to keep that snapshot around long enough to
copy the entire database? I bet you don't: if the database is big,
holding back xmin for long enough to copy the whole thing isn't likely
to be fun.

Well, that's how pg_dump works, it's not this patch's problem to fix
that.

You might well want to copy one table at a time, with
progressively newer snapshots, and apply to each table only those
transactions that weren't part of the initial snapshot for that table.
Many other patterns are possible. What you've got baked in here
right now is suitable only for the simplest imaginable case, and yet
we're paying a substantial price in implementation complexity for it.

Which implementation complexity are you talking about? The relevant code
is maybe 50-60 lines?

Frankly, this code is *ugly*; the fact that SnapBuildExportSnapshot()
needs to start a transaction so that it can push out a snapshot. I
think that's a pretty awful abuse of the transaction machinery, and
the whole point of it, AFAICS, is to eliminate flexibility that we'd
have with simpler approaches.

It's not my idea that the snapshot importing requires that
restriction. We could possibly lift it and replace it by another check,
but I don't really see the problem.

3. As this feature is proposed, the only plugin we'll ship with 9.4 is
a test_decoding plugin which, as its own documentation says, "doesn't
do anything especially useful." What exactly do we gain by forcing
users who want to make use of these new capabilities to write C code?

It gains us to have a output plugin in which we can easily demonstrate
features so they can be tested in the regression tests. Which I find to
be rather important.
Just like e.g. the test_shm_mq stuff doesn't do anything really useful.

You previously stated that it wasn't possible (or there wasn't time)
to write something generic, but how hard is it, really? Sure, people
who are hard-core should have the option to write C code, and I'm
happy that they do. But that shouldn't, IMHO anyway, be a requirement
to use that feature, and I'm having trouble understanding why we're
making it one.

I think the commmunity will step up and provide further plugins. In
fact, there's already been a json plugin on the mailinglist.

The test_decoding plugin doesn't seem tremendously
much simpler than something that someone could actually use, so why
not make that the goal?

For one, it being a designated toy plugin allows us to easily change it,
to showcase/test new features. For another, I still don't agree that
it's easy to agree to an output format. I think we should include some
that matured into 9.5.

Thanks,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#83Andres Freund
andres@2ndquadrant.com
In reply to: Tom Lane (#79)
Re: Changeset Extraction v7.6.1

On 2014-02-17 21:10:26 -0500, Tom Lane wrote:

Robert Haas <robertmhaas@gmail.com> writes:

1. How safe is it to try to do decoding inside of a regular backend?
What we're doing here is entering a special mode where we forbid the
use of regular snapshots in favor of requiring the use of "decoding
snapshots", and forbid access to non-catalog relations. We then run
through the decoding process; and then exit back into regular mode.
On entering and on exiting this special mode, we
InvalidateSystemCaches().

How often is such a mode switch expected to happen? I would expect
frequent use of InvalidateSystemCaches() to be pretty much disastrous
for performance, even absent any of the possible bugs you're worried
about. It would likely be better to design things so that a decoder
backend does only that.

Very infrequently. When it's starting to decode, and when it's
ending. When used via walsender, that should only happen at connection
start/end which surely shouldn't be frequent.
It's more frequent when using the SQL interface, but since that's not a
streaming interface on a busy server there still would be a couple of
megabytes of transactions to decode for one reset.

3. As this feature is proposed, the only plugin we'll ship with 9.4 is
a test_decoding plugin which, as its own documentation says, "doesn't
do anything especially useful." What exactly do we gain by forcing
users who want to make use of these new capabilities to write C code?

TBH, if that's all we're going to ship, I'm going to vote against
committing this patch to 9.4 at all. Let it wait till 9.5 when we
might be able to build something useful on it.

There *are* useful things around already. We didn't include postgres_fdw
in the same release as the fdw code either? I don't see why this should
be held to a different standard.

To point out just
one obvious problem, how much confidence can we have in the APIs
being right if there are no usable clients?

Because there *are* clients. They just don't sound likely to either be
suitable for core code (to specialized) or have already been submitted
(the json plugin).

There's a whole replication suite built ontop of this, to a good degree
to just test it. So I am fairly confident that the most important parts
are covered. There sure is additional features I want, but that's not
surprising.

The most recent precedent I can think of is the FDW APIs, which I'd
be the first to admit are still in flux. But we didn't ship anything
there without non-toy contrib modules to exercise it. If we had,
we'd certainly have regretted it, because in the creation of those
contrib modules we found flaws in the initial design.

Which non-toy fdw was there? file_fdw was in 9.1, but that's a toy. And
*8.4* had CREATE FOREIGN DATA WRAPPER, without it doing anything...

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#84Andres Freund
andres@2ndquadrant.com
In reply to: Peter Geoghegan (#81)
Re: Changeset Extraction v7.6.1

On 2014-02-17 18:49:59 -0800, Peter Geoghegan wrote:

On Mon, Feb 17, 2014 at 6:35 PM, Robert Haas <robertmhaas@gmail.com> wrote:

What I actually suspect is going to happen if we ship this as-is is
that people are going to start building logical replication solutions
on top of the test_decoding module even though it explicitly says that
it's just test code. This is *really* cool technology and people are
*hungry* for it. But writing C is hard, so if there's not a polished
plugin available, I bet people are going to try to use the
not-polished one. I think we try to get out ahead of that.

Tom made a comparison with FDWs, so I'll make another. The Multicorn
module made FDW authorship much more accessible by wrapping it in a
Python interface, I believe with some success. I don't want to stand
in the way of building a fully-featured test_decoding module, but I
think that those that would misuse test_decoding as it currently
stands can be redirected to a third-party wrapper. As you say, it's
pretty cool stuff, so it seems likely that someone will build one for
us.

Absolutely. I *sure* hope somebody is going to build such an
abstraction. I am not entirely sure how it'd look like, but ...

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#85Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#80)
Re: Changeset Extraction v7.6.1

On 2014-02-17 21:35:23 -0500, Robert Haas wrote:

What
I don't understand is why we're not taking the test_decoding module,
polishing it up a little to produce some nice, easily
machine-parseable output, calling it basic_decoding, and shipping
that. Then people who want something else can build it, but people
who are happy with something basic will already have it.

Because every project is going to need their own plugin
*anyway*. Londiste, slony sure are going to ignore changes to relations
they don't need. Querying their own metadata. They will want
compatibility to the earlier formats as far as possible. Sometime not
too far away they will want to optionally support binary output because
it's so much faster.
There's just not much chance that either of these will be able to agree
on a format short term.

So, possibly we could agree to something that consumers *outside* of
replication could use.

What I actually suspect is going to happen if we ship this as-is is
that people are going to start building logical replication solutions
on top of the test_decoding module even though it explicitly says that
it's just test code. This is *really* cool technology and people are
*hungry* for it. But writing C is hard, so if there's not a polished
plugin available, I bet people are going to try to use the
not-polished one. I think we try to get out ahead of that.

I really hope there will be nicer ones by the time 9.4 is
released. Euler did send in a json plugin
http://archives.postgresql.org/message-id/52A5BFAE.1040209%2540timbira.com.br
, but there hasn't too much feedback yet. It's hard to start discussing
something that needs a couple of patches to pg before you can develop
your own patch...

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#86Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#76)
Re: Changeset Extraction v7.6.1

On Sat, Feb 15, 2014 at 6:59 PM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-15 17:29:04 -0500, Robert Haas wrote:

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

[ new patches ]

0001 already needs minor

Hm?

If there are conflicts, I'll push/send a rebased tomorrow or monday.

As you guessed, the missing word was "rebasing". It's a trivial
conflict though, so please don't feel the need to repost just for
that.

+        * the transaction's invalidations. This currently won't be needed if
+        * we're just skipping over the transaction, since that currently only
+        * happens when starting decoding, after we invalidated all caches, but
+        * transactions in other databases might have touched shared relations.

I'm having trouble understanding what this means, especially the part
after the "but".

Let me rephrase, maybe that will help:

This currently won't be needed if we're just skipping over the
transaction because currenlty we only do so during startup, to get to
the first transaction the client needs. As we have reset the catalog
caches before starting to read WAL and we haven't yet touched any
catalogs there can't be anything to invalidate.

But if we're "forgetting" this commit because it's it happened in
another database, the invalidations might be important, because they
could be for shared catalogs and we might have loaded data into the
relevant syscaches.

Better?

Much! Please include that text, or something like it.

+       if (IsTransactionState() &&
+               GetTopTransactionIdIfAny() != InvalidTransactionId)
+               ereport(ERROR,
+                               (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
+                                errmsg("cannot perform changeset
extraction in transaction that has performed writes")));

This is sort of an awkward restriction, as it makes it hard to compose
this feature with others. What underlies the restriction, can we get
rid of it, and if not can we include a comment here explaining why it
exists?

Well, you can write the result into a table if you're halfway
careful... :)

I think it should be fairly easy to relax the restriction to creating a
slot, but not getting data from it. Do you think that would that be
sufficient?

That would be a big improvement, for sure, and might be entirely sufficient.

+               /* register output plugin name with slot */
+               strncpy(NameStr(slot->data.plugin), plugin,
+                               NAMEDATALEN);
+               NameStr(slot->data.plugin)[NAMEDATALEN - 1] = '\0';

If it's safe to do this without a lock, I don't know why.

Well, the worst that could happen is that somebody else doing a SELECT *
FROM pg_replication_slot gets a incomplete plugin name... But we
certainly can hold the spinlock during it if you think that's better.

Isn't the worst thing that can happen that they copy garbage out of
the buffer, because the new name is longer than the old and only
partially written?

More broadly, I wonder why this is_init stuff is in here at all.
Maybe the stuff that happens in the is_init case should be done in the
caller, or another helper function.

The reason I moved it in there is that after the walsender patch there
are two callers and the stuff is sufficiently complex that I having it
twice lead to bugs.
The reason it's currenlty the same function is that sufficiently much of
the code would have to be shared that I found it it ugly to split. I'll
have a look whether I can figure something out.

I was thinking that the is_init portion could perhaps be done first,
in a *previous* function call, and adjusted in such a way that the
non-is-init path can be used for both case here.

I don't think this is a very good idea. The problem with doing things
during error recovery that can themselves fail is that you'll lose the
original error, which is not cool, and maybe even blow out the error
stack. Many people have confuse PG_TRY()/PG_CATCH() with an
exception-handling system, but it's not. One way to fix this is to
put some of the initialization logic in ReplicationSlotCreate() just
prior to calling CreateSlotOnDisk(). If the work that needs to be
done is too complex or protracted to be done there, then I think that
it should be pulled out of the act of creating the replication slot
and made to happen as part of first use, or as a separate operation
like PrepareForLogicalDecoding.

I think what should be done here is adding a drop_on_release flag. As
soon as everything important is done, it gets unset.

That might be more elegant, but I don't think it really fixes
anything, because backing stuff out from on disk can fail. AIUI, your
whole concern here is that you don't want the slot creation to fail
halfway through and leave behind the slot, but what you've got here
doesn't prevent that; it just makes it less likely. The more I think
about it, the more I think you're trying to pack stuff into slot
creation that really ought to be happening on first use.

ReorderBufferGetTXN() should get a comment about the performance
impact of this. There's a tiny bit there in ReorderBufferReturnTXN()
but it should be better called out. Should these call the valgrind
macros to make the memory inaccessible while it's being held in cache?

Hm, I think it does call the valgrind stuff?
VALGRIND_MAKE_MEM_UNDEFINED(txn, sizeof(ReorderBufferTXN));
VALGRIND_MAKE_MEM_DEFINED(&txn->node, sizeof(txn->node));

That's there in ReorderBufferReturnTXN, but don't you need something
in ReorderBufferGetTXN? Maybe not.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#87Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#77)
Re: Changeset Extraction v7.6.1

On Sun, Feb 16, 2014 at 12:12 PM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-15 17:29:04 -0500, Robert Haas wrote:

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

[ new patches ]

0001 already needs minor

+ * copied stuff from tuptoaster.c. Perhaps there should be toast_internal.h?

Yes, please. If you can submit a separate patch creating this file
and relocating this stuff there, I will commit it.

I started to work on that, but I am not sure we actually need it
anymore. tuptoaster.h isn't included in that many places, so perhaps we
should just add it there?

That seems fine to me.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#88Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#82)
Re: Changeset Extraction v7.6.1

On Tue, Feb 18, 2014 at 4:07 AM, Andres Freund <andres@2ndquadrant.com> wrote:

2. I think the snapshot-export code is fundamentally misdesigned. As
I said before, the idea that we're going to export one single snapshot
at one particular point in time strikes me as extremely short-sighted.

I don't think so. It's precisely what you need to implement a simple
replication solution. Yes, there are usecases that could benefit from
more possibilities, but that's always the case.

For example, consider one-to-many replication where clients may join
or depart the replication group at any time. Whenever somebody joins,
we just want a <snapshot, LSN> pair such that they can apply all
changes after the LSN except for XIDs that would have been visible to
the snapshot.

And? They need to create individual replication slots, which each will
get a snapshot.

So we have to wait for startup N times, and transmit the change stream
N times, instead of once? Blech.

And in fact, we don't even need any special machinery
for that; the client can just make a connection and *take a snapshot*
once decoding is initialized enough.

No, they can't. Two reasons: For one the commit order between snapshots
and WAL isn't necessarily the same.

So what?

For another, clients now need logic
to detect whether a transaction's contents has already been applied or
has not been applied yet, that's nontrivial.

My point is, I think we should be trying to *make* that trivial,
rather than doing this.

3. As this feature is proposed, the only plugin we'll ship with 9.4 is
a test_decoding plugin which, as its own documentation says, "doesn't
do anything especially useful." What exactly do we gain by forcing
users who want to make use of these new capabilities to write C code?

It gains us to have a output plugin in which we can easily demonstrate
features so they can be tested in the regression tests. Which I find to
be rather important.
Just like e.g. the test_shm_mq stuff doesn't do anything really useful.

It definitely doesn't, but this patch is a lot closer to being done
than parallel query is, so I'm not sure it's a fair comparison.

The test_decoding plugin doesn't seem tremendously
much simpler than something that someone could actually use, so why
not make that the goal?

For one, it being a designated toy plugin allows us to easily change it,
to showcase/test new features. For another, I still don't agree that
it's easy to agree to an output format. I think we should include some
that matured into 9.5.

I regret that more effort has not been made in that area.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#89Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#85)
Re: Changeset Extraction v7.6.1

On Tue, Feb 18, 2014 at 4:33 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-17 21:35:23 -0500, Robert Haas wrote:

What
I don't understand is why we're not taking the test_decoding module,
polishing it up a little to produce some nice, easily
machine-parseable output, calling it basic_decoding, and shipping
that. Then people who want something else can build it, but people
who are happy with something basic will already have it.

Because every project is going to need their own plugin
*anyway*. Londiste, slony sure are going to ignore changes to relations
they don't need. Querying their own metadata. They will want
compatibility to the earlier formats as far as possible. Sometime not
too far away they will want to optionally support binary output because
it's so much faster.
There's just not much chance that either of these will be able to agree
on a format short term.

Ah, so part of what you're expecting the output plugin to do is
filtering. I can certainly see where there might be considerable
variation between solutions in that area - but I think that's separate
from the question of formatting per se. Although I think we should
have an in-core output plugin with filtering capabilities eventually,
I'm happy to define that as out of scope for 9.4. But isn't there a
way that we can ship something that will due for people who want to
just see the database's entire change stream float by?

TBH, as compared to what you've got now, I think this mostly boils
down to a question of quoting and escaping. I'm not really concerned
with whether we ship something that's perfectly efficient, or that has
filtering capabilities, or that has a lot of fancy bells and whistles.
What I *am* concerned about is that if the user updates a text field
that contains characters like " or ' or : or [ or ] or , that somebody
might be using as delimiters in the output format, that a program can
still parse that output format and reliably determine what the actual
change was. I don't care all that much whether we use JSON or CSV or
something custom, but the data that gets spit out should not have
SQL-injection-like vulnerabilities.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#90Euler Taveira
euler@timbira.com.br
In reply to: Andres Freund (#85)
Re: Changeset Extraction v7.6.1

On 18-02-2014 06:33, Andres Freund wrote:

I really hope there will be nicer ones by the time 9.4 is
released. Euler did send in a json plugin
http://archives.postgresql.org/message-id/52A5BFAE.1040209%2540timbira.com.br
, but there hasn't too much feedback yet. It's hard to start discussing
something that needs a couple of patches to pg before you can develop
your own patch...

BTW, I've updated that code to reflect the recent changes in the API and
publish it in [1]https://github.com/eulerto/wal2json. This version is based on the Andres' branch
xlog-decoding-rebasing-remapping. I'll continue to polish this code.

Regards,

[1]: https://github.com/eulerto/wal2json

--
Euler Taveira Timbira - http://www.timbira.com.br/
PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#91Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#86)
Re: Changeset Extraction v7.6.1

Hi,

On 2014-02-19 13:01:02 -0500, Robert Haas wrote:

I think it should be fairly easy to relax the restriction to creating a
slot, but not getting data from it. Do you think that would that be
sufficient?

That would be a big improvement, for sure, and might be entirely sufficient.

Turned out to be a 5 line change + tests or something... Pushed.

I don't think this is a very good idea. The problem with doing things
during error recovery that can themselves fail is that you'll lose the
original error, which is not cool, and maybe even blow out the error
stack. Many people have confuse PG_TRY()/PG_CATCH() with an
exception-handling system, but it's not. One way to fix this is to
put some of the initialization logic in ReplicationSlotCreate() just
prior to calling CreateSlotOnDisk(). If the work that needs to be
done is too complex or protracted to be done there, then I think that
it should be pulled out of the act of creating the replication slot
and made to happen as part of first use, or as a separate operation
like PrepareForLogicalDecoding.

I think what should be done here is adding a drop_on_release flag. As
soon as everything important is done, it gets unset.

That might be more elegant, but I don't think it really fixes
anything, because backing stuff out from on disk can fail.

If the slot is marked as "drop_on_release" during creation, and we fail
during removal, it will just be dropped on the next startup. That seems
ok to me?

I still think it's not really important to put much effort in the "disk
stuff fails" case, it's entirely hypothetical. If that fails you have
*so* much huger problems, a leftover slot is the least of you problems.

AIUI, your
whole concern here is that you don't want the slot creation to fail
halfway through and leave behind the slot, but what you've got here
doesn't prevent that; it just makes it less likely. The more I think
about it, the more I think you're trying to pack stuff into slot
creation that really ought to be happening on first use.

Well, having a leftover slot that never succeeded being created is going
to be confusing lots of people, especially as it will not rollback or
something. That's why I think it's important to make it unlikely.
The typical reasons for failing are stuff like a output plugin that
doesn't exist or being interrupted while initializing.

I can sympathize with the "too much during init" argument, but I don't
see how moving stuff to the first call would get rid of the problems. If
we fail later it's going to be just as confusing.

ReorderBufferGetTXN() should get a comment about the performance
impact of this. There's a tiny bit there in ReorderBufferReturnTXN()
but it should be better called out. Should these call the valgrind
macros to make the memory inaccessible while it's being held in cache?

Hm, I think it does call the valgrind stuff?
VALGRIND_MAKE_MEM_UNDEFINED(txn, sizeof(ReorderBufferTXN));
VALGRIND_MAKE_MEM_DEFINED(&txn->node, sizeof(txn->node));

That's there in ReorderBufferReturnTXN, but don't you need something
in ReorderBufferGetTXN? Maybe not.

Don't think so, it marks the memory as undefined, which allows writes,
but will warn on reads. We could additionally mark the memory as
inaccessible disallowing writes, but I don't really that catching much.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#92Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#89)
Re: Changeset Extraction v7.6.1

On 2014-02-19 13:31:06 -0500, Robert Haas wrote:

TBH, as compared to what you've got now, I think this mostly boils
down to a question of quoting and escaping. I'm not really concerned
with whether we ship something that's perfectly efficient, or that has
filtering capabilities, or that has a lot of fancy bells and whistles.
What I *am* concerned about is that if the user updates a text field
that contains characters like " or ' or : or [ or ] or , that somebody
might be using as delimiters in the output format, that a program can
still parse that output format and reliably determine what the actual
change was. I don't care all that much whether we use JSON or CSV or
something custom, but the data that gets spit out should not have
SQL-injection-like vulnerabilities.

If it's just that, I am *perfectly* happy to change it. What I do not
want is arguments like "I don't want the type information, that's
pointless" because it's actually really important for regression
testing.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#93Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#88)
Re: Changeset Extraction v7.6.1

On 2014-02-19 13:07:11 -0500, Robert Haas wrote:

On Tue, Feb 18, 2014 at 4:07 AM, Andres Freund <andres@2ndquadrant.com> wrote:

2. I think the snapshot-export code is fundamentally misdesigned. As
I said before, the idea that we're going to export one single snapshot
at one particular point in time strikes me as extremely short-sighted.

I don't think so. It's precisely what you need to implement a simple
replication solution. Yes, there are usecases that could benefit from
more possibilities, but that's always the case.

For example, consider one-to-many replication where clients may join
or depart the replication group at any time. Whenever somebody joins,
we just want a <snapshot, LSN> pair such that they can apply all
changes after the LSN except for XIDs that would have been visible to
the snapshot.

And? They need to create individual replication slots, which each
will get a snapshot.

So we have to wait for startup N times, and transmit the change stream
N times, instead of once? Blech.

I can't get too excited about this. If we later want to add a command to
clone an existing slot, sure, that's perfectly fine with me. That will
then stream at exactly the same position. Easy, less than 20 LOC + docs
probably.

We have much more waiting e.g. in the CONCURRENTLY commands and it's not
causing that many problems.

Note that it'd be a *significant* overhead to contiuously be able to
export snapshots that are useful for looking at normal relations. Bot
for computing snapshots and for not being able to remove those rows.

And in fact, we don't even need any special machinery
for that; the client can just make a connection and *take a snapshot*
once decoding is initialized enough.

No, they can't. Two reasons: For one the commit order between snapshots
and WAL isn't necessarily the same.

So what?

So you can't just use a plain snapshot and dump using it, without
getting into inconsistencies.

For another, clients now need logic
to detect whether a transaction's contents has already been applied or
has not been applied yet, that's nontrivial.

My point is, I think we should be trying to *make* that trivial,
rather than doing this.

I think *this* *is* making it trivial.

Maybe I've missed it, but I haven't seen any alternative that comes even
*close* to being as easy to implement in a replication
solution. Currently you can use it like:

CREATE_REPLICATION_SLOT <name> LOGICAL
copy data using the exported snapshot
START_REPLICATION SLOT <name> LOGICAL
stream changes.

Where you can do the START_REPLICATION as soon as some other sesion has
imported the snapshot. Really not much to worry about additionally.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#94Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#91)
Re: Changeset Extraction v7.6.1

On Fri, Feb 21, 2014 at 6:07 AM, Andres Freund <andres@2ndquadrant.com> wrote:

I can sympathize with the "too much during init" argument, but I don't
see how moving stuff to the first call would get rid of the problems. If
we fail later it's going to be just as confusing.

No, it isn't. If you fail during init the use will expect the slot to
be gone. That's the reason for all of this complexity. If you fail
on first use, the user will expect the slot to still be there.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#95Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#94)
Re: Changeset Extraction v7.6.1

On 2014-02-21 08:16:59 -0500, Robert Haas wrote:

On Fri, Feb 21, 2014 at 6:07 AM, Andres Freund <andres@2ndquadrant.com> wrote:

I can sympathize with the "too much during init" argument, but I don't
see how moving stuff to the first call would get rid of the problems. If
we fail later it's going to be just as confusing.

No, it isn't. If you fail during init the use will expect the slot to
be gone. That's the reason for all of this complexity. If you fail
on first use, the user will expect the slot to still be there.

The primary case for failing is a plugin that either doesn't exist or
fails to initialize, or a user aborting the init. It seems odd that a
created slot fails because of a bad plugin or needs to wait till it
finds a suitable snapshot record. We could add an intermediary call like
pg_startup_logical_slot() but that doesn't seem to have much going for
it?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#96Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#95)
Re: Changeset Extraction v7.6.1

On Fri, Feb 21, 2014 at 8:27 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-21 08:16:59 -0500, Robert Haas wrote:

On Fri, Feb 21, 2014 at 6:07 AM, Andres Freund <andres@2ndquadrant.com> wrote:

I can sympathize with the "too much during init" argument, but I don't
see how moving stuff to the first call would get rid of the problems. If
we fail later it's going to be just as confusing.

No, it isn't. If you fail during init the use will expect the slot to
be gone. That's the reason for all of this complexity. If you fail
on first use, the user will expect the slot to still be there.

The primary case for failing is a plugin that either doesn't exist or
fails to initialize, or a user aborting the init. It seems odd that a
created slot fails because of a bad plugin or needs to wait till it
finds a suitable snapshot record. We could add an intermediary call like
pg_startup_logical_slot() but that doesn't seem to have much going for
it?

Well, we can surely detect a plugin that fails to initialize before
creating the slot on disk, right?

I'm not sure what "fails to initialize" entails.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#97Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#96)
Re: Changeset Extraction v7.6.1

On 2014-02-21 08:51:03 -0500, Robert Haas wrote:

On Fri, Feb 21, 2014 at 8:27 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-21 08:16:59 -0500, Robert Haas wrote:

On Fri, Feb 21, 2014 at 6:07 AM, Andres Freund <andres@2ndquadrant.com> wrote:

I can sympathize with the "too much during init" argument, but I don't
see how moving stuff to the first call would get rid of the problems. If
we fail later it's going to be just as confusing.

No, it isn't. If you fail during init the use will expect the slot to
be gone. That's the reason for all of this complexity. If you fail
on first use, the user will expect the slot to still be there.

The primary case for failing is a plugin that either doesn't exist or
fails to initialize, or a user aborting the init. It seems odd that a
created slot fails because of a bad plugin or needs to wait till it
finds a suitable snapshot record. We could add an intermediary call like
pg_startup_logical_slot() but that doesn't seem to have much going for
it?

Well, we can surely detect a plugin that fails to initialize before
creating the slot on disk, right?

We could detect whether the plugin .so can be loaded and provides the
required callbacks, but we can't initialize it.

I'm not sure what "fails to initialize" entails.

elog(ERROR, 'hey, the tables I require are missing');

or similar.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#98Jim Nasby
jim@nasby.net
In reply to: Robert Haas (#78)
Re: Changeset Extraction v7.6.1

On 2/17/14, 7:31 PM, Robert Haas wrote:

But do you really want to keep that snapshot around long enough to
copy the entire database? I bet you don't: if the database is big,
holding back xmin for long enough to copy the whole thing isn't likely
to be fun.

I can confirm that this would be epic fail, at least for londiste. It takes about 3 weeks for a new copy of a ~2TB database. There's no way that'd work with one snapshot. (Granted, copy performance in londiste is rather lackluster, but still...)
--
Jim C. Nasby, Data Architect jim@nasby.net
512.569.9461 (cell) http://jim.nasby.net

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#99Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#75)
Re: Changeset Extraction v7.6.1

On 2014-02-15 17:29:04 -0500, Robert Haas wrote:

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

+       /*
+        * XXX: It's impolite to ignore our argument and keep decoding until the
+        * current position.
+        */

Eh, what?

So, the background here is that I was thinking of allowing to specify a
limit for the number of returned rows. For the sql interface that sounds
like a good idea. I am just not so sure anymore that allowing to specify
a LSN as a limit is sufficient. Maybe simply allow to limit the number
of changes and check everytime a transaction has been replayed?

It's all trivial codewise, I am just wondering about the interface most
users would want.

+        * We misuse the original meaning of SnapshotData's xip and
subxip fields
+        * to make the more fitting for our needs.
[...]
+        * XXX: Do we want extra fields instead of misusing existing
ones instead?

If we're going to do this, then it surely needs to be documented in
snapshot.h. On the second question, you're not the first hacker to
want to abuse the meanings of the existing fields; SnapshotDirty
already does it. It's tempting to think we need a more principled
approach to this, like what we've done with Node i.e. typedef enum ...
SnapshotType; and then a separate struct definition for each kind, all
beginning with SnapshotType type.

Hm, essentially that's what the ->satisfies pointer already is, right?

There's already documentation of the extra fields in snapbuild, but I
understand you'd rather have them moved?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#100Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#1)
5 attachment(s)
Re: Changeset Extraction v7.7

Hi,

Changes in this version include:
* changed slot error handling log by introducing "ephermal" slots which
get dropped on errors. This is the biggest change.
* added quoting in the test_decoding output plugin
* closing of a tight race condition during slot creation where WAL could
have been removed
* comment and other adjustments, many of them noticed by robert

As always the result is pushed to the xlog-decoding-rebasing-remapping
on http://git.postgresql.org/gitweb/?p=users/andresfreund/postgres.git;a=summary

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-wal_decoding-Introduce-logical-changeset-extraction.patch.gzapplication/x-patch-gzipDownload
�aS0001-wal_decoding-Introduce-logical-changeset-extraction.patch�]ys�F��;�]z���&u1q6�L���������b
����������A�(���Jd�>����4�[��z��*��[���'��������`��VNU�U?i�N�M���i@�O�q�zG��z�Qz�l:pf�����]C�����3����zU�?��0�w�O���Of }��;�V�}�F�^���?��t�_����C�v�xdz_���j�}.�2UW������tPF���6w�v,�8�iTK���f��3��80]7mp�`L@c�r��2�
����@���������7@*����L�R�U����8r���������G�!�LU�
��F��U�q0]g�:�`TV�����#S�M���\-�'�{�vG�2�/
p��P%)��D�������|�tc�6���D��8�vB������.i�.�y�x�d�{t'��@�%tB �!3��l�9Nmc�G4�xbh7�S�A�v���hw8��.�����7�3��ca������`;8f�5B���G�|/��]�`����*q����6Z�a,@#����d[g�Fw�	�R�����V�8F�i��3�x������m5ch1��UD��H8�0��]�pF�B��v����x����Xs�������Q*������R,��:��6p=���[s�-�3f���f���[��t6ih\q�4*=n��-���-N'���i��=M��@���t��?P���7��=3J��W��4�1�:*�=�>}��R3�	�����h\1��=��e������j����1�n��{��s0����X�TJ�p4�����F������3�X�gE��s�o�go���$�����	�Wk
AsZ�`�����Z�f"_�E���x9�=&H|�B��Z()��=�G���9W������p"�O�.�@gS�����b�'9��Q��� ���`,�������1�yL6�Os����Z��S;&b�d������U�J�<N��PC�UlY�����l����}j"n.$�������+�O=�,|+�sc����#M��Z�0'�y25^B��|����� �>�8���"7���Ep��-$/0��j">�#9��RiT�.��A\UR����<g%�i��G�9��}�c�D��i9U?�M����l���5�S�>��+&��"&��P�,��Bm"����np��������v��Zc��a
K�����IS��M$�dS��I�%�:�����#��@�VJ!����w���R�(��T���X������T�x��y���&�@b��V������[�)j��f,u�l�i���-=�S5hg i:X���*���~P���3���P��D�������A�6�h��L��������G������'�8n������R�����j/c"&}��X@L�oH|�<�����#���qZ���5����y:,��m��~����_������������	��#���Xn�^���QS$����������=��)����6���\6��qm�{^�&Jmb�
�,&IZ"O����X4� 3��9���B���B���hG1'��i;�Y����h���[L���C<�������.�d�S�Y��6�"Pq����#���n��"N��f�����u���m�p�3��;O�����b�ei����VY����S�K��2���xV�H�Ez�dgN7*��$V��}_Dx���C��*7���Q`���Lw�&����Zl��9�=D�$7S��{������S�m�YQ����$n6 \d�b�[\l��1����>i%5��������$I</�����Qj�3�N3�mH�ff3��g�)!+�<�D3��&��T`���Y�O����t���\������4Q���*}��9�	W������"��[Bq,]�B��&�Z�F�y����%Z�{�t�
*��w����a�3�SC�S�����H��jI'ujy;uN~Ou)RIGu9>���2l�O�!�b]�E���y�j]�6l� �6Z��m��#��f2��!��\����T�6kA�fkA�H�� e�j-H6Y�����2��	i{uY�X�U�dA�TJ����q�HY�8���P�M��X$Z(K���M2���-
�{�e���D!��V�mb'Q�6�(�Tm8�J�^s��f��A�RI��A9�y��Z=Q�v}x�����>%���x��T�e����1�����o.n{�
�]����'�w��w��
Y�������f��%]�0+��{4����/��Y��������?X0�D�Y���|���W���Q��H��H}���',����U/���Q>n��J���x>(\���x�%���@>����u�{7�I������8U�L^U�t����,I2[Ih�&��p��6�G�`l�:H����8��t>��7��<kT&^H=b����s�_�Ld�]��7-X�a:h�>��=��_v�h�����)��`�T���6��|�u����+|x�?��~{�i��;�E��A���G4������m������N��o=��u]f�U���������E{���Z�e�~�&����C��@��o���7����(���h6%���B?�h�?]
��C��t���W>D��G���3�a<�-:L��W>��q6z��\��
W�sYCf������Qv~�{��]Lc:�e�G��k6�z����d����G`�L,�?k�q�9�,{G��?l���8H�OA��"q�.���j��i)�~8y���w���'L�%���b�C��Fa����X������_�n����6h�Q.!��|B�$�X�.���������n�w��{�k�U��5?�4��"�8$k{���+j�iC�x U^�E���Qk�R�6Y�����s�&����W��3�x�"C���p��{8�������6�\gYkD�~��^�n.��p)��/v����Bz,�:�%Ig�Bv��a���b�Jf?=��gW4��xZ����7��w����r�1d��46n�����2��qfn~?2OU�*�u�h�
}����%JB:>7]x��m3q��JG������'��
t|��ww����U�q�����R>��v����R�k����-�eq\�X�$����T('�{'��y�!;�e=Y�7��NNj���d��N;^;Gw�uaVy��`�������@����t���S��]:@
��Q5�N��9����w`O1�-�0]�2qnkH���������.������7W��;���HD�i%���U���nvc���#o��b�����b������^,�Q��m�������t],�M��3=j��e�J������N��;}?<���#�#r����>�=��@e��Nz���C����G��l%���?T���h�}�U�,�O<1d��o,0�����<�gs�L����������K��`X�U���Xf<��2nz�Qv�V�z��fH�vFZ�:���g~��3����&��Um�K����H�<��B�H�O���6����wz�f���:����&s�C����VIn�'��,	���,q�X�^�>�Y�^3e�4;�����������;pq�����?w7 �����F�gs����c�{x���H�g�w�[�;{}�a+�������k�
�~��1\�L3�L3�2�K:(����.�e�C�O01���"�(���q?�o�`���g����v��%~;��YS��	�Qw�������D.�F��)L��P5��Y��/Z����NCX/�9M�\@��� ���Q�	&)%�i��)1���fc���r�������	?=2M��Z���e25��O(\<A�s\ ~~	I�%S6J[L�,d����&9��B������������^����u�r�K��Z�S��Ow4_u��&j��[���Kw:Q��2���]��{_|H������J������������0!(!���zHx��c[3�pX��!G�~[GlD[�|��|%�)^w&����5+�E���W����+��������Fwn�	[�����K���j�8�I����
�p�X���������y�S.H��xJu���/�V����O9"�M	vh�=)J��8��`�c��*���
LzL�L�5�|�Y����O����M���2���e�I=��	���nY�E���C��v�f�fLU������B��%/�^2�z�&��-��}���o���������+�������?��b�f�B�mZ��1����I���|�98�
q���-�+/2�$`������^Py�GS��3����T���sTkY�X��������#��ur����F�q�t��c���_~lf[�<s%��F��T�(F"~�[����4�ZYs!��$�3�.��������O�9���M3{�6�b}�2�3���a�-�?|����IVr�eF��he��_��u��MANi�$<n�W�Qt)��y�}�����nj��x�z�%�w���.�7Z��q����_��������D:D�}Y!��$����UZ?�.���k����s�����2-(#W�1Y�>��K8��y�!�����S�tl��|!U�
�|��$����|��y�v�zoy:�:�o���/v��VZ_hq�����8��K������pk�|[�����1���lI_���2'�� ���
\�x�����+Cv����FcN��t�Fn;�/�����aw�
����[�����t\�.P�f�ic��nJ=�
�Z���O��v�]��rU���������x�3�>�/���1�?-~tx(����m���X�t�{7�c����������t����{j(#�4L���������)�_�O�T��Oj����+��9�C`0�P��?k�@z��*��,B.��N�|'���5��x�T0��/����������N��P�1��P��K�+�����
c6�������dvw<�78e������3�����GM�����1����Un�l��:A��4`V������0�4j��	-`��C����e�ChuM��#��2`nOn&�K��N���5^#�������S>��
�i��e�S1'��,[x��N�bdf�F�B��fX`��s�v�ssQ��
�B�M��O�s��X'_H'�%u(�����C�a(+#�|B19�������T�������"���i~|pb�4���<M��ue�\�|Q9�A!`Q���2	USV���� f�p�B���o`���z�%��({qLF2s\��!�B�3-��@�0��T]�����c��pF�������/{������������o������?�����//i+��Gg�$�a:[o�Ed �3���o?����v7}�6(�j��W����g�?���#��|�t���'!�(}�[�����N�{��7�Y�����WBQ�+���@��f<:��z�B?�q)�7��}y�%��<��� .x��!��[U�D���B������
"����QsF�;	bS7�:�1���}�=��p;vqv	n/��n�_�����L!���gD�����>eS����eV����	�M�w��n��Q����8����2Q�Th�>l{yk��5}~O��Z�vY@O!CG�4��	>n�1��Xk����V!�v�����D��Hb��B��43]��M�2uq��:����EF�R��7R����W~�+#���3A��zA�krI�9�yij��89z�B%�c���f1I�]�$W4��D���Y����W�I��&M�&�	>,&��2�G����N��E��D���|X���b�����i1I��L�F]�L;Xp}�U�������+z��>��������o��E��`�l�qej��z�&.P��������1����	����[�X
����p�z'���gU�*��MF��(\������e�h>U�fL�V����i������0P��[U=���jY�x=eU�a�����+�aYyv$��Y�%��"}%Be��Dh+-�
� �W�������N��_����m#I�?������M�<K�����r�gd�+�Ifg���HH�c���e�N���^WU7�A�:8��v�0�F���N]]U�GN*�S&p��E�����#.���S?�s�`Wg��Nd]M�S���f:������h�rD�~8��
R!/�<�'j����h���<N*ZmU_���k�W�FcNf`�I�B����l���
�	�VD���h�aW�g��?�42�ty^<z�x<i��g�i���;�U�����ET�,��/k���+���F���0���[�v;+m�[�d�3'��c�G���W����[������t4��u/�R��Y����u
~�o����a4���J��Z��k�y���r����v�v���	��J5?��Q���B"c{���k���h~G����T)��(���d��:�E����rp��L�g�Y�L�h'=~�������w	��i<�����F�*��C�jJn��`']������
����m6��7��msC~��U�3����t�&r^f+4a)@��hm��$��-�.�K�P����(9������.�����g�]:����p�qj����y���~�t��{!m��F��
���R�q�V�nm�$�O��,��<,���+��]�������:ZY���0���w��v����}�/���#@v�x7���~;�|������GU[6���mz�o������p��d�Pb���.]�E&v�wr��b�m��4Q�m#��F����i4R��X�����hZ���[�@X�dt����9�������!���C"S��w����!X�����h���	����^�m�����66����*8���[��W��5%������K���T_��
�Z�=3�?
�_���p������_�a�m�Z���8e{qC�[5n:�R���2�2�Hd�W�"�zs*I8��O�Fa��F�g���*����{Wo ��������3-�wm���?�����������]�����R+l���m�Q<��WK���'��L��0��j��O�u4���9��U����=���jt	g
���)��U?���Lw�A�)P�����pZZ��:��
���g��x��/G�$��F�)��-�j����rw6��z����~�Q�G�H�\q���H�����^��m8�v��4�S��l��R�����j����{�<�96�u�X�%��o1��s�����$�y9����y�C�e4
$%]��M�%�;qsO����^��������1���N~J3�����:����,B
���z�t���i�I�!�m�	���!6�z��d�~7���������38��&!6��B����s����I_/��x�����������G/�AO�E�/���,�
�p���K~); �q���/_�<tPV���x���?��#�	��3HoI$�������J��@�\�tb�^�X4��X���FG�KE�'��#�'��`QD376����{o��X���u/�����;i�����dP���n^q6��om���OCR����,�_J���.��
v����~s��}������=��m���g��������O�������������Y�W���G�i�2Mpu>����=��o3wO��4�J��?��������Y8���+� �k����Q����A��o�����v$/�A�5�����7%����Oo�������	������t���t�/��_��y)����_u��������������FB���I}~$�0�������Xcn`f+-G�_U��nv\4n9�1F�/�1>J�r�U�k�����`,N�b[}��
�?�����nG��I���K�	;�����"�\�~�n�.��]v����K9��r�6����:�����W"[Ra���~�s
8���lk�W7��I����[���g\y��r�����I������v����l{ovN�N����i��o���~R_����?�z��e��Wg��)/�Jw���h�\���e�]Xk�Y�ci���K/���].�Oz���%r���w����}�&�9�E(_8�����
�9"�vPS�d��x:�F�Z���9I��x�lcX��4G����g���x=N��k���l�ps��r�}�������J��������n�^����s������=��z�~�����K������<8��V���f6f��4\4���W�����y<�����)�)%*���jy%����%}4��V
��p���}��a�D~]��
[��P[�BR���fC���V�SU�1h]&�>ep1��;���^�������������������j�J%�'��;��Z|���3��H�sp��wROFX����lfG��8��%!���'��dl��D��_�X4�2������_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_�W�^8
�1���/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/���/Q?_��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|y���y����{�w�������ix:����t��n���Uz1�M;��������������k8����//�A/����;�S��S���������J���t6D�lt�.M}x�f�M-c��^�b-����{
z����.�at�����.�|�� c���� �?�F\��}��i�h��o��7`����%Pu���v�%��K.�hUn�����r��a����3M;��`p�}�R����s=�������[y���g�I�b�%����/���!?8,�c~�
�Zc!��
��p;�"�5����0��/�����z��hP��4�<����j��h�6���J�Z�U��F�YmU7�[�v�R��j�z�Qk�Z���V�]����Z�^o���V}��Uo7*�j���7�f���ll5��J���5��F��l57�[�v����j�z��j�Z���V��Y��n�6�����fksssk��U��n���[���Vkkskk����1�6:k��6*�1�
��QbP�Dh���L����0-���0�j�Z��I
3�Wk�j�Y�����jm�ZkW��T��`��j�Y�����j}�ZoW���UX/��Ym����jc��hW�v��U��j���hU����V����*E�Vm���F�����lV[[�V��Y�7k��zu�Q�lV7,�Vu�]��p�[��V����n5�[��`����T0-,R�]���v��nU���6@	XV8�J�V��*�Z�Y��j��Ze�V�;.�s��0z�@g�_#&����Qk��.!����Z�Y��j��Z}�Vo��.^j��%�Z�Ukl�[�F���p��^�^k��2�Zs����5��V�0AW�z���������Zk��j�6+F�Y�m6j���&���U�l��*�$�U�m5j[��V��f�*2�����v��n����6P8^!�1�J�^i�+�z�U�l�+[�
�B� �9�3`	�*h�B��Ja90gL��1�v�-V���������������z�B\��I��Yo����zc��h���!V/5����Z��f��Uo���
1��Z�z�;m��������
�0AW���f�����m�U�l��*�k���j�����V}{{[��$1@l�z�Yo����z[{��� c��F��lTZ��f����+�(�`��
���
���W���R�4�0�z�p{q��-�3&��c��;������������4��f����%��&�P���l4��v�U�~bu�RT4i���j����
�20��6��M5���f��U�.�&�j���j5�@�@�@�* �k���j�[��f�
��X!m��`�������fe�Y�v��l��9vP��s h��{��iq�`?���I����V������� *�C\�:���9cb}��qT����5	6(6Hv��lUH��)�kXB<i�zo6[[�V��Y!a�~bu��&�=H�Vs������a+C��ho���/]��b�yt��lo6�`�RJ�5��QTZ��f������UHDI���$),�(h%"vr���D�N ���p�:�w+$���u���[�HhUH���u����1�
	6��N��Ja90gL����$Ql��.G>F�j�6+$��^���5,!�l��m�6���
9�+������#���*`�y���P,<�l��B�C+� ���@^�]U67+[�0�
Y
y[�xMV�����s��U�mH��Dy_�d���BFD�U�n ���A8@���(��:7
7f����@V����u�!�&
�`�r6B����ElQ����}����5�P"P<�lonU�A�A��)�kXB<�����V	���
4���%��m�rQ0�<le`(�U��*��2X
u�r���"�o������I��Z�
�a�l���N�@���IF��+��$mu�
R��N�����s3�IQ��Z��
`\!�'��Il�m-����YU(`u�!�o����hoqbU2=������(SA��jW 8����zaS���x��]�P��a�~bu�R��W[���Dmn�"��E�h���!�-��-��-,�-��-l�-�-��-L�-��-��-$�-��-d�-�-��-D�-��-��-$�-��-��-�-[�-H��m"����ms[���o�"�e9�2���-����������@��<J��)ER��J+��Eh�R���IQ�#�B
�(�Q\�PF���(
K�(�P��CQ�	�
!((P �'k''�&3&�%c%�$�$+$�#[#�"�"#"�!S!� �  �'I'�&y&&�%A%�$q$	$�#9#�"i""�!1!� a���&�V��������F�v�� ����DV���Z)�Q� �$S ��&n�BE5YD.'��q�;kW�� ��~���)�S��M���*5J��x�W����fp/Pu�f�T<()��AFEL��
C%B�<(ER:"�'7#�&����:!�<(jR��h@�GRN��G�B�xP��E��|���t���*�L���Ja�B�'��71�
�:�A��%rXrRD�t�\*�<�zP���A���v
���KH�������<�]��&;C��Gk)�����<��P�
��	�Q��2A����
�����NU�b;�
�A=�$
��(H���PlE=�|�< �)��[�Py���z��>�xj5�A��L�-�x�"u*�>��,>�x�1�C��z������`
�Po%�"9�����z�H%>�x���C
���
x�Rx@��2�n�O[(���@�.�����������C�H�z�e)�Q� O%��j�m!�5�!��bC��J
U*��l��?>�!P��$����u{�}���N��a|P��-x@���Z��)C���-Z�m
x@���H)�P�B=���ne���<������2ycE�;� >�x�o��z�8
>�)T�$���bT< ���
�_n!dCv���
�V|P��Y�(i�Q���@�����A=�j��*����
�)��S�#���&v�_�GU�
�"*?���1��>4�P�A=��>�x�< ���z-ZR(����RXQrx@�����P�E=����L��>�x@\���
tT*BV!���z��|P����V���^��>Xe�H��@:<���Eq�]�h4����<��)	�Q�C=�:>�x@���!�u�������< ��
T��ZC+�h��Gm�R>�WJeT9�.�>RI�>���F���!,��F���h��v�z��,������>�x@~�������5���A=��+>��Q���X���< ���z�d0|h7�(�<���<��x@F��-R��A�u�-�FK����A=�CXe��"��i���H�`�e�u���8���< j��V������z��|P��
�l�&6��hU���Q��(M�����,V��b-���zT����f���e
�z�x@�Q��Z��P$�����E���	��A=��5>�x@ ��������N|@}��U1���E�qC�w](���BcS,��!�TT$�QE=��(>-��A=�*��-uI������< �C���hx@?���*��(�A=�j��?�4U|hv���z��)|P��vQ��h��}F��G=��Uq�QT��<SE�",�\*��G�Q�����������z'����c���A=��>�x@;������l�t[|�	���`�iT<�D�%W8��p����-���z���~5���x@���h����!�a�fi*��x@����S+*B����:�z��`|P��*�b&�m�����<D<���z-Z��*���
�jE�U�i����F5���zTZi�HK��<�u*�T���N5��mE�^�������<�*Vy6�YEc��3>���Th|����j��'�4�(rnrR(�
B��ZP�U��Q�F=�Z5>�x@��	D����uP�F=�
6>�x@���^QQ����Un�<�k��z��m�h���h�
8�P��A=�CD~��7>����q�<�/C%��Zx@��(��P9G=����<��e�cZBi���J,2T�+T/����z4�@@3�}9���G�i0	���_{���M�n?������lz
��Mp�=,���2�I��h��������Vv���d����E�'1<)+��S5TT� �*�;����J+"�c��H��k�'TD>m
�����fh����	��F��M�-�����~$]�(5��*<,���]-i���I�C�	�W���D��rZ�i�����(2�+�x<�c��i&���f=��dZ4�����g����L)m�i��i��A0h�����Ti����!���A<����ViZ[iE�u�KHcO���%����mli�$�
4�?�{h����&�Wh:�Y���SE��&�FEM����[BkT��
M���/�Z��TG�jR�l+HE���F���U)�IT������rP���@5�">�w�����"
S��K���'�J����>"�Q��hE��"��2S��b":P, �';'�&&�%�l+
K#�"+�>&!{ �'Y+fEI-�(I$�I�I�M[�Y���A7<j�G
��5��Vi+��m�&�sM�����5��������O�PQ���<���&O0yN��Hn��^|P��5��x��^45������5��x���45��x��<zB=��x���4(5��x�P1|P����it<j�G
��5������<d��0	x���Q<j�G
��m��.&e1^��dx���Q<j�G
��B6dg�tc��x��:����E�|5�e�E�n��P�tKx��J��xn��8�3�����w�D����\9�E=�������<3��(�
��G��7x�z�G��u�CH���G�������x��:�!���[��x��:�Qo���:�!$��]��x��:�Q<��<B=�C�*
��G��u��x����A��/F�:�Q���Q<��G��u�C��P��@�!��nx4����������&v���3���5DW�yH�<
�5����<�G�h
�CX��t^�Cy��!*y���R�]����e� �91����'�<��)-Y
���G�h�&eQ�h
�C�
��G�h
�����$�
�CX���G�h
��x46y(�z���/����<�G�h�-J�a���G�h���h
��x4�A��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?���,?L�a����hv:���$����h�����f{�+BL�jV?v���;���~�w�����w����(��������7�'�/�~����4:�&���R#�u��A��������O�h�n�[��`P�+5��&(3�7���
*�	�@��������L�Lp����X��	���fi6���fs�����<Z��f���lm���`���������&6�����jmmnmma��P���P����6):W�J�,���\�f�ia^�f�������!f�\o���������M�%��?��?�6v-6$�)���za�M�T�TpT0T�vt�O�rb!Z`���`�d�E�{
��U����8�n���a�5�5�4�3�2)(`�[�P ���M�J�JpJ0J��t��;�			��X�HNFB�-�����:����RX���1D�����@`��� ���	(.�)�$H �h�\�/a�ckc�bCb�aa���U�^�h�i��������&��"�,�l�����\�&�?�H

��������@���c`c�b`bd�@��
�*���������*B�(����6`���Z�R�4�0���&��"��I8gL��1����j]6��6v�h7P�K�' ��n \�I 7�$d9U�.^jb�as�����~����Xx��m���N���!��&�jT�	nf^VC���0�-��&xX8Y%6����A���,`,�+`+
a*2*(�1-h(�c���{��iq�`?���@�6	=���9�3`	�����5.�s��0z�-��J��C�����KvP%�a	��	2�sok C�~bu�RT4i��[��G{�Mp0��2!�r /`������ ��� �dO �zcl7A�A�A�A���P����R�C��v��l��9vP��s h��{��iq�`?���I����V������� *�C\�:���9cb}��qT����5	6(6Hv�
�J��M	\��I�{���j��`�$l��@C�.^��)�jn���I�����Xx���jn�����C�E�F�,���lo6�`��H))�RN�(���'����UHDI���$),�(h%"vr���D�N ���p�:�w+$���u���[�HhUH���u����1�
	6��N��Ja90gL����$Ql��.G>F�jC� �����a	�dLo����0B���
4����-�Hp@0<h�� {��@R�=��l��B���oP��<E�PA����B�B�V'^�a `*� yrR�:Q��c��&���~��Hn0|P�u�<�;����
��a�`?��/�h�{�(�I9�z���P�s{q[8��&G_%-gg
"�6���A�A��)�kXB<�����>�%�h�,0�� ZPw'��C��JC���NY!��P�.'�n�+�X��
y/�^��\��Q���V��I���
��-�d��B�M�V'� %jq�$��
�97s��{��iq���y�o���������U�"V'����\��'V%��8�y|�2�*���A�A��)�kXB<�|%���h|u�k�DC�R����Rm��"��ELi�����-B@[�y[s[Xl[�e[�^[X[XQ[�J[�C[}[Hv[�o[�h[b[H[[�T[�M[G[H@[6s[�e[6X[�J[��-��DlJ�9����-K��El�r�ebmb[:k�km�E+U����j/�"E;mX�O���V����h���6�_h[���6��Z��NA����h��O}��z[-O�?S�pB���*uQ���!�j���:�e2g�Q����P�i�����L����l���$��[�\ �$�$�$�$�$�$t$g$Zb	"�!1!� a���&�V��k6�7�7Q�N4&�%E���Ja�B�'��7q��V7Y�ZU����8h����VME�B?E{
��)�S��`M���()��A^MD�J��� >6S��AI�2*`n��+��R$�#r}r3RiR�*�r8�EM�P
��H�I������!�G)gQ~ _$�'���#�xPh�0F!���L����X���:�A��%rXrRD�t�\*�<�zP���A���v�Z7�ZCOMw� |@v��
4j���(>R,"�'#y&��:#U���Ae�*���iI%��T�(�����<@���J�9����z��">�x�E�`< n�C��b�`
���jK�< j��z-j�[P�ET�.�����0F|��Q��/Q����0|���m��BL4����J|P�q���Vd1H���VcdO�\�@�C,��3��X j��z�X>m�F�E����(�RF��A�J^A���B�k*C�G�����"T8h���< ��C�H"���!�on/��/>T�)C��6�O[������>|P�E��2$��AjA�6< ���z��|(C��!Vvne���<������2D[,������������4���Z/�51��Q��<�7�|Q-�B�j����c���!V��U�:
4���A�$|�z2@�C�_Z��B��#!2x�y$QT���A���JQa�ZD��'$c�|h �B�z�|�z
ARx@��Z��P�G=�\_O*H�����
��x�iI&���< .�C����x��B$�������O[OE���&���A�(�l��tx���p�����@�)V4�����!�+$�5�q�x@����~����d�N�:�<�p��z�=�!+���V��Q���|J����r�]P}��(&)*|�G��*1�������A�mW��P����'Bd;��|P������<����	��$���]��5��u[N��� ��z�$:|P���O[O����&-1Hc�iT< #���*��5�P-��FK����i�)Ye��"��i���H�z�EvZ����#�P��A=�����������z��|P��3�e��h:�IDT}��jF���4�_�n��TX�����*&�Q]�R��7�w��>�x@�����r:G��Z��P$�����N[N�(&@X�������������fMi6�px�Q����'�"I��[l
�j
$6��x�i!E��Q�<�������<�D�bK�FR*��x@1���z�H���~�UU�<�Q��z���LR�<���C�+W�<�N����K�H����G;�3bw@=�����S��ZM��*2a1�R�E=*�<��x@G��hu���K��-'���9��z�t|P��v�O[OS�0�&f[rP�x@���Q��W�jk����c4eWl	4�����R��Q�E=�/>�x@����'��4KSF=��/>�x@���]���t`|���=�<��b&�m�������S<���z-Z��*���MO�)���M#-��4��X$F���J�EZ��T���S)��-6v��m9���5�<�x��z�T�*�&��Z�y��L������*�PC�=Q�)E�s�[�BqWU���o��5���x@���(�< �r��uP�F=�
6>�x@��St����l|�r��]�<����<��-PG=�j7>m=���x@���Z<��:�z��e=��Zx@��(��P9G=�CN��:���uZ�i	����+��P!��?U��Q��h��/�<�0�m���6AO!��	n��e5sX6�
K�h��������� ���U������{��G'����a��������xww�$����������7�/_r �����������<F�pu�h���R�p�k�y��������`6��B0:��;��?�����$��o�l����Q��s=;tF�����d�$x�`�X��~�=�
�=�X�1_�� �M��*
zv/�@'X���:�>E��L/"�9����h���9:|�l���-��b=B���3�����F��y4��:�����|��<|�
GW��?�f�h�s��{�)�:��_|��_|��_|��_�����/����/����/�����p�I�/����/����/����/����/����/����/���{�U"����l����|�#����>���|�#����>���|�#����>���|�#����>���|�#����>���|�#����>���|�#����|J�'�-� �w�|�YP�$� �}�T�I��uy������t�g�����3@����?�g�����3@����?�g�����3@����?�g���_������$��V��p}=���Q98�DQ`r��h<�S�0u���'��x�a%����&�q���=��4������x����t��Y������E8e&�p
�N�OXu ^_�&Q���^$C}��P<
��2I�����=::<z`���OU~�D1z���~H��������O�M����Ov���iO��z���`}��?
���p:�����y}G�i�{a�����aw�1�M�����x]g},�%sF��d�{����ec�wz�lE��Y�V>���������������J�<����������w�v�Bs��$�>O�a, �Ty��I��l��4l�^�;
O������r�����d4��Nwty��~���F�,�����bf��]�:EA(;3���b��@��
�������s��i��)~�tg�����^*D����������,�L������d,Q�s7oMl��*�^�K�
�Dsv��`�JO"��t��q�1U�=��W��a����hr���I�<~~t������������T��b3K�X�����Ww�����{'�i89{�/����a07�,,�Y�E�r�������7���B���z����
�Y�[�t�����l^�N ����������8j~���.�{�CvO����:�]����U�]�i��k|�����a�������<�#�F��q��SA�=�7���e��'a�J��L�|�j2��-O�M���2�@�,���)�P�1&�[O]���J}	������+���2\{z/h�3��3�j�������T:����t6^U(�{i%�t�������&��w����-I�����m1�T2X����	i�t��r6�U��S|���F��?��S����~K�'��C4f���K������	%���w����m���y������.���QG��������'f/'�e���s[���G��{���
��N�&������7�F.0D�^H������ei�moZ�uK��"}����t�HvP�)6��*Z��q�:S�����Y@9-��������I��@�^���J���z�r�����V����^��:��,�f�ZKXG}�QQ�QIXCti<��!(�yw�1p��\��\�J���PM��hV����6�����CYHClRz�.k2��h5��Z�mP�a��l�
���G���G�kA\� �j���p8��k8�[�����!a������9b]��}�w�]�~���{R	�h�i�����
�q��y�/J
~�Q)����Ov��E*�
�o��R0��i�h^���x�?�����{�,�_�%R�_����^�m��m�0���0�Ic�V;lj�����]d�|w�dV��x�t�c�8���I�G���Ig8�\��Ws��3�s�Xx�{��1_�=>�}���#ZP����@)c�3���Y�Q��Yg57�?����f���pG���Z$o�I�;s�"S�Y�������er���?�����EC�[�WG_���0������h��"y6�������."y���A�g����g��LB������9TY��:��3o���T�_�p)��}w�?���L�bA?����M=����ffx#��#�����?�*��������I����������.���ax�A�g�j���O,6�W�����1/.������
������u��������(R�i��v��h�Wwdd�Ie�����N"1;���;�WR�k����wQ���\����B����{o������K�:���G����J�/=�����>�
y� ]F"�����X�O����T�U���`E-�&��OP���:�5�/������U�E�B���p�+�����Y�a����%�j��k�-xM��;�����U��+o�g�}7@����m�����y2��L��RKG���j���~�����]����>�\xY��h<��x2���:�����z��*D�g��4��D�Q���X}����gg��1�99}�p�w�}��3����nS7���`(������Vu-����Ch"���R�:��s�XQ��=�[��6��.[�\�4���������6�A3�����c�=���|�W!$��vw�,�D��J�#�\���������r��)�nb�w��^�U}iW���9<�H�x�!�k]��h�a5�1��\�:?�mM[k�������4'��s���m�a��������
��y��5���l�h[�7��6�P���,G����\����Vk�w1�$�����-��������;S��@������\~��'%9��	�����q�i�kY�����OQ!�5�v����D�������o|�a���`'�Q������������L.h8����3���1m���^�d<j��������;u<��m>1�/�����[h�}���v�v;����w���.C���=H�{����,��o�q���x�A.P����A
��>8��(���FvL��-�[tc�N�=��j���[���7�D��i����P�$�Xx�>���'�a:i��v|j��*b��;[%�C��d��#�d=�&����(p��*?�M��z��h��W�����k�ja�~���1�?y��;��&��e	2�������8�e����	��%��H.g �������AQ�N��x@
�X@����3
n�{�'i��,n����z���}t�w�}|0���28<G�7Sc1��9�.G�n����CaOB����8�;���G�/�zw&o������cN���g��H��f�+���l���&���O�t����"�}g�K�Q�|�l���
R�2�����������w]��_���������H*��i�����`�����2�5o�j+/Q+���Y��q:����e_"\d����rp:��f�3����O��O�}"�r����SKk����y���8��"����V}����Z�j�T]�l���V��w���v��k��nC��������W�&��?�)$���x,Nk�"��Mcl�RE�6����X��G�T��O��gn:1|��%�\p6�����]��������-z��ss�i6d�.��8��!F(m��g�Y�������^:�����Nx~^:���|�&��O���#>{V[s+���a4!��`Q\B/�,����f��u:N�%(9c��:���aDo�UD3coV����l�� >:K]|�?�\�:,n��_'wP��
��(�������T���Z}��l����h�eG�N�y�~��^l{������?�;s�(���"^|�����5�stW��n���u�pp=�O�ha&M=:���m;2�
���4Tr��l����d�;M@Yy*XT���[��&��G��L�����T+�(�DmO�b�������8o��|�.��u��?�<�>�!tO�n��b���F�������St"_��E�Eee����w������2��cn���%�z���n2�g��J�N�8/�f���m�+Lq���LI�T{L!��hREM�$�NE��4%QEE$lUV���I�����[��|��s���y)��=���>W�i����T~��n7�������+cT��O�������F�����G��u�������R�����>^RF�������JF�zk�l�����'��c���u�
�� �
 ����_����i��Xe����	[������`C��-���V�4��v���-Vfy��%lS����o����SQT�=���Ss���k�|���d�H���)�� ��r�o5�mm�;���UBWE��7��E�
,�w�Dn|9�*�	<��OL�&�)����C����&!������<��h2�p�X#����@ �p.
���E�t�`�75&��g�\�j����FW[4���G�e�e��9��R��:RMHL�|/cp�
e,-��'y��6Q��Ls�����9���-�Y��e�_���h�����g^�[�h�����Lo�����G����&��������m-�K����f��c����w�������N@0���p�jw�����[����X[4��-/���h,l�����M���d��n�KjKw�|k�vIm�.�oju/�%�-/�%�e�d��d��$�C}":fak"�8�-lIYu��o�E���hX_a����X�������K#���1n;"t���Jja72F���n���������Z�}���F+F��9!��������b�:'�"H~!��m�������z�w��n��u�h�v���M����]��EX
�pet���?�^�BC�=�(���5qZ�q�����"��������8/>�(h����o��1�Z�B���[��sE*����	��-��^?�H�.�M���[Q�)��M��"u{L*jk)�������W�n!3/��j�Xy7@�6sXd�$������_��(��������To��+=��O�p�X��J�����Y�}���K:tgW>q�IP~�SE�[qv�����:���������Q�B\=MN��gKt���t-�������h���n3��9��b��NW��i__*����V��'f��9�B���VZ������:����+P���j){j�v�q{����4��c���C�
�L��[���m��o�em�"��[&6s��V4��$�8n������
�z�1W��e.�������p�4a8L����X��E�}�E�g�{�E�.�����y{=�0���7�M�ph�������@n��2��Mx�wp�gY��*J����U�[V�n+5G�2�����OfO-]Xm6�0��^���`�s1�T[�	���J��6q�r��A�����/{%6��k��y���H�c-��e��d�w������J���L<���'��@�7���-��o�km�!�����.�"�\��{����
n����J�>��6���Ia�����z�K%������,8��!s���0.�&%�=�~
�������F�Hq�i���~7Z0�q8A��3�E��=�%��I��4���9���h( 
�����K���Z6�L������:����v�39�S�
���y���{���g2�M�����QtIT�r�D�x����+,���KS���_<3+~uM/�r��,�fCYA.�h=q�&r+~��z�n$��T���g/g�� R���0�"s�������|\��������3�wV��SmX�6�4D'iE,��������&����A<$<^�%V�$]�����s��9��q����`'�W�Ah�~`f"�s��r�c2��Ox$�������/�/�.i/>O�W
��~-���V�3@�L������w��?r�����5�o�fZ�o;�j�Q�t��v�q��=`]7�r�������[.�������4g�:e���-���I�TM��h0]����n|�T,+l:�C��?qRn/��y ��
����d���)3��(>S�4a(��|�i���<���=�w���i�����b��}�1�w�6�D����}���8j�q�o�G�N�1�V(�^�-�/��$�sp���l>��>%$ ����y�����S�tf���g��5{����D�^,���a����T��EM�-����p'Ws,1�R�(<(z��lj3��t�	�%B.�W����%sI������"n<L3B�C #F:jF�1����X�%P���o9�������{�-E��YK3�����`f�J��H"���3J��`�����J����^��G����5gw��H����S�=���c�����X�h
:W�~�?SY��@����G������}(�V
T8<z���
�y<�����.�eh�����}�hzR����ik�6���)���.��q�VD��$n:K�����3��s����|S;,����?�����KL��?�JR� ���U��-^���G����� ��;��W���-:��~\�e#�]����fN���7`�s���%�o���!��4v�,���!O��*�b�i4~��n���H���o���hoc�+i@N�S28��J��I`Mi������8�R�./�\C�Vo����%��'6�M���������%rG8��O�F������l��|����Y~�z)c4������1�'�-����
�a�oUf���h��R���:���3�ut�v
�a�������~<o�NAlf6��:&~Si-������y���G��?�m��p�I�ldq������|W,�eu����bs a����*��a�^��,L��l8Kr��4��q���'wVa��gi�\Mma�5�c��h�b���w�I�e4
e+DVOt���8������`�����.��w�CP��=����C|�����s�[�y���m��Q�v��t�~g��t��h�/}ruO���������.�����}�!�p��C^0`��_v��T��b�9��-��AW��c�2
\F�	��8on�5���H���sm����.��Q3���Z���Q�'R��D����j��:�hc1�	S��/$��i������M����\��=����{]`!:�]�����_lA�{)g�,�jsf��;��e,a&����7I�h !����6��cH�g[����5I������Z����)��b��8y|���<�}�������=8�;�K��x�~�	�Z�Ws�E�7�J}[�l��<B�0J��E�����;jnQ��[�x����.�5g&�AX/(���x�[�'�Ut��D/�?�|�!A@�\?��!}��V��r������o����$����7�����r��tT��bMs�-���-/��L=;���\�Z�=�s��N�Obn���%��m�H��K��
/�ef�9r`������cu�;x�����:}�����a���+I�d�'��O�#}��(���`q��`��X���X����L�D/�]�,g���<��)������`��+����e2b���I�/����H�.vuG��Y�rp���S{3I��*j_�;=�N��!

����+�������0��"K��[YJ{�wE6��\F�/=�;���x�=����AbU}���Kzp'�pn�<@��lc�t����x���O�+]��j��r�$��s/�����������M��rc����na�PM�b���dp������#w��=T���$
c�v!v���������h��� �8�I�`(t1]���7���n%a���d�<���X���s �"�pN;2��p��^j�nH.�6�e����#i����^p����-w���_q+���S��A��?%��qt�;�%��qV�������}W�H�3��7��Q��j�������o���=9,h��%Y�����A�v�����2����b4�iDp����� �|%Wt2�?�2��I��J��kH���>!�6�Hd:��A}a���3�d�����l���������\:��.�V_t��_��,�x��.�����O��V[�dk�5�7����l��9��=X����dF~�����(F�B�-.I&~�m%������C�%�(����.2'+Qt#87�a�`����^
������ �h�+���2����y�])��dH��2�q��Qt��f�8m�{��[��n/��j|19�0L_�]����Et�/w�}�k��E��B����Q���-/ir��v|�����+�zC��%�>����s�{��t�/����f/�:��q{���wrODy�{�7q���:�������mm��_��*�e�g��4�#G�Q	&�~���ZIn�8�Z'���X�~������������X���xnU7tP8tpGr��F�L��d\����{M��n�
l��w������Nz��r�������^��<>�H�������$��G�Y��>����Q���Vi�^V��i�.\�V&���;���D=]7H{������$"
�'���O#�d�����>���B�S���5fNCO?��>�������N���4�O��v2F���\>�����l8�?>����R�8T�c��4w��h��Je.���o�D�Y[���x'����?�O�]�����I�I��a����.��S57�Z9���f��*��b:�{�}#A��f�-��d?�y:K@��I8��/��`4������j��m���$gm���)��3<����N���1����p�j�|�S����%�9`+���O�G���;�����,M��F��Vo=��������A/����lL/�.�3o����t����T&��O;	q��i���������������k�m���b�hS/V+Y����B�0�DAhB��*���+���Fz?��
�Q�c����u7���`����������(Y'�V����pk���u��#[7c[���t����+8(s��']����K�"�������3r�[
��t��G|����������GqT��})��`�36��b����fk���_���Q��l������>��9�f������[fn;XT��q��\�qpy�O����dl���e;2�
xrkS%����J�c%��O6@ms�]y*�_+[t~���l5�Z�>�bH13�]��S�`'�(�+Y�����N�����{*��~����2a��f/�����bV�|�H����������^��,���$�������?����$�"�.~(�� �N�c	e�f�.����&P<��R���%{��oQ�b|����r��	&���5t��o��(y�e�X��-Wo5��p���6����Dn��^<[����r7>�-~{�(���(���q�G�IK;����~1
J�5l�jm�i����x�}s�������)��<��-�~2�*i��}o����j+f�x�5z����b<�D��M��<������:����cc�|a�l�B�c���>��/��$����
�z���(lr����kk6������N~��p�yv��ET��2��?
N�������;�X���{�}�������w�����VS���uP�E�_I���f�P��O����P#U���������Q��u�����;�����.e������NG���Gf���_��xx�kp���Dlyen��\`k�3���(?���\�U$��-�������\��yiK���;�g���r�N��D�y6Sd{�%8x{Y+����.fSft\����%�Xg�y��vPG�h��&��x�z��A�/.n[��U
[/?�����~:1�����S��+t���#������F�z�=)���Iv(��0q[
aW��q49M.�*x	B�jP�IG�g�Y��7�-����V;KG�3��!��^|xv��V����r`��mv�`%Z���k���=�P:�^�Z�n�:	�Z���j�kRGq!_'A9[�n�����_�U�u�d�r����c>��?�����
�}��;�`��������4+x������@>�G�R�I��J�D���\B��`��GS3�1�0��RJ�d�O,��M$���$Wo{�pJK�X[:�������M���NV��n�gVs&�r�j�a�l�&���p����'�j��t���y~8y����~���{�H���;������@�%�%4�����N����Dg����*����r��4bv���%VY�6���_k���{�v����d��	��F����T�UO�'�2�d�MV80���a�QKt��d����BM�U�\F!��?��7*/����G:����)�����p�(J)��M����&��=����t����������J�d����w�����{�y�}��j�QGlk�����KO��C��c2s������=��Vi�3���0c�@eM7��_��d�7�/A�y ����~�7���@�M�8!�R�d�4�r)dHi��[����_y����LH[��0�w�}���.;PL�R�*�^�dM�4����:h��:k�E���D���V)x<)����E�_Si��;"�����/oVQ.T`)M0��\U���
�5mY���Y�#������)#���J�A�0!z��WS������++�&���'����K�Sv@_#���8����
�F%�%����W�'h��p�����'; ���5��y�j����o�J����@u�;�Xc�C����}�M<14r~)��i0A)�_�k)a
�����LG��0-��$���+�.��O��L�A�u����$A.��}8UW%=���0$������0��6��������O7����2
��M�L���}6��C��@�b[��6�����,F��2���D�T8�������8R���+*���zuo�X;���Yw��K)��b����(h�����_&���g����DW=��O�0H^N4���wpR;�{������a+��d���?���#?e�:��n�ho��F�~�������\�2�fx��4���A�`�VX��q9H�A��S��G#H����d������<���eO���>Y������)G�K^DcSW�[6�'�
O�R���DE}R08H
�l0-��������=}j��VR����������s���-��x'�tf1��s�s|r�ys�����R��l"��X8�����5~]u�vy\Hv���������Tiv7��������y<��n��x�]v������(���gYm<���X���f?c�0������G#	����&N=m�?}���!�=�?��'��4��d4����h��J����S���&L.�C��n�����Rx�1�?�5;n��i2
�����~o�`������f	��o�
�������(�yr��%�)�fSP�)}r	����8���+���&�XR�y/��n�Wb�Ukl�JYk���?��(� "���%`9��cE���(f�����_�d���D��"������<��{�u����\�_��${�~f�������������Y�����pN<�~lZH�?-���>xa�G�]���M��553�7���k,�e:"��U8c��x\�F�P_ ���v�\��h8Lu������`	���v��9����l2�4DC�0��a<EE�Q2S0�9})2��B�5��/��_g�A���m� ��D�H������E$���=�G����cg�2�v�@d��0���8�N���P���R�R��/O�a�}�]�1j�<*�K%�D�
�N�wY�Nv���c
�!��o����s����b�A���'�dX~b�q�H����}r��;�X�������?�����M�r]��z�h���O���&�B,���TW���
��J��'CL�JM0�x
��BB���H������#���G���M���y�{r�}|�y�}��])���Y�<�����E3#XM�$3e{�����$.T
ns��T�c���N1�i���e�zCW/�r����;��*o��e��!�Rm�Q�<����D�C��t����L2�T&�����C�8cU:�f��?���$.��e�N�f���:���X������ie�*���k,V��7�N7�������\�ok��H��q������}��L�������%��^[s}�ZR�����%�����V
��*��S�����G��������o������\K��bEi���T�:���s:�FW*d-�+�[��U��{^,�5��X������H�jI*WEZ�`�|�����G�O���������?F�I��[&;��eJ�x����LF��sB��c��xe�1����g�Sq��
����,j�h����Lj:p^�d7���ar�=��c�{C3���J
��L<fQ��U��ZFn��@�[
�]�H�/'�M��q�#r�[������&�����Z{%���h���:��������%����u��7�X��,N��k�$����XX���(��������c�m�lu����������^pcU�sG��M���H���U�3���L��5O����+���j����{gG`|��;z����bG����{n�����7�a?��6.�u��c�^-?{���p�����Q�F#�l}LN���W�o�fn��XO��U�!'���=��X-9ce��Ud���������p����x�TG'�b�uH�;d3����	j��a��^�����F
�/�h�HW%�R��s���1O��qg����?�%��"��0C��C���-[��a���^Bv.���������,�#�Nb��������Rr��Y��������N������h��V����R��:��`1����4���~=���UL:�is��:����ELjR���kV����u�Gi�?���<#����1�2����Z���^������1���+���l9p�������"JgE����
I�N>��N������>�����{)^eD����"��s~9����@t^�����z�4�t76�nk��Z���://y[���)�W�r28���>w75��bR����|kt��7/�����8�~�����A�u�)����P��o]^����2�����EPa�~�/.�/������hk���i�����������D�n�X���}W/U���?I���__�����{��d*=	>O��Ax
�Iz=��L�S�*�������Ff8�&��?F�(�:��1Q?���������.���mKy��K�K8Ln��-{�X�z�}�me���`o*w$��(IiDr-K�f1�Nk��F>�d��H�������Q���Tq����lA�z&2O3�U���?�����L/�
�_h���	^F��_�1�v�[�F�j��*�J#M73��QU��5����u$�r��;��#��M�p
}Clb������3�<�v�R�\�~��W��S�2!� �L��*s�J���
������K���8:����J�n������l\�Dw�� �Z)0B ��2��[\����0D@R�;����^yQm��W�na�v�G��Im��<1gQx�9*	�+���������//���]���m� �6�.���7:�������I�gc�vF����/�����F=�t��n9,�b<�qMw���1�^��:�"��^�g����O$a���>��a�$Egg�����ek��K���z$���e$>�b����l�Db�)R6xm�5����u���c$;T6.(j`Cb'�U��4�I��CkPXiL���
Ph95F�z8�&Nr�`���"������(W����������8[�&~������J�W=����z��F;+T-xU����d����)��EqJ��y�c�N
���4�;�,�h��FI�^��/�W1������6�nFG#9��	�l0�_8�
�T��@pN/���_�Q*>�x��M��i��+/��w����Kx�/�GF�[7��z�E2>��m?�s�b��I�!�B:��-��K~�i�q���=XA[���.`�/�!�"
����R�n�bvH��Y�vO76�[��f�;�C�6������k��Ml����Z���Sp�1�k���� ��;��r�������W�Cz�tb����02#��?U�/��d=%�64�/�y�i�?�
i���u{q�$
S�����n��p�f��/�C����8�[��9^.q���N���GrI����^��S��c�����������/�^�-��Q�
s�H����
����:+��P?�8���/x��`e�bH[R��M}J��?��SU�`7��r�:�f�^��,�t. ������J{X[��L�KV���Xv"��C���W(�-�j-�P�4xu
�����ZcR�fpP�3�~���n��AN���?������t��
^�B����5;,�\�l+���h45����(@V��/i2��a2��FX��1����`.�a��:���h"S��������
A&�z�;!�����-X	��.�L���Y���U�� �C�a�#yl����u��z��?���f��}4u�CI��������R�5�q8S_}��yl�;qn�D��dH�J��x�����:���'c�i����4�C��9�P��Pj�
� Mg��tSvP3mR����9�M���1��t��C�>\g�R�E.W���U�����^��C�$;@��!��hjV_�X����[�v���V��(��N��Q�F%�j� N���&�D����;o�%��K������;?�n��u�v:���/B>cw:U%CII�5]e4�:O N"��������r�$��K{m�y@5^/
�&0�u5Vm������L=����Fx���X[���z���v����;[W(p�V�n����n$����3���f����f��4'�n�!U�������V��5��U��I�`�<������m���shi/��F�r����5$�H~�H���_�~\��Gm��r��b���p��{��9���}JG�<~$�1T8���Z#�������q<��%��D�m���@�r��8��L���S�T�U��*p��Y�m�8��s�A�~)�<(X1�� H3t�U�x�)/DN��[s]�5{��CF���1�G��4^�R�rd���2��(�K�t�W�u8�w��)��I;r��|�o�=����P{�uB!����'�6Z�E�g����	.����:p�r
D�XoK�����\���"�	�F��+q��qF<t�i��"�����V��k�@v?r����)�����'���M��r�����RM1������V����i��)%R���\�v]t.��7
?4�2����iL���;0����O;�&:���sq/�s~2�R�!���e.���S��a|�V�X��gT���2=����Z*4�Jp�q]/<�����D�aj�W�P�2�N����Zb��A.��^��:���2�v/0�m;������!�t.�q�����g^���K<��e�)���&g��=�Z�k�� _���6�]�o���.�} ���Q���2TUha�]�6@��r��V9*�����A�dt]����bJ�G�m���
��rN��b`$S��l����P��qu���������-V���q���G�����A0lAu�����[�����gr�7Y_9O�+)�PRh�4rNT�����6h����Gj�C����?\/��G=J
p^��bR?�.{S/�?zDg����������O~�E��or�G����f�9��_���s�j;��,��=b�9zd�B�X�k����������^	�D�] ��������	d��a���F�+^j�U��G��a�(Gd�k����h���I�$J�cY��h:��z'��H�Pe��5'�UG�e�%w/K�(w�}��������#>�'���������G��qw}]��p��:)�!E=2��X���+h,����#���\�Q���#��`#�F��YYLU "�Y
�Rw�*yOZU�[�_�!�6E%�B�H$X� #��V�q����~���A�Z��!��J,��i�����v��?"=��nm����5��76&$|f���>�`>���b+�k|�d/l�����z!b�%��^���������`!��WjT��l�����
`�����kT6�ZU|vj��B����Q6���B���&nEl�(�U��3��h�y�bM��V�Q���,�+��<7
��Qg���uP�^�f��~��������t�	7�������G���Ld)
.e�R����/e^�u��P�5����:���=�Ox�W�+&�����a�B��-xv:��B3+�������9f2*����\����fen{g�� v�Z��	&f\��Y�_���&����Y���g�'X�F�l%"M�c�q��Eu���p6�d��2,���!%��3G��k�?�@���"�F�?����x���`������h����
�<k���Q_��o��dM[�[�z�|�Q)7U��=q7h������W�(�]���P�j,�{�hI}f����	O7�h�K9?qez#�^��&X7�NET|�{{�E�2�,�i�h������8A|���]2H1(�h�0{���i��6���$f��i�
#��]	����,�*�h�D�3"��-th��Y
"iD����6(q.���Y3�����3R)���&+�g]!�K���#���1���2+<�5@�%��+��Y��%�
w�����b4����>=R��i����Z����;���F|p��t'���Pb-�fVOG=�J�e�����?4�(�lb@q'���z���
e+n��xih
�E�L�v=�!����Ggg�n?v��H�y�h\��\�c�/�6��t���Ft�(�������;��-b��\EO?q�6���������D���� o���5�x�����lg����Y4�~��Z�7��>�p�Bx3f4Sb��C�F?��0�.�Lqy���EW$.�1S
f��F��XX*]���L�{��Q���x#B��ye#�k�,�-�:a�]z=Z5�����q����u�4����w)^3hiBJ���\[��|	�Q����B��f������L�7iP([e�`e1�l
r���|�u�u���Y��R�=��)��������Nk�Yb��N�Ls����m���9�����3�����r9x�{�Y2�P�%����,����<�&��|'���Z�4��hl<
���
J�.�2���t'�UZ�
#�)�/�i��>�%J����0�D��HE
�����t8��lE��h
mC�3_	����U����$b�	�6��_�;H3���	W��6�~&2bnZ�o�3�M�E���vS��*��k���pS�|��,�H{Ds
���������h=C]41�@�� :l_���ZA,TKjZ1��wz�m�i��PB%<�t�?Q{�8��T�3�f-��g�(�v��l�^mi�F%L"A�g)T���P9!�����@�:%�P�\�0;�75��|��'h��?���A>�ti$��U����O�DF�/9
��~oG���r_(��J�m�Z�������^Kxji�&�u}M�J������*Ve���gC�A�������!*$���s�s�������
g��t��9�#��i��a���Z �����0�+8�P�E���Dh���>}
�=��9��c�)��u;���o�>�a�dzP���^��eN�Ld)�G��d�����:����(]��YN�U�r+�I�E9�G+f��������r��cl�,�i���s��
����S������5U��������� n�jo����(�5��w��$R���6u�y6/��2���W���_��Y�Bg���!I�O�NKE���wq�;@emL[2���
�S3�n&,I���������!o�����$r	��2���9�~�v�G-�����1mL��~&���@9Iy���D��K;���k1����������EE�Wp�h.��Jht��3_��W*����o5�~��]���)�2������\����+]����e+�1��.>���W�1��8����f�I��`�&�A���������T�T�DU2	�[��Q�l������������m/��;��$�����[�M
N�I�Z���0�����,g6��%ZN�;����9>�>�p����5����yP���D#�S�����/��O�-�ZI�a�I$r)=�!�ox��+i��P
 �|C�;�.���7��}�����V��j����g+&��4���J���.��Z��*�%�^����hh��5�v��m�.!b����~,�\	�����r�L���p`�T�������"%��j������z���QzR>����sy��_%�^�D�V>_ S�m(|�������w'r|.pY�������Z��.��@�2�$��}�������g#�Jld��
�UZ�?E��e."d���{���E��lF�y�c�� ��(��=:>�����(3SE��/&iI# ����iR�OFQ������:�g�5���%����(Xw-�m����ugS��(��q�!�3;���:^�)�$�h0�D����JG(���5��_�c�7'������C���~�
���$�Q�l�u�z�t��L2!/����\�gc:X�H���x#�Cj4)-x�d�'a���Fw6I��u��%���Q%2I���(l�����*N�C�%16����N�����5�a�t������+��-��������Q46�^|�����k�s�e��C��z!z�'����S"�M},75����s���������\�9Q���OQOE�0
�5?E&�M��j4(����Y�d��$xO�j�����
Ks�-�Q���G�l��+J��Wb�����?tc�+T�d��#68f�ql�p!+�s���&to�K&5��X���|#��&���<O��o��
7��y��\��{S.�YQ�3�_����TN�M�,�M"�4�O���+���KvU��	��7���ty
���vF��^}K�}�(����mP	����e�~z�/�se�7���?���B*����V�D�%���J|�X\1ZK= ���phL��X����FqJ���/���T{6/��k��$[����n+^���@z��EWk�S����.�SYx}��Y��5�}v�,��|F~�;r��;�q�� U��aU�G�SR����h64��<]YHVX�������p�M������O����=�^������"��j��vNv�$a(F�3�������u.��9W1�bWb�M�(nhj��V����PT$T���$o����ow�jvy��Tk�:�o�2�CI!)O<�����_O���o_�%�$c�����l��������}C:��	d��*�k��R����x6W����#
���Zf���/*~2��S1$�,V������|c���,�)}4�a��+���!�f)+��y�38�����/�ttx�����{���}��+?�1��	�R`��7O�M\�9���!�*_�%������]��a����P+m��U`\-f��������<��aC�%��f<~�
X��������!��T�=Iq���J��� ���(�5��37�3�y��d�������t2�/�A���\Y�89)�W
������9�A�x����%>X�t%�|G�z����E.����//u��_�Q����'b�}a���g���F"��#���$�4��>]~dUK������f���-��V�{B��>�]�g
�`��$�
����?2�2�_�Rq�
�8�:k}SO���K��8A�u���EW9����$'��������l����l�5�I@�9�\�I�y-a�	`/�C_��j>�oH� ���������H�(5�$��R��
B)>��E���3D&�?����������_��^��Gw�z��_JJ����d�9�������B�,(o,���f�>M6��p�Me��8W��&����M7�N���E��,���\t\h�U<������X5W���J��_��3�����k%G&��������+�!�������
So�P�����'#���������!5r�j����)O�w�
���������{f��'��'�F�����q�J�7*g�:��KG�P���"��Q[�	B�H�*�������l[���
C����^?�D���g�����
3���e��n�
@�6��r@K�J�!)��!���f��`�'mHT+���B���:�mk��,�����H)7l_i���-1	��H�E�3'82�,���=������[��a����eK�"��PI��P]a�H\�
������G*-���4��M��H����3���+�%��x�i�U	c���HU�6�f�9��=�X���Z��cV��\���[��L�]S#=�sU��^�Za���N���J|�[��(�T0��K�5M���i.Q0Q�X�$B;���KX�VZQ�D�_��Q���+�P��,�=M�k=9�k���)���G����(
��\�k�ZV;3N�Q�g2>z��vsX��.���] ���Y6��"x��������7�?�{�Q��{%���=��59�[|w~���xw�����Y�l���������K�L��������<K��Q]��<�pL�8=�P�{�V�@����Un-]a%�\a=����{��P+Yt�g��;���Z�C����cn�,����e�}�Z�\��E�$@1��u�X�M�[2�PF�g�j����/N��i�mGoB).�j����h&*�]J�������Z�E��,��s�V_��f����IL��}�Q�&r��
�](~)��k���>s&��S�����R�S��\���]�W�����
@cR����m��N�pjn#�{ ��$��	�l\���4<��������%�	G3�Z�u�ic.R�;�
C�U��k&%V1b�GG��W�y��?��;���$�^�D�!�������*C������V�D�b������< ���Y���+^\�������	W�
��tzc��
�5���gNy�a�M� �f�����/�q6�<F�O�Mj����\YK���YC�X�X�e:�]�g�(�4�t�T-K{����/H3�S&K����O�A�#
C��9~c
����U�M �b��]���4'q>����� �
{|�m�</�>)8�58F}A,�����c&�=9�s�X����m����e��,�<���E��&s�5�^������h��'O���!��?������r���B��@��*~R��HOV\F���fI�@��AP>>���d�l�OW��
�y���!��!h�+>d/�
`l�pxn��7�3�"�K�>+lb�a^|m������k@����!�-EL��A��WY�\F�������P�X"K"��0���Z��7P���d���&��^lj�+/��,�����\�I�����t�$��_�C��S������Z*��M39����Z�LW�^x�fN/L��� �'�_���'�e�z/�7��P�{���(���N��A?��s+�rcN����z����rm�+�)���w}��sJ��BF.�.������L�O��$H$������5N�}M!!z�HB������6��s��������i�L�������Z����L���������26�[(c�����$��l� ����N��e!��j&�p{��>��76��V����q8���������Qq|.�{��q�o������p���#���)����8co��S*cp�����fr}��k�7�(�5-���,C-��=%��K5U�s`��Vm�BJ��Ix�w�%y�F��sz�1!�u�6!J�t`�\c���}���������o����v��>�J$��)2Fj��~$��5�&�vi.�K��X�0��5�<�g���-��,K�
-�S����/����d���I�)o�����;;������)	<;F�_��x�Q)�����cW�����Y�`=Y����	����@���{amB�0y�>����y��dP5l��*���J������i����+�&�Zb�{g�
�aE����$��	�#C8g4}j���:�f�s���G?iG��xvi���X�����N�c����O�<>vj��
	���&��N������^���!�jS�t�	����t���U-�r��P7�[����_$�d��ZP��_�k���t
���K%��j�{����D��X�r�<���������Q�o�O��}��{��~5?JA�l�G}AO^;�4
���,U�� J�]�U_�V��Uk.EmJ�&��Ap��� �ek�n�(����S��*nR
O��Yec��l�����I����$_Q^1�!�[�XN2~@
�����6�{0�]�� ��
���������1��#��Yc����Z�\�_2��PI9�*���L��5aLS�h��$ZP�6�p��E�jfc�T��P���A`(Pi���q�K��kY�>9J�ad^-��R
��X]aq��q#��2�N���'�:E�&u}��L="Y2c���	OyQKc����QA�kR{�-d���D2&�QH6]���"�QP�����iXi����Um�����������&�mk�����5J��fyox6�2�j�[��C��I����<9����9��o�G��_�W5qC�Pa��ht&����n����d��t��WI����_���q�
������}��}g���!�)Yc����� �a�������@��oB$C�5�����	[��Q��U��Z!sJ�������S6����+�+�
��;��7j�w#F�qR#�I�Jes����!H(�k�M�-��,��u��C�8��7�z�|���P���}Q:���h�+7gt�k�Bu���}��,Cg���]����L���Q���^>�k�M���<.�����-����&��:o[�^�����V� ���Vn��'�j���.q�����`�$>������o�+�I�
@�o��$|m����H
�e&������2/�85�
4/��3H��7d�Y�x�%���&�(I��Xs�b|�N"���I?Jd�F������j�\�t����N�!hO\����&.8���0����`:��i� q������/�=�������k�-,A��g�c���]�HC�}���KM,%�`�Fq{1��}��`e7��sv���4L"�$3�?����h���1�=�4^��$�'���t�#�JwA��Lh����a0y���Lze���;'�
K��I�P:�c�?����nw���������u�A��0�����a*4�4b���f�LS�^��u�c�vuw�^��bV�rIdGsA�,�����4��
~x��0� ����"�]�fs���jnUMN�cE,��pE� k�(����b��3xd^�����n,�6x��q	1��1�lt��w9fcu9%�_�&�k�q�H]:G�m#Xu4�;��\nL;�$@���%A�D�����*r52W���<u�l{�-!�[���F���;��K	U��:���h��8;P��j� ����M�������	2�u����m���y(���^}��z9��W�,��k���XY��I�{��MU�f�l�B3��&z4���2#n��Xaw�+��L����������UnK���0�9VO��~jBI�:}�=�1�����;�[����N>�(���z��cp������|@rM+>�%�dE1�Rc�c���[�H/���id\��%�j�w�C1B�*��_�sW�H�pr5zA��]A���=x��n�\�6��h-��d8���i	�a4=���_�����o�����8k��K���6�dt�
�����vo�y�\,������54�E�yC���UI *�*Av�(:�ufL j�P�I������.4ni��y=E���8k�����1{G�k�I_���]��I�s7$�$�0_'��M�3	@�h�F��-Yi5�T��W�}�f��<ql��^�R53}����� ��u������4@�QS�U�(��>�v�Vg������@wN���66�*B���ii�[����1�f:.kL�Ar����:���U��}��������V��66���V�[�y�5�x3�Uajd���o]H*]�w��v
��C��(.����|�qG��X��xww�D��e�u�Or|��x0;�T*/0A���>��d~���g�X�2����]a�g�(��YC��%��x����>z{t���rM�����Q���}{�?�{|��8x%;I ������X����K0��E8����i�\�z��Y��	�����t�6���|H7_I�xM�5c��!������|��VQ`�X~�2w,��#[?��MSM��Z��"v�����U�����xu���45��x��C���M�h:B��t �Ds��I����o�23����������P��<��f�J��Pcm�&z~���	�4����T[��w��y/�5�����Z��j��I�{,��t�$��iL7�	���sr�MI�"/��
�X���5Bl���Z�v���L�X�)�J�+JF)�#zMw4�V+<)Q���p��At��d�2�U�r��<V��eP
OGBu�j��(���h����A�)���'���lkt��>HfE�
��M��e�2���UV>����0��)n����Jb��yc"^'���lA�M=;0J�j��U�gz��q��}C�Ng��$dO�������d�Vr1����
B��Cv�)]&��������v����OR�%���7h����x��u�6m���J�m���nm���M3�,���zbn��9�A/�b{X�U|��oH!_`�&������3��n	�MIi��4{�7�{�%Z��s���zuzc�Tp;�������%|=J�H�����fW�z#��;�����
���}����MN�	��D�|sj�6��8����?�����+b�����{�	g\I�W�
��X�}<67�8�'k)�S�N����/'�r��8�=�r.(���tM�1syq:Z?��9���2J�^?i5�F��
��;��~m��k�������y��Ns�q��if�����L�;��?���H��xw�?����~��@���t>��]�K&j����$�i8�k�CHow*��&{�vzr�dH��'/����	S*Q�uO�b�soV�z'����V���)@s�����-�J!(�� �	�~%�R4�\M������@�YV�`1I��-9���V}c�EawsU&ia	)N��y\]���<6(�[��I_A�;��2+A?9�����F���B�B�Q��0���:�>�^sz6J���*��>g����v6�g*j�N1�6j��/�d��|�na�!�:�������%���<��I2y� �^�~�G�	W�5�^��}]x�����b��#g=�T�t�S����8U6���������q�-+��NW���`
���K����/QP[�q��e���VU;�+�{���A��2��*�0'E��K.=g����y_���<��/��zp�
�����V���X6Y�euW����9Nr
xVV��9�X�����O���z@ch[7�U�-�7*�c�Uoss�]�66���i����W�����3�'Zrwb��%�&���c����/F6�?-���0��������*&I0��c(T�y���B������A@�:j��e���h���s�[��/6�,�g�Y���y�mV��D������9���K�6S_����������8��X�l��v��=���h�U7O+K<���;����'2;�+��#�	sc���v������`}����w��/�'����5������������r5���$�x�9�`��D4���y"�*#��>�������4=�~�~���t4����0����]&�
:<��CoG�yB��[s[?�j6�Y��������B��6��Z66��J�hv�/z������HdiGw�\�U?%{�l�h�l_������Mr�HM{ovN����l3q�ig�IJ8�������q��?q���/��?�b���xj�q.���V��V,�Hb}���4Q�p��J�Fl�6��V;��,/A,�������i�����H:rv�VM�_>d����m0���Oe�A����ek�l�
��m"�L7.������$$��5�M��Xr��e�X�5�I��r��%��=i"�v\%���(��P��Z�[�6���m��q��XAS���69�/�i�������n�FK�V��x�q�<<�}�,1X�����H��ao��sW�Ki��x�������������m�C���2��QC���!
�EG�X<����m�,w����5��i�:�xy��+���_��L���
���e�u��_`K^�Jd�QC��~4�
�6��?���(��gxa��4?r8���yD�X{��-�O-3�}$	����g�J���2��������M�Geg4��	��kA��nA �6��O�G��s?��?�Bu4g��'�������Qtng���0��UV�>v�ba\CM����s�J�Lvl+Jh^�
�X%�+{��<�Xt�O�u���(��)_�X���P=���Xr�x�d��sU�57k���������}f@�p�dq6�����f��q;�]1�Jn����l+��������l�*���������^��fG��?
~��g�nt�@�����K9����u���s��x�UQs<�x��j�u�l�xZ��E��>Y[:'u[/�X;����f�����M<�P����36�n�\j��O"$���)������������CpR�F�!T9���&z��@���}^P��
[98C�	��N�L���*O�t��b�p�����7;��U�H�����Z�Z�^s�(a:�i(0�]���T���3�i{�P���L:�^�S��"KlEf2^�VR1#q.7�3���4��~�����I0�o�W2����iX@1}���[C1f2`��W�\�2��S�� ux�j�1A�D+4��q�k���r'VT^���;�U3��"�{gAxXoN���=z���|ap��	�|(���lB��SS�Y]�Z�T:���4����������sr
�#iJ�&V4v��Z�m�����o]���IoD��t���<{<z��+�{o^���pc���l��)�������������Vy��d���w�5���U����,�^����ox;���W	>�&Nk��\����>��n������B+b�!(
z�}3�3�5�,��1�0;K���y������w�?�|��~'����'{.������w���_�;9��kYr��~�~�`����^��2��{�b�������c'*a�d6��MX����p�����'�`��5�<�`�*�J#��e�
K,QdS��5w��0��}�e%��������(!��~�1���[�-���<������u���y�Hbt�m��D�7t�U29Sh@���h�u��=x�9|��9�q��/�m���eY��vw�,��:�?|8ys����l�\k
�d���D�6EB��Pf�e���>I��*�qx��w��������������B%�-O���i����w��'j��K�$�}Al�Z��X/I�a��Fwpx�>�&��Cw����?����������?x�U�=x�}��n�d���>�~7��h����hW�Z���}�S�Ko���7,T����5��j�f�
���)�x=����V���5z�m�Z@�F����|�j��6�|�l��=�)&�lmM��a��y{#��f2{]3#��Ti��Sk��@�L����%37�%����z|����{�o:o?��w�������G�'E4�����w{��&������	��&�S3�Y%"��JK�������4�K��5��Z����t]��j-������8�_m�����/������m���f��$�QFw���7Ir�$�N�t��~f�Yg��4�O��&�WR�S���*%!����G� d�o�`A�����)6�S��"����Q��� bG��)�fc����IG~9�*D45�k�$��G�FA����eh�%X��v������W,M|�������R��9VY������'�����'����f�XNo���!���j����H���'����+{�e[N�d��	������k���"r%O�Q��W%Va�X�~��lad�z�[�L�f������
`����E�?>��������M�����q��7:�K���F�JE����)������_���K}�@�!����>n��������d���<���,���h��r��T2cB��J�#��n�nf��u���nIr}A���y#��hb��@3%R/��xm�qRp����������h&V��Ol�8Q�&�Zy�'�� ����}�}I��I�(�v�
�
�=c��4�c��i8(��P��U`�o2'��5@C�k|I���U�8�c_�e%����x��W{��H^Ys��~��S��)��:���Q'c���Bx��������d6��c�.���!�.d������G�<.�������f���vk^Vm��=
���Ox]�����M^��;���[��N�C��64���q92�_o X�� ����jv<�rDU��K`���iot5L�!G�������<����IH.�{K�$���Gf%�.���c��'�Z�='�k�n;��MO��dl0Y=�
�3Dc�j� �I0�ak�����!��kI@$��b����5��������9�q[�cO;�����A��*��$�m���!����o�,R�#k���~{��BML@7�w�^���[;�S�%ZYF>Ys�L�!��������������S�R9pw����8q8��2=>��v��%�2��*�t&"s^��L/F�s��G�F���_NH%s$
��x���������t�����FS���u����^������$����69���rB&H�����4��-�/q��k����t|q�x�<`�����a�G�OT���Bgu�����n�������W����d]X���������%u�|x�f�dw�oU*�#�w��Kb=��-(�C���T5GuNx	?��m��0�V�!N���z�8:�%����jtF[��7U�����'N?���
�wz#����t1�������`�w���z[�}��k����n��7�����q\�0��fR��/��f�!���&R�,v;��Ov�T|NX�0k-�2%���
.f�����������2J��"\+�d,�u�����
����F���H8_�8�����u�Y�N��� 8����	���;�=��}�3.�#��YQ��A�.L:���LMdm�I�uz���f�4��e��a�)E��1`�����9�9<��pt�{p���5�D�M1�W������"�$������+�d��iv�j%�N��(@ �Jl������J�)��u�7:�Nd�n����{�a��h���#�1�F6��l������!C�5>U����eu�V��%�A������#�����kYR���`(M��zh���tG�O[�s*��v�l�T�d�x+*:��D���v�����HI7I����� ��#A��x�6$��$.�^E�V�k}�$�_VJ�����Q�t�^�?z�s��<�o�I/��?N��\�l��R�F��!v�����wHe���,v�Y�D%N������K��"��������L-k��e�����������������S�TRqU0����T(�i��Y�rO�3Rb�R5V��y���F}{����	��Z�Z�m�9��%3�$$�Rk���������,*^�
]�E�V��cC_X��w3>>�������Ku������p��dL���0��C*9���x�^b�,�vr��'R�P��#m*�$y�%�����6�w�O2�<h��d+��N%�4V[�X^.�����C������j�m�&�='1o�,�	�.���[6�ug��������6g�jd�g�9�LR#C�?�%w�f0�P�9M��7�� ���&	���<��hg�I�	6�<s�Xl6����K��q���(*�Jf��'@��a�*�n�+�T��2�^_5��&�	
^.�:/���U5����e)�������j�4�bI
����m&�(*f`h6�++�]9���n
��a4N���Y����`�Lh:�U���D3��c]c3eK�����0�n�����T��$,�S�������gmk0����n�eZK8P�d��H��������p��w�������9�T�f!;�X?o��tdL�Y2�\���|�Ku����M���K1�����z���o��f��|�k:�R��JfG�6�N�81�p��-x>7-PRuz���F�^2G�������!2�/�Gv"<i�]�	Q�q��CZn�i�������X,���\�,s]��\����m�II��u_,�1���
�nc��
�xM.�����#�_�~�|�OkN��N�3�8�>�(�Y�H[����Cw����{W|�o�y���s��aj�y�����I�mb�w�hHz���7��/�'��G�lnH���)S.�b�X��s���R��1�� (�/�k�^�=<z�{�������Uy�`s_��c�(J����'���>�L�������%OO���sxp��n�@�����4=����~�������3H(����?� 7'm����!��7�b�z������uYs_vM��2��x���z}q���-���9�fQt3��Y�������&.����^6n"O	f�
5�K{}�?����*(�0��
H����� v�--INyv<�_����ct��������(�9%I)�}p!x(������U�9�#)�fKJV�������Zzr���XJ�w2��k��?��)?0=3�Z����$�N���3I�i�~4��dO�X�ef;����F�F����j��1k����R��"������������S"����$ �a�%�#��A�n
�%�'�p���vx#b���+���3=b]�
�����{�������s/��6�?_�Ut�>��x�G�@2����eE����+j�(�����R���� ��*-�:�~1��Z��h�:s�'tB�7s�
(Ez����G�����g3~�`	��g,�����>��������b�E��d|�]o�n���M_Y@u��? ��+�1�n�`�@({�yxv��lqPR-)4'�f��iX�1"����F���6R���\5e��`}=+�\f,���Ysy��Y�����])��b�U��{���Bs��Q
�j?�8J#d���D�v�p{;�J\�&v�z����
�	��c�0�u3�h�Qq��X<��
RN�)3��&7� �����i��(s�J�!����F-Mty^��0r��lZb��{��x��1�Q69"t�rd}��$~���k<�N���U�V�)[/�M����g�8��M�K	�M���9�)}-u���<��8�%���B�Y�8<:�����@-sc�q�
����89����!�`A"��;�q�w��AZ{�?'"����9{x>.G�&�}�=��:4��A���nz�������]HG������Y�l����{3I����k7������vlxT.e��L�f�4���Mr��H�ft@��+�����4�����L������3�m��5"����*f{���Z�+��w.�i������p���"�YIq��-��>\��G_b��$d�6��N���_\+���2$��H������n�5��
��lH/	"O�Py��,�J)�������4�t8�L����\����>�5���s�+�����Zw��8��8�5k	�pp�����?8�/�����B���~��u�.��&�E[f�-���n�D�\F�oM������3�?�^�V�H)ud��`H6����9���Q�����D_����5�
AJ��`^M��;S��4�V��v��+KQ��]H:7���F���#����FB3�]��{��I���F���n��)kD���6�m2��x������3�-���/L������2dK�����V��n8�~1�3�H�4'���&�K� �@go��K�zqh�	��m[����Q�'�'|A.�����oL�!����m�^��!�6�'��h����������W�����f��D��X@P��%���;����I�dl����4@OG7L�d~��a�B�gZL/
�n;�$�+��(�� �����Q�=��f~7����H�$���1��%|����!���S
K`y�'t�D�Gu��$�q`�
��3�Qo��k�pR���H���}D]�4�A�Y�g��X&���t�1�{��%�i�]+s=#�g}M��$��<(	y��E�(#�7�a?��6.�u����e��l3���E�%�������\��p2	��^�M������a[��X&v��� ����`���d2���zr�R��%�R�e:��m/��}��M�HSwx���Bn���Wf*W��J�l��^.PyB
���k����Dl�ckK���Y8�2o<�;����x���Pzy/����9O3��������`+v�]��;�f�|>��*������|[60��s���7�i���e�.q���[�l�^	���5��0�d�\0��/;)~9�GQ]Q+��i��V�)�i�$W�.~�OF+���d�H���I\*�l8h_xL_�4�?��M�Z��R�	�3����'K�5�
�Hg��]���{�Y��N�
��������������]49���](D��q����$���5�����s����U�~�Ak6�$��������������4����^��$��^�������h�4�]��+�Ml�Z�@���c�#����������������t?�l����g&$X�2��M�j��-07g��a{�2�9�z
X�9�H��h��<�������d��S_�H;����Ulo����k���{sQ�t���ow�O>�
x����d��j�7���5����%0������HR��a��D����s,������JI����"���d
�8.���<~~��/��>�<�����;�&�C���v��+�8�T����I��a���zhn��N$��X��&U��]2�e����+_���Q������H�0D�(��H:�g<��X��8��+gd�2]:���'5$�X����$�%�	^��s#0>����66w������9A����d'A���M�'n���������������O:�����kwi���X�����#�Jg�8iw����dT2��%e����l�J������Z1��}�@R(�&��/1e���<TxG�ST))!���������oN��Z�Oe�����I�9=7E�9��gr��� ��<�EkR�8JN���G�I
>E|(���iBc/1���Q�A���(4�_�M�50��$�����UG�[:s�_@����z�����#��������?�~��
K-�f�6u �X������{?*��~/�����<�o�������G�;��F�����|�*�d�������t�����4@�"���/%[����w��_��z������&��4�6��>���������a���KSz�6?���5��"�����^/%���Lx�OQm�2�Sq^������N��0�X��anS���y������D��6��a���g����=�e�Z��m���j���^1at����z�8e1{�8�'T �^J��,��t����X��4%�|�Q��y�x�I��v�l��f�������m�jkB0�"�����Q���N�4�u	��&=q�P�`Y��9Y}%��!�j�M�0��$�mLn��D:��6�)RN��z`	�<�M���m<
w����"��}`G��Q�U����w�Gi�Sa>8Fv�
D��J����T��K��
�h�+��n�KH\�v���l��5=b��y�L�����������J����%�ty. ����!y�U�k�>�G����_����P��
(ct$������.��IX��8��!@7u����^�?��f����Y;��N2�~jE���X)���A�$�"�\��]�����S�uU�d&�-����z�_�k8~����t�g���OD��2�{��oO����D"���}5+�g�����
�1�%�@:'�[+S-g'�Y������p-��kvD7��8��l{x]Zs"d�����#��?�;N��y[��~)�n��&]C�k��}r��-@���N&yI!y*(��Mr<�]a�k]����H\@�!�+M���%��v�l�l��������S5X���F>�[��+gXVA����]���S�������Dcf�F���W4HA�%�Y����������rh�P^��s_��A��<�h�q6��QXmt��w�%�X�{���c�K�Th$�d
D�$���O��SFi��6�c��.�����T�Sa�4�������8:?=����(�����$�����7"��(!��0�K��i%	����~r'�]��W��I@E���Om��W�����BS�?6���i��+�w��f�>�5q���eAK��:�j7��/�_&��)X(F:�q���8�>��Kf��L�\���Ns_�&x1��L��[�[���YOF��8�q�GQo���&����o�[��3#z�g��x�����Fq7�H���Yax�s��r 1x������$�H�~3���c�B�C$����M��?4M@��X��>V��P'��F6��
 ��qx
,���i5 ��P�}Z��`4��.G"+1��U�m������������TXt������D,���#�\��Pb`�*h�����fc���i����������h+�B�g9��
�XBx�QP�����������x�N�3p\I�m[$���3��iF��S�W�N���lh��I���-p(��1d�%d��������A�F�H�4l�`�y)���k���	������_��$��f[	�� ��x�.��t�����e%jGL�X������R���-�r`��	���5�$�n���f�����~��B�G��sp�70D{��+�=������*�A�j��^6���OF�#c9�	dj���J�b��jT��o��3��)���,Y��+!�������u���<^J�~FE��Z�f���`V	��6O����`{i
�'�]C@��H�lR��4��"?�K�c�� `*��T�U�����7���Z�8������^��������$�^*Q�O���q��,��)����D3�1��C����s�"3'y���l�N7T|���G����tl��t�����e������*2�9�-�NLr)���Qy�n���PDc����\�y�������n���W:����^������`]�����4��-�`�M��b�7`z&V&��_�3��N�B�R��D.f�Ft5yWx
���_t�&`:��!|��5g(Vc��%��KM����z-W��9Ms)�^b��2�]�qg*LdaQn�������,����G����	����3(���%2ny&zp�	�k��L��
i���:L5N��!�$����M��\b���C���R���b�6��a�b2��K>���!�����w������L���_�\(����S�/��U�k:�����kk�|�m����Gt^Y8L�F��%���$����9��c ):p�z9N���z��{]���&F�E�Bx��z���Z�@��"��m[6���T����,hP����11E�'��tk������zp-�����O��B=�J��(	������
*��N��'oT��V:��
s';�[�[����P����8�X����`��l���x��d��dn�a/���NkF���? ��l�jj{���bg��?7���aO����0c�>�t��C�`���P���T24Y��lZ�C9a�c�����?4��1t��p;&�UfXN��59�%E�%#qq9yaI��f�����;�2cs���z�9�JbF%���P��R��MP0����\@�,��l<�7��1_V`�,17��zL�}�D���#P�!$��4e�F�������&�Pt%LY����~�:y�~���-���c���_��d�!R����S�M�?:�8'��*��as?'�+�&m��D����+���
�I=��4[&RH���N.�Q0O��������^2/������5F��t�&����F�="��b��D\�pr�%C�j������H(Ho�e����q���q.��2������Q���"��m�F]��i2��������=V��,�m^x[	l2�u�]^�2�TJ������!���E�e��;6�y����f����c�SV�\�� ~�	@��f�������-6���Qc����;���[��e7��X��[����|�M���A�8p�
4��_d��B�����5�ysf�'�g��b^�H�����EZS�6uo�G�y{J2�b���g����K���^n��2;?0r�����T��H����{�.�����;YM��������"�] M�����;,�r0�I��[������cHd��9��>�����W�	:m��5w���f<�I�o;���,4��6�$�@�n�{��'G��;��
���^Q�t�k�����+^r� ��U��Y,���\T�q5�_=N�<����L��<�x����As�cCf+�����c���(�\�:���s�h5����1��c������^G����\�jm�������xN:�PU�,��U��Z��{/���D�x�`a��n��	D�H��+���q���	�|Oi=!�������^B���&�l����i������'f��U��S��<r���:w�(K?��a��B(UY�N��dU�4��t;2]S;�3��-&
i�@���2"�#���==��Sf9d~�F��]s�yRE'�'n���h���,Z�bT�eD�=6�H�E�8EG]�2x�:�$b�A�8.&ZwO�G92_Q����T�m��e��
J����b���`@tf�K������,�����X�V�����f3��GY]�.�g�Z�=-�}6�E_�9&.�o�j"���pO�;v�Nx��E���`PsqOR�['TW�����h�K���}2��fa�(����L6I�A���f��f����K�_��e�K7��d��c�A�k������uz3.��{������5�������f�Z/����a|���rsG3�������ZIn��9�fU����.��2;�n����(��aX�.����l��L��������$����M^
����y��(&ZY�)�1vo;4&��n��/Di�ln�86w����E�:��n��[C���f��������h��lyMB�/�PF
|�������^��'�o(�ms�����u0M���G���f�t���R����
Y���G�K�����=O2����x���hB_b�I��d.��er6!	�4�B�^���B��7y3��t�d�_��M��
�h�����[s�����%��P�\�H�u�l�2��y�8��qB�e��=!�����������)/���f}3~u�`�-R���O��l�rF?�<�������^��]����~v����S.������)'��.F~���2q@�*���'�����+K���N��p:�:�3^i0�ejv1�8���CZ�\��?�<df�	�����%I�|���%�ik�O*e����3�_�5��k��>�#��5�.X��k����W\�j�pD,��(��m���z�X����u��\����
�o�;��e������8gJ���K�%��T%�PZ���Y>��H<������Rc�:k�r����'�R�#�s
���L�����z�Q�����E��c�!%7���X�%����a8��kX�4���H��R���=��K��]�������%h�6KN��9�/~�7�����y!%�X�U �����7,0�����a���Hh<���4�����=��`v�J>�(����es��w����a�h�����@q�� 'z�C,���J
B}��/�j�ht�pn��m��C�2�����N	Q���=���z�f�]�������.^���<�w0������,���6	9Sx)��G�I���q��\4E���LmKT����d��ep/��,yc��o���������,!�Rq����:K>��e����[?`������T����
TR��9EL���ov���hp�H��"�������oFb2I�s�_�lD`�({s�J�d]�u��r��6�E�E^KBe4��"M=��R���/W�L�o
��Mo�	����������;��
���R�*B��%;�u�����N����{Xb]"LOg�c	�"
�\Mp��*H�`��z���o^vw	��)Z����i�.5��q��WSJ�_��M(r'�7�!`NB������wH�FL�����9�]aS$�-
0��f%f;�Cs�;��zc����\���Y��*N����m7������d�j=�=�L�/HC:E���t�-�M�Ad���v��%Q�2���T|�0x��^���L��/ocy��������.���0�ZVL85��fa�6�)����rt�E����$���_-���IR^��<�N���,1]"A��$����U�����$�6���,IIe��� 7DD�#�=Ob=��������R_J(��Qyn<v���n���YR���&f��%1�����\�E
�5���O!���df�E���\�.��_����\���.�F�I��qR�H|lS2�_��K
:��L3n\�$#�f>~�P�Bc�B�����n���8D���pt��^"�c����
�����d��$��WD�b�%�,�}��I#k^X)�l��hU����%k�s�6��/�P�M*k{5?K�c
5�\R�B��Ux?Xc��s	�����9s�E�y$8�����`�i���������2n���.���,9�p����8��6/�����{>6�/�H� �����^������iF��	@w���}r��'�4������GX���p.��>���x�|�L��Z�d����5;�S���G��$
��z�B�yH�%S�D�1�%�Z��+��Mw����W�d"8������F�EQ�
���M�����\t����i��"��1����i�`��	���>�&~��.l��L�7�GF	���<��Y�hbo����Z����b!��Y���[��C��4�����F��X��B�D���E�-�@��Z��o�w�gIy�4��z����o���k��
�"��e��ah,����\��3�p�k���GVd�1;I��K���!^�����Z���!}MeJ�lm�K,�d���P�C��dt���a��F����U�t�����)G%�����?�����TYZ���0~�&�����)�DI�(���NKI���~^9��3SS���2���>zpuc�S���#>N4�v�
��T���z�AO���Y�d����}���da����KKn����VJ�*a-A,��t�l���bG�*hZP��7Sb��O��X|��.��D�?',d��F�D}�`��	�C�J��%v�3��B�i6*q��k]|N���y�c�&�t>��3���e����{L��\VH��!{��|���$�PH�I�����}!`M>,3�����b��`��*}��XC�zT�z6 �!��CC0�WB��X�N�?�@$��������A%1
k/&J��L�}��?bb;'�Mz�<���4N����W��c����MP��O}}o����n9]
7A�@��8�^��������}��/V$��H[��8LGD3��sv���E`�T*�$Q0����Lk����{���A���k:��3���!���;Go���3x�}��������N'��1c4!j�#���B�7�+��(
�M�p�:��>Cm\2Z�A;Lr��_�w4���I���i�-����0C�L"4|���&p�+�/��.���&��J�d/4����(�h}A������?�
����-k�z�rPB��t-�����������L���-�n�2���A������A�:?;����,���-Y�E��!?)~]Q���p��/62������:�+�������z�TJ�y?��.�O��@���cI!�0Ri�o,�Y����BP���
 =I��ea]N!]6Bp�� �G�
^�����b�hx��.��Z���hNr(.�8�^�0�u�3l��Q��e��z���\�_���D���1�q�1m>n�z�@��2D�d�
������L��*0��-r~�x�vog����h������"�^����!��@Y�������!�m�v���j��\�g�<�^|?;E�I|X�2Q�OMB��h0>�
T�]F�T[��pq��mpM/F�Y"�'Rd9�6�7�-���26$�d,VLu^�%�DFWC%6�=HN�K�H���RG��� 	)n�F51R�Kq�2�w�O�F@��Z]V����]���l6N��8����y���E<��1�u�b���HR���r46�]mX��Ok�YG ������R[��	����A
��)#�3��^r��}?��YT��Po"�:��3�r��7���]2(�����HSQ��X�W���U*�V��.+>��y>2���:5J��	���sq�bB��������d��x#�k4B;��&
����}u�?<�no�>G�6]]��IP��#x��4y���:���)3
'@��b�����'KlDgr�E����v��Yb;I0�[�
�p�){'���w'E��$�rrc��jek+N����bQ�Q'�`�I�.i�/���vw��y{xJz���������L�R�Z�T����/��Qrz&���O!�$K���������w�|�_s��A#���q��x��aS}l����'����*&��<�5N����`���-��zvk�j��t��-��9��2o��������OT���a���ik��J��-LJ,%���|�����_(A�z��@ROv���?6��q� 3��K��~�O;��X�$�=��^�u�6{��{�iD������?��cy�1W�QS��;?$����fDG�`#w=;���z������1�����{��y����\�������L0o�4eS�@B&����s��y���E2���2�z������������
�%
k,��x>;N{����&)��850����&I��g&i�+���qg����v���sc3�{�N��M�}s�����38�;��VF�����L��'����;��1��S6�^���,82������/��yGO �o��K��i�P����7�[�]k��7�Q;�3�NCQN���d�E�e���ldl,��v:u����RZl|5[�$�!����Nf����S��)���5GY/�5�d���������`�
�t2x�{�����f������v��2?S���^2���A^@B%L����W���F?�$7:\�,�sa:B���94��[�,���4,��Q����oz��*���#�<����3�)�}�r�L�������\�L�_������NQ��`4�e2	9�5p!g�vl��y��H<�M��!���S��/s'��>S���_�	�>���^�����I��6#�k���������rRW���� �kl�E�0��~�2����d1J�����r��-4����G��f������G'�o�2\��e�����P��a&�X`R��;Z!�N��Z%u3��o%l@�{G���������;��Dc�?�.����zP'�t?�!99�4��N/��[M>�����S�u�C��
/�Z����� L�{�����h��N�c`�%�3W$�aV��C�?�4J<��Lmm�����/���)Q:o����$�}����i0.2��_�����:����&�r�dZwb��x�
RU�q�+{>��}j{�.Z�����_j�$��Y%@K��kH����C�����DQ����;��eu�����)ph��7Ca`:�'����f��R
�����������}��	�������(���Ov>9�{c�~�eC��ud=Y�lk���&�����:0_�#Hv���5(�/�WA���5�/����p�|��i�
�w�zKom�������f
����/�\A?�&0����_��1�f��D.��i��R����b�s����
����/��E����WJr+��Mt����$PqP: ����G�iTw&l&��6�^�z?h`;
�%����|L��wl�1�frT4�g�n���O#�;]�����k��"�,����/�=���������>�$��,Q��(�����IrB��}�^_�sf�u�:C������sv:G�\�)��
�$�U�S%���/�� ���5��L���I���i�~��[�����ON�����	�R��,#M�*�>q�����}*���4Y /i��s�^���7���q'�T�����'�����;���~�����kO+�N���4c�'*e���w9��������{�q;��,j�^dD��s^�����wc<*�
�/oz��A�WD�8���:������J!���;��N�C��D���"������$�F_��H{N��2�{Q���4�*����������J�@w������-#u�������Rdd\V�X����VdV�@"�$F�u�@%��x�|�����]**Ny%����NU�r)IP�@"a���6<gq�&'/�����Q�����E��wECtJ�m`�d��^�vb�� \��)��{��k~*���[�h�:R6�8�����{�������	�\����,��xv�k�������a��^`"f,~\�z���?f���KOH�Qf�\8.\�\b�^������I�O�o�e�z� W��6�w�6�u������S%6�e���=[5�������`BZ;��o��c�[�����H��S�T�K��`l���PM��jH���!.[r�T��<9�$���"��j��4(FW�(���)��9�2�j����]0El���Qd��8I���V��N�����PS��{N�n;��U6�j�+�J��6!�.�<�Tr`���{�}~����}Nv���g��������L�d��	~���3�8������z�_d.�zzqx.�R�?���H~a�J����]���9b�X�NBf���}�!���*66�M�>K5g�1��pU?*��u�
H2��F 5�H�V3F�pWF�L~����k@����$�O=��t1��m�hwk
��(�U��{3�����@��]�OV�4A�����3P�
4�t�,�:�H��tM$�"�R�!�_	� w.e�z��X��Rd����-ww�P�gmwg 	
�9LHS8ic�#]���p0u�b���Z�}���f6YVh���j�b'>1��F��z�oR�	�ut0�}�(Nz����\�>���1�R�j��4�
+��d�	���>��Vv���z���s����t[����m*!n�dHuPH���$43	����;���w��x���9�k���QRN�	!b�� $�� 0Lrak�0������Iup�ru����������O&<$�u������.q
y2��=�l�>F0��kSN
�k1�3eU�su��K.W��W	��&���y�$��Q�+�	I����186�
�g������]c�;u����Y�z'��}��o���n]��_|�L��E�RG�_�+j���,jI������RL�p��-\%�U������kN%y���
B�9
e�	�a��������L`Z5J�3��C�5�2��1��)	)��K���;�����Z�6�K����I'�[A<��jg�k�Dg����;XE� o!u�'��s�eA�|��G��f����������Us����-\0�tZJ�����dg��G'��F��
��/gcZ�R��|�WL%���,	Z}��(}�������A�=������Q������pu��R(��XM^s�� ��e=�
14�FRFk���_aE�X������n��]����ga"_������q�)��p���x�"tnY�����d���2�-)�=Z2�h$(1�SG]b	��>�~?���@^?G'|����9K�G'��g�?}<��8||px|xq���*jLF��0�Y�����c��l���l'���5��hqm�9���pg��Q�7��n�Kg���u�6��=�n>���H�n,�6���������F�S����&�!)
�2�23�t/���`5�����a}x3�LXj��=)j������F�o��xO��VdC���vxzvpx�z���[���~���!G����x���V.��7{���'{���.�����NZGK4�����p��q5*��HlW@A��|+�W06%Y�:��#��1�XF���jh*��!a]�7�G�CT�qoJ����T2�-M������$q�O��!���w����AO$p�� �AW���(��`F��H+�c��	�f��d��f8���W8|����u��	X���/���&�DX�.9&��D�R�b������0Y�����\Axrvh���J�>"u���kN�y�$�2���mR�'f�G��r�p��1��	�C�G���9Aw��t�:���.u�*���D�Ey{|�����!��>~xsx���i��:"���YacH�5�x�w��"sK���mi�7��aD���o��oT���|�Zx����.����UH���Y���{/x<�wk{*�_g��q4u�����G�������}��9�J|R"$&���J-��t�)e��_e���G�%��0,p���X�jH��PB����VvM���B�m�C�"=`O����+��%o���������wA�Cz�fok��F��b�����/��R�Z���TF�2!8����cQ�9x�+�q~��XS�DA�L8����JC�*�W�#��@rz|��B����U9��<��QI�3��R	��\��H�p��R�}�s��a"!�0#�P��4���X�>��_�iP�F�G!�6�������S.��(j&�fJ���f)�?}�L��K�tE���c��2��|(A��������.a��bK���$�Sr��M@��b�A����Ap��P���`��gT
��[�8�����Ph���q'����d��@���h��Z]LT�n�fSS���N�E6mR���lc�� �o�:M��2DG��X�fO|u1��bbBaB2�lm�wEJ�W-Xw���V*d�����O���U�bp���o��3��N�m��V[�h��w��z���w�EX�Z��WY��>�,��'a��I����"��p�D�����������y7��F�E��$i����Gy�M�>��9����5�9���6+~0��bx�������^DaEaX"��x���_%p�g%r�}z����^�a��
��J��k�Idh�&~�]�^z�w MWHB����o&8���*bo���o�KJ��#��������l.��
�9��:3��HJYe��]�
1���}��J�����s
��#*w���T�t���C�����vtI��\�{��p�p��i�n����aL$�a��@���+R{e�F���Xj�%����y���.�i4�/[�����+d��IGQ7W�{�1'��[=�����J��}exw8L��&�����s'
]�v����Q�>*�waw����
�]���������*+x�E[T�������8^[C�n�3E{o���h�$��_�W�'K��1�l~s2�'�����2���w�U~���v������E�w@����J�F7`����C��@S*�!�`�����"��l$&�*r6�-��#��w�j�{T�!;����^�\��}:�h}��<����m�N�.6�����B�N���f�On�9�d��{F�S4���8B?�{#
���z�C�7�d�d
|�y���iK��u�#���0�u��_��:4�`����hZF z����eR�70�����c^EB���o��������'��T���EF���N�R�	��S�6�I�U`k7��Z+*���-�]p\�W;�����!���yLjo�S����1���@{� ������E�cQ[YjV��R��OL0����R\i����K2_D�������A��:w*�R�F���ilxlYn�Zd�����3=�Z���E6���A��5'��]�wf���8�w~�AQfXe)����,a�9)� �^�u���J���v�+��l]�ls�����x�rb/L����{�]#!��aE�~<����_�QDN��T�#^0�����\�������UC����'�#
��S����tA���E7�����|�AU�c�R)�����6��9�����g,�[4�aLoL^��QX1EJr~^�����'{x8
��~�1��d�
����l,4O�*�^%�)��m�i���Z�E�N{����� nO��w_��w�Y�D�oa�y������1h�K&$3���4<����<������
�	�d^��0�vrD����cs������2�����"������;���Q���"��=���D���e������H�>D�|��	�G'��*�r�����}����:������vq����)����[U����U��X�S��h�V�,�Y	/	�7]���1F�l�A����"���[W]a�s
>��S�k��$�/q�,iY
�>��1����M}�5�Lj��u#�����?3iil�!hB*^�D�����^�ts6qPsN��O�MP�A������������l��]~4��syD�p�~���a�/C�
��f��[E
-����U��X��q���A���<b�����0����&���S���
����%\�������Z��y���F��7�9w��J���[4W9/1	@����z��S`MO��|=�X3*$>�^�W9��\5U��bV������N�[����O����sd�-�W?:y�=�R����|���Y���eH�q6����*,��?�M��~9�����-���)���+�����~��c,�?E������b���m���4��]L.su�F��8������;�x��0��d��N��e�5S�g���{9'7~��"9�I��G2.F���=�	?sLUJ�A��L>����D�������8dvT8KB$���0�`�8J��73
R�a�jv�4�(Xl]��^��2�b�M��/���<�(�Y��{�������{�=*~AsU�$JQp|���~�������oXL9�&f��X��z�����pG��D,IuA��0F�v(6$E�K����W,X���k��p4 0�����'�X��X�qRX��l�N�u��[Z���t8UZ�@Z�Dr��?a��?�2���q��Q	v����#1��c	�����"$�	����a04�����G���y��q��1����>�=�}v�&��gv��%9���}��#�o�E�N:W��r���"U�D������8�dp)>��S�X��'������(�?�����\m����t#�xkkw����G���I�Y"�B4q�J� "A���\!��XN'��R����0�#���z��������\I�V�x�x�_Tx�����t�a��� :�J0|n���q�I�sV@:=;��y�>�8>�H��p\���%���s����[V6n�6)`)���+3n�'�����J����YFE�8
E*�^.Fxx��`=���f��G�W��"wbp��kq	{��^���]��W�`��D<
g��a�����A��Q���������L����b���u�������83!�ru�eB�i]��_�h�f�5�G�� �j������~PG�����D��������P������K�Q)�	�1/���n\�6G�av���nY����b/��u���#X��o����_���-��|������Y�(x�J{[�TT
U���q����wG>.�Pe����m�j����l(M��`x�Mfl!�9�J����g�s�X-I�a����-�`��������?�~Z���\�^�GY�WyI�H�E�W�@�{bU%(y�V�@6�+�h����@z
��5~��^tnNG��td@3����r�I��,��!�t�2vX��4{�	tCz��JI>e	>C
�u��N��wu2\E��=�
�&�3)��)��M3�3N�C���y�:�X���c�\������*^�X9T:S�8���91���1��%H��sG�SZ���U�����N����6(���������XS��2�����I.[L��a�6K;]x��r�Vi�����D����e��c+�����+R]=Y3&E��gCZR;\lq?f���ur�2���a�Zt����� #H�	HoQ�7�����LwI������#,3��"������U��;]��	\,��:���<�g��GR0�+���I7�"���8���g^����+�|w&�*����^;�$������K�hx���6�!Ff������@�>'I]���)�q,����q��\�7sg�!L��Ph
�,6A2�R`b0��F�g�MC�����!�{����\��"�F�m����/g#�6���`�b7�[��
���-��5��o��d�s�l���kO,�lw��*QQz-�����|�B���>���i_�yC��NUj^+����������|?��&�:~;��dl�J����m X������I�1`'_s��B?���!���c��K���uXa@PM*��#x�!Dp��gy�T�^PZ�PrD-�2���J�ps����@CX���9d.�:2&���A���1��z���{���"�s:��|h�S����]2�l�O�e\� I\M4�[�����2vYG��Kfp�M�:�V�Q�J�a<����%���������<�^�h�<*��_�SBO�z��g!�q�.��r�_*B��{�<�����U�����#m��L���Q���g$��4�@d�W�p�-K�y��5O��N�7����B5���]����T+�@>�����#��ba�E3>m*.�HhA���!��f�0gO0y$;e]�����:�2��^4���$'d�\�.(���W5�CSM������z4���3P�W���dq,M��C���8=8�1�G�{$s���@4$D�5��p"H�!,�D�{��`��;Sa\��+�81AD��w&����3�kK1.�`9�������1�h���z��ds�����yEd?���sX����igq��y�d�3������O�tc�
T>��/����_��`�{�MP&�{iK����}�El�l�����ssY#"r�������]# ��H���8rB�P�E�^�qNiqE�eI�WQA�z2*)Z��i6N��`�uw9����K�.�)��n�Y1#:�V!{[�p�l�8������>�I���$bDcy(�BA5JF�N�E��i&��<�	��qd�u�����8�*���[�x�����R~��2WsH#!��vj|L�����Y�"}k���+^:�(�]%!�D�IY��QS�l�^���q�=0P��$���!r�@�����H�Z='��(�����:������*�V�')ZT@���+�������l �����u�,����<�o�Z&l0��L�z#r��!�����Dsy9[��s�����Z���P�K3P���_��v"$�|���@)yH2���@q��e��`�Y��j�����2Ru$k�
��e��&�`�,��$��y�n��{�V6��VXb�62��Vn��a�D��#CD	eq=m���5��=O$w3�A�M�U�����
�E9n*�@(<	�M1
N��@V�MKC�u��!��2|�|����-g�D� ��Kl�����96Hd�������������y��2��DY��06U��F.��0���	x����(����U�&������UB����.��?"�.t5/c� C��#�.q?c���5�MX�n-s4(���q6����-���H)wo$`4e��Z���T�'��p�U$[$����cy��.fT��7���_�Ul���d�nbh���j+r����n���fd�?��0+Y�������z%�-�������	xW�����z�W9�k�v������������(�����rB��?�H	�pM�69Ql�Tco10.�}�T�Bku+�#w���{h�ai�?*2
@����x��J�������P���\9���+cs�W`D�:}%8�F2+fj��%e$}����
����s�\x��w@������f��A~�D���-��34�<����9���`��{�-��A�
X�+w	����`��-���Fu5���g��[�H���PX�OE:�'���2����<���K���=���`3��4���$����X�y�+�~����e��U�$q@S��S�I�Xo�KRA����p�-,�J|?�{�
����)��+e	���	u�.�H �����g�P��T�P�k��Z|�����8����(
+�����	Q���F�u�@*�x���EbXo�`	���H9��b^��w���dhe�*t)AXZCt:%W 1P��������^��8��\)�v���a]�X�*U��dzc[�2�vn�M�J*�|A	g�NQ�V'�Oh�|�����.KHl�*�P�5<��	������mDazOn\�.��,��E�3����q�u�������.I�yX$�A��sC�L��/��3����-UhxZom5�o�X")L1`hui?��$�����[J��,�����[
�[F�rwD������u��K�V��J*"�6�C>W
�������v�)7������PJ;1W������\���S���Se^A�]�7������Oo�&��b�?I������3mL�=��My,�(|�����
uh^{��M):�n.��ES�QbK�%�H�v9�x����@�'�:�;���{��	��no��~�$��VN6w�fQ6��
v����9�Z�4Ko���.�6�����Z0Sm@&���cMa:��ay)�5gxF�U(8���2^��D���8�/���"�����,s�		��(]`+B����
��p�
M��[����D���Ks�
�M���
�$�7���
�OF_sLI1�'+���b?���V���Kc|l$ A���?G>CW	�.���w��
�n�i��${`��FM�
'H����H(�t��=X�'pq�\c��r����j�X�V"�����|�#a��cn���{o$��6�x�%��h�t���v����9����j�h?6x�?��~�Z�6�2�7�����&�A��DNHcrf���jx���1��.lo�_Pr���m�	%���������	z-!g��U_���c<��F������=�\D7�l��r4
�7I���A�N�"n8�
�%���kb���u u�.���n�R�k�������d{���.�8�E�����pQzF��1!�����SBZJ{T?��x4�T���0�b�
m/���
:Q0����b.}������t)��a�m��	^���7lTs_�H�>+���q$&�C��h��bx����Ig�K��4V�gW]�0����T�{i���|i,q������H@��2�J�IG[����M�z*��#>JU�����$f���������pf�&��2Q$d�"��n��nWn����&DZ[U6��S#��l���H��0[�85����������[�
TX�5EF���M��������&�OiC�R�#�!�]\u��3��F��Rku�A��)�@�C(���$b2=nl�k���SU��B~��IQ�^� �Rnp<8���\��w�/��O`��J���+�N#����P]�:��a ������Z�s��G�|��>�	pd>EB��6
Y���V2,�c��V|�D��%Q�������^��Mkw�~&Do����D� �y^�ge�'�P�}��W��Yoq{6���=�($$�b&p��s��^���%ch�Z�~��8Q(t�(��Q�}���`�)��8�u�g�eO)�������*�2k6��M�e�Ye^w0b�0�J���C������-�m$xfT��|��:�,�i��$���LK�A�E=��#p?
c��+�7�k\�Q������l).Y�/�-��v��s�^m��h��;-�-�
�����.���FKC]�R�gY_FG�_e%�t�	�R��
McD$a��f�*K��^g�B��B.��_��@*!gCB{d��NPh����xGZ��{G�`P�n�����E���j�n�vC�2�8�b�#�Hp����LsIWx=�1gSD=���K
�: l��(���+���C�sCnT�����8N������f!�~��"I�6D����N>
�������Q������7�o57�Mv��
��N��}�����tw�<��q�[9���I_��qG,8Yk�P���q f8���1[W���c����FZ�tMK�z���y����#�_��O�	S�`��+�X���
�p8����j�j�s{f�|n�1�7�q�����i?O�pUky]��b�s�<���H���������� R��+�3�`��a���k�
�O����� A8��-�!x!�V���#~QPu�����5���y�C������r����pj�����;�&��~5�{G'���g>������=4G�w���P�'d��T0���G�c�fEg��1���L��e���9r��cB�1����o4d����(��-����@�:VU�*������gI�O��Q���<�*��]g��p��������Y�
����a�o"���^vM����5�WJ��Vm�<�������v�������*~��O��>�e���^��M�aem���:����D�o�}A�Y�5�M��-(�f2�����A�o�R�^��F�
g�b��`���3�2r �fN� f�[����-�+!�F�X)KZD6SA��.���������8���&e�&
��f!�{�M9G��>8E����E�CBZ�r�i&��Q��s%x�f<��"x��Z���y(r���b��V��H�$F�4��v,L���
�.z���]N!��nx��������C�����R ����nA���.���N����������T%����h�@K!�����}}0����+�,|��bME�U��U����������Q��������1�4�f���t�;`LK7#c����4�����<N��"c�E�T�K�S�<:.q]�������j��(����IaU1�!:2"�(���{Gn�C��*��8V�{�����9�J�=���3������m������=K.��v�k����j��v"��@RU�p��`���RLn�[i'*L2�����
�)��	��e]E-�w�g�#q��������3C�L��<�;6"R��)�����PI��k�������. ��(c�i�oX-�~���12����M6����������z�K���W1��5������3L�L�t�O�����10M�h��M�6��?���d�U����c��"����+��������&|�--�����HFB;�3��X��Z��+"�����[6��3�w%����aI��@���
��g�R��^_�Dhr�'h��n@BN���tec�
�{h�o�\r%�}�f��T�o8�~H����/l�#����[k�d���BfVPrE����L�� �[��g���7����d�# ##&���u-G�M)��0���DY�p�9]%���f\�0L})r���Z�{����cE8;v`<Y��h�6�������$a7�2����`?�(�	����?M;��z�A�4�!L���o���;Kz	��d7OTZ/��L�����{����� ��f@ug����g���\r>�R]E�%1���h��"�3p'F�>!�s5)��<Rg�(��.v)
��U���L�p�cU������w�"1�D���7Ab(t�T�&b,�7��;Q��K�����yZ���e;�@�]�I�f����t�. �M
�k��aj���A����	(���]*��UX,��Y����|��������p��Q&B��S���TH�c���(���Q1���o6�N���`�g�v��8�������*��L9�{2R��*X6��O����+�88�WY�Q��%V~/G9H�5L�w�Pl����768UX/.���L^�s��t�
#�t�����gG3��	������5��� ���|�6��pO�~������rh<�fr�~�&GN��^)K��0��	J���!���b/U+��D
�A�^�d��v��f�#�Ph([�(�p6��_���`n��J"�o���J��RR��*8��\��Kv9�����p��|��8xQ3Y�eZr�c>�6�TD	��% ���M;	$+2��7qd��(�M���xA�t������+a=������$�r�*2�IF�M*AM*��p��rw�cd����0B�el�~vL�SJ��7X\������r)j���t���1�k��4��^��
Fu$��	+O�`D��iX�p$��3r����*�u����U�"%:�oD������Y�$�t22�X��G������"��"[����!�����l���A�+�TB"-�\�M��I}�7Q���o�S�`�a�J0��|L*pw�$����zX������3�Y2$�����L�D�!t�M���8v��P�d�Ya�-����F��Pk���.i^�]^�),��o[�\�Q�K\���g�DT�.�lD��^_e�c\Q6��c�5	���5o
aP��w�-���p)&�?���j�z\B������	L7^Ut��
����#=�Ro�.a��c�7���v�18�R=���i�/7�g]��hsP�]��YX�>��3'� R������G���u�*��/���7x#p+!����@w��M$�_�*�8�6(�UxV0���L!h^�����tG�u?�r:�%B)�0�/J�+&xTs�E�q��\�R$�v�z�[��oE����f����l}1����e�A��"��N"���+�)���E]~��wZQ�_>�B�G���E�QIH�C��
�nO�������1��K��Y�@�B<�	����l�e;'��y���t,K�������wf>6�[��w����C��C�Yp��h�E��[r���c�C4X����Gp����mk����k((��������	��2�I��)��'6viQ@A��=MTbp@��q�i
�;�kp�����s�}J1~��_�/_Oc�0�
$=��1tn6���{-���23�{s�����x~��f�
�e��:����{�VR�G��;I����f���=-0�@�%AP�XZ��I�&�a��*W!���P�"^C+���9+UQ�*Z��V�����L���h��<�Fb6s�N�������7e��n&�~-Y�d8��i�_��]��'��"8�M����oQ�|E�7�pa Hf�sI������`D��cP|��!��
��K��p�?��/!H@��#.��,^5s��K�h�}5Q����^	�g���������l�����5d�����s=A`�~L�@a�lLG>}������I���s��js���j���
��}��-�$IJ�q�}�O�Vre5��������ar�MI6���� �x����5�$�.fC'��u����6���-8,q!�P��io~h}'~�/�U����@'kv�%j.)������h�T�����W����{hS`�Nx����}�Md0uh�5�����U��������h6���Z���Q������c���:��]�/g�m~��D^:���y���<�9��:��7	P�(A�R��f��q-s����a���?Ur���!I��8����r�lP�o8������S��b����P�zZ�w�W!Z�|��!��sZoZk:��K}�{S���`���7�[�����E��b�x�R1rd[�9�yvy2��}��lHX}�,B��5L<������}��x/u���1L�N���(>���k[��=��g�Z/\E�G�����B��:����>q6�Fc���S�Jt�������h��H�{3��+whj�>`����@�.k9��-;�s0g�i�����O%����(7ws��?��EeH���R���!q7�����x:����)���.�����W�������h�#B�mJ(�<&'��~P4�P$�?A_q`Y�qsu	(#��G�b��
��-1�<>1AD�������w,�>�j1�~���8��K��T�G��?���n�0�����3���2��`?�#|�p���9��1+os��-������$?����
�GJ�	�B>
��Ifh�G�E�qG��i��������.����_�NO���~������~������d��?���[Gg���~�~����V$_�MD�ML8�K-�L��L����G{���TM�e��B�%������C������0p����me�j���)������{���+A����Q}4z)�@�_Ne^��c����[]:����7�*�����k����;��6����]G�9s�LD�A[��8ZG�{ �}�q�����.M�%%`pw�����e�?���>���K�x
]��`1���[f;��������?��5=B����l����gC������~�_���������Ft�EQ�����C0y�I�K�W4�-�Q[n��M�����-`U-��m��p��Z�o6��p���2\8x�^�]�#�i��(^g>D�!?5�u�
��&��!�&�y�#��B�����4^Sb��]l��:W���$�"4�<���"d���5)�4�p��^y%�+�BJ?F�D4�����y7��XC��4pCU�$x������0�xu��
&�Ry5:�Z5�{��������D�s�Y��:iQ����Uh�.���DY������|�!��QA.�C����C^I`�MK���43}��''=|;/AA���L���z�o9*=�v���B�����.|������F��W�	B���T�������@�J�#�(.T#J"
��Fx(�f|���]�-�*7�/�7#���D�@��!����WjKk�J�NaqX"2������+X�_=�I��Mq�o)�B����-2���"�s����rlx��u���'�@�{�r���G�zQ�|�V8�Z�k9'Hp~-FXh��U��j�I	�m�	�$��F��$��V�I�&I��b������Z
��i$�0����R�)�������n/��l�G�3��(O=�������Y�NU���Xu%7���,~��F0�eY.���:s��O�
�#�*kz��j�,w�-���"�h��59m��5��PI�P�O��@�p�1����\xD��qt�0�P���b��c����7���/��z*�|��������K�H��)c�R/���O�[*�A��&����f"���)��CM��`]����$�PlC�$(N���aW�0iu,	�b����n�Q(D-5�>��q9=+�a���[�T�
h+$-��LFr���PW���V��h�)Yw�� 1��5b���#������}�lsh�4��S9�)�
;h���;�~d�������"��d����,�Z���{�q-:1��	��y���G�_��W�������k+N��0Ja��/
e���,W��K����?e5l<�{N]��p��
�KQ�t29���v��Yv��O�_��=��*���w4[���P�M���K`�8��1IR���!��{��9��v&��<a3����� K1k�]:}����"c�dA;/�-u��|y�}x��j�C�r�5(��e�)��B}��#���/&r56V��m������O��~���#4�o����5��
[`�B	�s���w�7���s���R�`+}�m�{n�6�}l�6�~���MX[��ui��z�f)4l|����\X
yN1d~����,�lZka�
���c�1��C���dG�RR9�����;o���*K"�lf�i���W-�����X��X�<B���=�
D���*���0��3
�0Km�V�M�����A��Y��xC�)�"3U'�:��R�����dU�����9N��k>,��.%���w��lk�'��o���&e��?��?�xJ��w��<��������	������F�B�oH��
��eJ���~�D�iPc5��i�,FU��v���F���`)���t;)�L8�B#����<��&�����;����
�%x�SM��s������1!gf�&�j������� �i�c|h�&n���8'\���Q��|��wJk�����3�����U����>����3��rd��U<$��#����$�� ��\Jc��g_K�R���NG>�����E�gF��n
��x����N:��3 �R1��y�N������j����L���M
R�����(7�����A8�td��),8e�p�p��0:�A�W��k��H2�|��A�K��;���
	�r��D4���\N'�<�Z��rr�����"�)�%Z?Z\�I0�:�]d�>��������+��{���s���|�D_4^��%4� �l�DoJ�z&z6+Gq�X$g�$��9�6��O��D(7W+�;�./���gX���P���/�m��|R/�/�_54`L>������2�^	�N����b��*��y�O!0UH�����x�H�o�������%�Ly�����z�e�Q+cv&���"�$f�Nn�b���a�TRyE����������5�elu����H�#�F���mX���>J���=�o���������2-PF��g{(qf�)]2M/i��w��%�h��~������;qu�L=Vg&l	5Ip%[���������N�/�NO���S�m>_�I���T��M��e����eW�?/����}������Dwt�0��`�fag�\+���%I�-�w��S��)�b���F�(�0B�}#@p��$b\��"��m��YiM���~B&�����!<�S��]6��'~�@.kLOs-,��"����9^���?�~
9���>��������O��
7�Q���/3�]P?�6F1�m7�� �p����xO>�5o��:�;��_�];K�>DQ9t2XZ���#[d��s.��l�����@�J�����	���T�n�=�@ef&�����]����p6hI�OM���)��]G�;���'�Y'c�)�-�IX�������QX_b�z���*�H1^b��:����3����m�:X�
	<����Pl16��2�]G�CW�e�����r�\���d�dy2�Bj��D$`y��o/u��E������X�{����]\����+���������s�!af�������d?xpv�_���������]�������������������QwDq������u�<�
�x�sU�<f��~�!��3��tq��9^rZ���J�����]�%[�s
#�J�&��T���}��	�����y�y>��0T.�e5jzmx1W6����!\�M����~L.��"��/{��>}pj�����=�b� ��X����H1�3F��e��`2�0���������������K"]@wC8��1�� (����Xi�|�!���q���^������w��K�c��#A'�z��G������)b��o�]3�����<3��a���!=Yj�x��eW���t�.i`�>r����_BHC�_��i{���%	�+�N��O�����^i�a�.'�.��8�M�tf��S%��~h�&�Q������c2Y�@"�����e[�F���Y�=�f�kMNY��d�w��������O���3�~��=�laoy����o1B�K����Q�v�����]�#�������IzM��bz��Z��Y�g ��is�x�gT�A��Vg�#k�Y��&�1K���S�69�K�KE[<���Ha#OLt�CTyr^v#�mt���F��
E��?����:Z� ��\�6L/0�y
��;����2��5�����������XW�Tp�L]2�T=��]��4�+���f��Z�!�&���������l���wG��.Yb=G�g�;CM�i����Z��m��^��^�>��+��iCgR
����Y��WL��	0�b���\B�[F�s�8o�M8�T���d#���������2����/\5������V�
/9:;�7��B9V��0�u��U��t�Yib�����>|=�S
Ps������K�I����Y>UsU�ucs�+!G6aBS��Z%5K��y���7�H�sU�)&oY�����bFE�����]����0�;$nZ���W���K{V
;I�-��}W�dD��o,�����i��x��h��K�^^;�� �|��qD��'�V�80T��5G�4�	Vk�������sPX��
g;��z���[�F�L9X
S���h���9���W�k��k��qS~V�^���;Ki�%5�J9�����su,"��#���c�*�1�1Ca{v�!��u��f�h{r�!��8%��� r����(�\��Y�����+��e���b�	=H,��HI�sS��g�W�^Y���I�R	�bQ2B/�o��1�)I�s�/�]>�7Fm<����	���1'��o���-|W���\.��k��]�nH��1�M:Y��������n/���R�{�m�=,W�B!������y���+ykc���Cf%ke�L�F&`������9���W����OO
���V��R�b������k�����7\��l��G��b���yr�/a���oEkah�u�������p�|z�9�$`��\�&vx��3o��v����Q�a�3�3�\�J�����N��[�y��b�q�p�e���
M�`��	dI��(Zi�^;���bcK=Or��R��/y���~>5�t�4~�+U	�K��F_�v�J�T<�1�!��`����(y����{�zJ���-2�c	(
�-��"ZB�GI��g�����%{ra�_Fm�w���R�zX�}z5��kTuI-k��ZA��C��#c"E���]��T�I������x)�*�9;��4����>��D8*������+xv���u������G�s�561���S.LaD�HS��P�=)s�� ����p�.���������AY��a{��
��vZqgd���N���}4��y<���.�Mw���zR���CP5+1�n��mP�C�d�4D��s�~��XL�Xq����M�`0\:Y,F���-u������l�AB}�i�ujL9wZRX�j>�C��1w�y�A+���P�Z��^��������'1y�1�y7���}��0^��a��� �26UhH�i�d�������X\llY��R��f �)�[A��q�����fa�:Vl���Y��w0���Q�h�f=���������{_/a��*�dm��Aq~\���N���7�GON/Z�@������[y���b�
;���n��#��|)�B����P�p{^A����O�}���z�1�a�������/:$�;�m�1;���7�����n����+[�;������o@<�B��������O�������v)_�G�Z�;[�N�No�O'����!HD��,��r�����knQ���[,>`	R$�C��N!�v����a���SO��~���� QD�u�1�!��Qu#9�k��d���F�0�s%4_���%�����?�Tkp@�3�I98���Z(��c{�:�{.vL�]���ZK����a�zM���rb����]�w����h��Vh�M4lN�wTt��f}���i�k5��Cqm]UCv�S�I������3.�$�*�P 
�x����D��@���n`sD���X����e(�� +s��O������V!���2gfn�`MJ�mi��5���������=�n��_��%_����k���#��V;�����"p����Y�p�}��|�������>��z}����X!/����\3���U���}0n��R��H�lXd����H�q������JI�T7g���TQ�0k^6�_:��(&�����!���Y������*�SXZ���]>��IJ�aMR�����o��@��?�OFRY�7p:]����M���d��,��������
�������k[�������u���h'��&��&�>D�XT��$�DU���$��������t���6r���]�6���R�u6	Hf�*e�s��X^4��j�����d4��5�d%D�"E�[�,���F�U�b� H�zt=`��-���X������*����������>���yT��v+k�y��[�n�5�J���[�����U*-�������n�`����5�M2_e���	�u��)V#��F�s�(�����':r�<^,����,VsEB���.�c�1�/�������d8��j��AV ��@��(���&�����K���yh���0�����[���H$Wg6��YO)��f�D�<C���VK��i��Z4�]�#�}��l�{�������^h�vl���1�f��]�����#����s�VI|��_��o�(m��r��9&�d�B���V�����K��M;��Y�� �����^����wG�{����_��.[oO�>�]X��@�����z�K���ki�����D�{I���4pg�D��&���Gk"�Z\��FI��a�8�z��O��PSe��5�B�p5Hw�����x�8P��j�b�i���-v�g��;��s�y���
���\a�;
,������������{���}-��'e�y����k�1�#]"<��	��:<��7���z��S�'�y�����"xV8v��2@����M�i�g�������d�di���a�`l���t�;�����+~�W�����g�p��a����@��
�?���"Nx�<}����'��+��,X~��Iy��S���Pd��5��a��R~}��D8�����X	�6�
��f��B?����61��l= ��l�������&�S~V�bX�����	�0rV�B�'
�\#��z�c��\Tn�J��������[���/*8�DR���/M�Mr4	\`�M��������T�XVk������v4#7��.����6����O��-����2����/���a�<�����~��n��:��L�8>?�A%x*^O���fC��&��-����5�NZ�(.r��N$���K/k���X�W7��"�d���@���kg�A��=>���pO(}�;:A���'�>�Z�
R��I&�T\IT���U����L��g���Z�����5���\����n������!�kW�KN~�����4������.E�s!u� ���Y����	����c{f@�����@�����;J��B�&�E	9�%�L%!�
�JN�(�i3�=���Uw���I����s-�����}����aV+�LM��20�q���HQ�T>0�s'/���?r�����b� nA��Z��AZ�����z7��rs��{���tc &2�'���\�q�Hdiv��*���>����5������O��^��d��k6��O^v_��777�����c��[���X�]�����Vc+��nl�|�2�����z��zt�)���t4�MR���z�tB�(�)����c"��
��D>
y�x����w��z��x�QC����t�RLo����C������	=9�8<�aF�f"��Il�G����IX0�'t:b
5�d �o�%�,��,vH�	�*��Mr�����F*�u&��P;C�Q�J�)F[�PT\����$~����]K��WZ*�Z������8�e6$L������w��3�8�����������),A��'js����-x��2#[����j���,�6C�������
G@�[&�LjE���.q2�#N��M�rF��Zq[�L�7�����b�N������1���xI�Q<�ik����DIS�9�4��>�B�i��������C1���#p#!D8�19��N�]��lB�:&��da��i����tUbx�eK���K[�����#3�(�����-WT9{@�����1����x����B�c&/���I����0�Eb�x���1�X����J����ap*;0��.!���4[��yuy���
NE7h�����P��U��p4����/��	�-d��/��8_6�d<\wm9dV��1�8a�X�$�'�T~��L�i�Y�e}��!"�G$m�m���,��Qd��y���n;"�69P���
�s��������9:|6����	@�?�!��%6 �d4D"�l��n}"l�V��H�{zB�6�'�H}��]���)���-ig�k���z�;ywh����X`���F��T�f\(��*s�x2���'7@�|�E2c�=���`;V�����0�����e8�RZ���mF�����?U{�&Tp#�Wc�a=�An[����N,��31�n0�/��:,ZFx;yQ	�
$��Q��|8}"�wt��
_�N�,�{z�ust�b�>�<H&�Nt��'lPZ�2�D�Vp)!�{��/���X&f��U�l�5y���+�����<�X��^���i0�r���6{M��7�s��(8z_�N���+�\�I�����c�*�8���]LA�$a�PA����[�j`Yj��j�I'Rg�,�P�BI���"Rx1RAY��8�n��mnP��>����MF��R�o�����h��F"��s�u��E�����F���,��LGP0-��ujx��}�9k�kQV�Jl/��6@���b!�2��0EQ���Ij��4�w
|�s�F��@�:�G�\4��������G]=50��3��i;����Fo��9���cDu��aZc2X��o��lO;��3<I�� i������)���(J���6���[��������x:(	�+�8�
��c��~�r����e�g������+RN�o�R��v��7D�����C��.L�o��~[�{�������U������� �s�������}]��eW������o?��.�|�w�S���_�"�;M�$kh�C�&#w{��c:��"���b�=���G :|��X	K��p}�<u�w��}����=�?;[�zr~t~qx������<Y�.��S�}X>[��9
q�f�+f���M��m�����.�(����@�X����-��%(��3��>��[LP�J	9\3�X�:�H���oI�#(R�%�����$b������y��#���:����h�{�:'��"M���Kz���O�r�Z�,{�mGEkN�h#t�$W�J2��J��lT����	D&�.�d�[6`Wt��4A��G����@d�%�����`�$lg��S��K���c�4%�6�J�H������Q��A0m��OY��E�%�un�����b5(9�����a���<�&�geC�
�bR63��M%������YV �,�0w��aZ*�J$�H������Q����r �J�kd@�JC�@2F������gM�2�#��=b)�CE@�3N������N=�������6���b
��'���6<x�z4&��H�c��`�����!��s�L��t%�[�?�]�o��%��<��yu������x�d���9�������I�.}�v?��N����%��l�n��LLMJ
�
�_"7,�q0O�-|�������}�/���d2��E�	j&����|��\���������P-��1yT�[�/����KV����L��H�����_�����E�T|_�Q���X�RD��K.�3K���IW/
�an�f�&C�9F��t��&:�T6�����y47!+)�^�;q<k54�Y	���}*���JA���]8�v�jt
����i�A��W��\��
��Y���tvN+A�a\��I���QhJeuo���t-bM~���Bg�n��4� /��r3r�Ax8{=+�����).�lh��ho�!u\�#���{SFT�]>����^s����E(���PX9q�1|<^bd�l�A���
��2����-�B����;�O��Xu��"� 6����	3����������$au)��pB�]�
e�������d#��������[�������s�F H�X�&>�Jtyi<!S�O���*
]c��@�	<��x�d�rd#�Zb�&>��Z�\�=co��K����3���&C�����`�O�eG%�Un���JO���]��hyO��l�J�( �Dr;����5���Q���682��M>n���a-dC�d�>���T���}dA�,1csn��V�:r
#Q_o����t��n�����������f����}>:@^h>�������F�����d��\�s+�;U����A
R�2����MVu�cc8�	�XWQ�*Z��H�,��	�i�8RX|46*L��w�j-	A��&Q?�c�3?��:�!��T
��Q6�A�G�"��)T��2{��U���rU����f��������������F?�S�k!!7�K2���I��}-����z��P��f�Ql��R�f�Y,RXX9ke�
%�*$�)��&��D���d��*��:A��K�vr�b{�E��>��<a�+t%���<�i=b�)9����%ix3�����2����q
�} �tA�"@g�
�c�8=8�19�KD�~2�e�TgTLj0#��$�6�C����c�^��.g^q�{�N�a��9m2�?�	.R>�*���c�����qq�P��� ��PEN#XW���"FK�l]C���,Tt5Q"���9�t�?���@������K�RH�l#f�9hQ�4��+�������j�K�N���E���u��s��xWD�60G�1�Op%>gt��Y�2��<�Y��;�]Q��3��n\d�m�S���&�h�>bw�!g�bIA�������^��c?���;����T��}Vi:v/n�5�w��vgd������2P�:�����^$������3~$��y��<��e�?"���C����K:�c�%��i�Z]#����:)�2��l0i�����y9v�������;��f'��>s��3�I���
II��U���tv�����5��I.�J
z��
#i�� ���v�E�X�������RD'"���^M������%>�fN���8j��@~m����Q���Y 7p���
e	J�����RS�1�����D�7t��ox�%xN�����et��i������TY`�6����l�k`�?p�a��)oa��x��:��D���g�����gS�>��g�7B����p���^������}�u>8|������������9:9�X����gE�_�j�_�E�\�b������/��I������p��|+4E?���f���'�E�P�M
�]B�Y�����T���D�p� ����fX�5�#�h{�%�w����4%ZK��\��u���Q��^1�J��I��'
*f�Q�1��l�����v��'�	"���!��l��v/oeuad�����m�����|jVC�t1��N�XK�*�y�$�a��=a�Q8�I��*J�r�P�G[>���j���{F�'�<i��}B�ae�:�uwYLy����M2
��8�)����O�K�Z���(T�2���O��=����-��-��;'$�?��4u�_���s�#��8F�b���G]Gw�	"����p����@1��^EA�����Qx�(���i5�.�-�.��U��d=@���K�$�;���G�|�S��fJ���eB�q.��|��v�C����h%?�
����t~g���z��e�]�=�Y��+i)���S(c���[�������N.�`Pb��~�r����'����C'$E��Y�f���L�9���I���?\��Ns8i]��@[s0�
wLC��6�����������l�#a�z~��a >h����`�zIB.9�����x]��I�"�%�0o	,����2�8�� I�.����Q�3f��[Z��H<��S��:q�\��K���"�d0�+����[���������x�p�]����]���&��`���=���Y��x�I_���rB��I�*e���u4�TO`���)��uv��������W��O~��N�wt�c�8�b8�F>$�M�K�����r_����A#E�x,5���s1]?�|��<��6����������h�?������"%�M_q���kkqe%y�����3��mt�Xd4�<z�X����s�P�_�k�F'�)���{�i)������B�zMf���U�K�EQ�?��"�2��]��1"��pb���N�	��:�#�&"�DD��*�{��R� �W�]�<�k�LLkBi��)�������k���n<�<`���B�GL�:O�Z������aVw�H��������X����/r�f?�-��w�����%H�;���8��y��r�G�Z"&�UC��&H�:�)�����C"4tb�_�I��`��9�[`
bl�����A(�r���ZzK
�T�c���s2l]�����/�R/@���{|�
�H����(�TPw�	��*"��%�iHW��]Q���z����c����!+�T��FR���$���>��cr02�cJ�n�����W����a�hl���@k�	� [V���J7��7�G�a�����!�x�X��NQ9�?`\.��-{�}��y�����G��Vc���}x#z�������Z��R���d���}���c
\�k��Xs ���$���a��a���K
�"�1�"o�!��j,|[8O����<���H~��~eT��_�
d5�>�-��C��_:�un��/��X��/�p�.~�$e[��$�8�
K�'�L����\��<�����bpdDWf?,��R�D��U�
X[�vD����"�8�;9�����������hb��2e
��$ZZ�%}A2�9�c�!���������k�oE�!b�)���Y�w���5P%N��Y�|L�e�*	�E[�YPsJ��T�O����=g���&r���-��h��s������C%B�=�K?,i�����p����oM'����u���Jm��%`d~a#�CD/q���V��,?
�i+][(F�"G[������my�L&�>�?����������h)�;|��#A����7�.�Q�b�O�?9������u���/�}��-�>�r��;b1��l���#�{M��#QH��8E_9K#���2S��w�9��<Up-�l����8���#�d�������UG�������g�������{{o�����]i����1�����q�1< ��h�a-���U�29y�LHDW������dx�Q�-38������>����494�����!�
A����(U�	<KV���3�r ��1�G
��P1����Ve��%����RFY��������,��x4��������1���\4��H�.�bY�+�p�N���[�E��{�#�R�qb��}���oR56��<?7q<��uv�����X��W�����A�������(-��s��q���Yac��9B3(h���N�"S��|J/�5�V�
����"�������.�����*�)v-;������WzC�������u��Q���
�P��,�EzfX�=h�c��&1~��N��Q�^e�F>���)1|x�WE�K�q!7�e�V���)������%t���8X��$���
������;�5S�L��X.fx?Je'������-�\���V�\/b�+�S�g\������SBC�^��L�0���5!<�)K�	����*e����r�S�V+�2��k�e5����
���h�8E���t?I��}^�DM�<��=�1��������(4��2j���i��&d��"yMa��I���1������2�������v)�=c��xzzG�D�,#U��H�i����F7#��'�����Dr�yV���A
�"0�0��=o��an�N"q�|�R��R�*�(E��E�j����'�Wl6��
����zbK�s��6���+��b��8��B�S��	��_v2(��ZhB]����+�,����b	z��'b��"yl��X)�����Q�������k��@=��C^(��S$�z	�4��M�T-�)�f�1��A
�������l+��a�5{<�E�)[�d�<��c_;*@<�3�shH��m�>�L��o�%��n���i�q�g�i
���bN	��r"���x3���5�G"�w%�(��H9R���0d.q+��V�RD�{ ��cw���e���:�x�>e������M�v�v����?�l��;�;#��X����2BV:2�	x����]'����Y����M�$o1"��T)�	��9���v~[LAk�uQ!��}��$yw�����|o:�n�0#�p���q
?��(�/A�����I�b���6�XP�[�Ofi������:��0|&d
���E[T�-��������jU����.�?OG�V����T(���)���j����4�7�6j��^~��;dg��$��[������|�8/��"�����jUc�sf�,���2�C|���_(�.�a��r>@�K:����
;�$��A7��T�!L��n�-�n7K�E�v��h���g�\�%��u/��p�0�f6�f��P��������p)���.��W0�/�mw'���������{+�})�(��:3��*�)�O^��0��w��dVo��n+��]��U��.C���
���g9b�zK�fb����a�V14=m�
�mS�B�
U�~�f���C\��%#�W�d�_;"�/%���V~�i�p�E�41��b�a?�8?�%1�`A|��D��2�}�1�Kb�j*&q�}��
f���Q����
Q�3�R%GxC��+���l?p�����Cw�o�u�b��fk���O)H��Y�&��5�����m������y���K��@J��Mo��|7d��O�G�U��M	�f8!��HB��� %c���z$��a����������v�-LJB1ZW����+M;H�c\6e�%)�N��x��j�����E��[�MF�MO��){����	��59��TXC���D�7�p���3M�cBc4���G�)+w��mfI�f��9�@�(�#|��@�}���O�� �e������nU�$T5Q�)��n��8y�#���h���D@U)��@�K���Z$�����g�N5n
.(��i!6�T��d���>$E���,DN�oJe�L��&#x*.=#Y��}3t�I�
�n��A�=(�i�.�`�E�&��0�fh�����>�=���Hj\�����$��	��|j�
K�������X����
�=ME��^z7�dK�fI�����[��nMY���;e�Ch������b���/k�$�0%�2����
%-/J��A�D�X8T(����P�����
������*C�
�k='Xqm���^���^eH����
��K�0#�a����]�X_v��Pb`�b��fr�,����8�=����E�6c
;���o"�&d��am^~�_*�����.<��(���Z$����k|��,�LI�~��k������]��0��J�ib�N�KM���W��8i��5H��F?��K������3�gh2t�
��4,f���W�@�(|�&��9�V��#��+�������� )M@|�M�r�	"��)`��?z�J!n3t���Y/�����SLYO�2���(�T�'�5�R3<��X�
�
-��S`+�_v
�k��X��o+d����c��/>U�i��b������P��+#91���/��W0Y����:����nB6�V�!$��xDwI��~��������zq&����+
?�
iC�@��v�q�J%S�����|H%����f�
���1�,xQ������h���1���,��@�������D�����9�x����\d�*�>6��g�[' �,�V	�4xE���^J�|4�e� ����ak��3(:%\$M��M(��u*	JB�����4MeHRO,(���!^���G���~N�\�����h;���j����\�g���TeD>�p���w5�I�D�����	��G��)�����>EC�z����ksA��Q?�V���f�1/��d��%LM�y.���(��n�x�;�&��,z�\;�gUl����Y�����1�����i��P��2\�'�T:���!�<�!�y�_xbU�J�{��{W���t�r�G>�����_��
��L����?�(
��K�H��g�L����\��^��(4�/����N�e+���#�rDu�L���MJ7��Z4����-:�UI��t�����&;�\���<�f&12��mj�NQMX��[�
��Q.c�#,�*/q���E1#�.%��%�f7�RnC������i��0��S�D�.,�P�G����j��.�]Efo�b���l0N�$����t@�/�5wx�t�*<s*)KR��=���O,\&����]�3�b�z��PG��$i�8�{�;58���B����rq�&P���"�E�Qp����:���2v��w���Hv���$9�\N>�;E��,��o�����-�������0}�#��
������_
���������
�P�{	�,3�xo�B���J���OUL
�5�E�*t�"5|�2���~����tM�%*p�J����s�U������R�X�����W�(0�`�x
<_	������a�3]N7����'k�p���]�1�/���%q������J��6�f���G8]��{�8X����6��nc`�`�������hBS	�v$m�V��k�,��*�����p�a�����}�y���]p�"�iu�Qr-S?M��H�S���")�@��H����{j�w�_!���f��1��-WZ��>��P�#H���J���o���0�J�GLJ@A����$9R=�T���-��|�`��q���fE^A�0����ye�S	���(��G��T�#�}V��������p>
��F)1LJ���#�7��"�������5lZ�b���H `E�W��W�g�f8pa����745/Z��]�*��:RK����
$%h��"��"���t�`��\���q�]��W�:��Uc���T#��M�)A��	[y�O0@13'X��9�'�����P���I/\�:���mv�uf��K����+�.����F�����_�����D2��
?�� �\ /LK�q'��,5�������%�\U����{(\��IJ�H��������D-{\xc��6���J�n����i��81�[����$���/���rd�����*8ZI�b��t��}�aR=����x�\$�L����<��1%���
l*[&�OUL�G<�x�|Hw���Lo\CP��sc����%�yT��3��QS���j����>���m�&y|OAh��I���^
�'�O��P���D���6t���	��;?���um<��p��y5I|eBw*�3���0)SW$d
�V~�Z��,�>jr�����t���;����y�l��9�f��f$�v��(��x�h��M���U��Hq�,Qa,�Q��As�7�"�j����Tt�*�9b��k�D���V�J�<t�I�Nq�����%�G��>P#f�_)�p���y8R�	����������"JR%�	)�����+����R=�N$FG�@�B6Q�H���sk<N���xV����p����/���o$<H�����r���,A���bcWx�9�������l@��>y��a��kF	�����p��q��"������c������0����yx��B|���L����V�7��A�[�����.!fr�'om�96�Du�+����a����78(59"�]��S�n�b����E��R���z��\�����xg��E����g����-���l����kJP�$��������������J��L��./���?W���`��=�\�r�]U���vV	�!�}J}��{6�n}^'��3w�u��u��w��=����=	�]6=�Q��E4/[;^��8(:���e���!F�����cC�T8��*�r�k��D�:��_|���$p���IK����9�V���	��?���_���t	� ���7�d49��3B@��AK�::�Tct��4sgS_9�B�����R���^��XTO3M����,x�s��UOh'���t��8��`����������D]r������lK������� �@D&1�`�S�u����"3����*�+�W�����u�>��kfST4+AX��@T��'�r��a�
�)�v���,Er�3H�Gbb�w���:���YT�gS������U��2�ot��K���|0���6��m2�;2�^N�%�yl�2�<��:�
J{�N�i��r�'��"�W���
��&�����E9�VI2��"����m����9{�I��S�y�{:aI\J/��L���W��7���e=�Pj��6�y'��B~u�a9���2��(k���c^a��Euq��C���x:�M>��S�j���5
9g��	^0���h�V����F��e��ZR
�����o�����v[njW)���`���-5B�T�.�Q�6^0}-@Q����C�e�9���_�
��������^^�6+���
"�A�����t�~W�����bz�$VW�"��9�-��(a����L e�%�=&���a���(s
����F�6r�t8u�;�21�o8I?���E�&g���"�:��=	�2�}w:�''� �2\���feyk1w��Jl���_�X�g����f3���f}�=���4��:h����<17+&F���;Gy�bL){Mk�4�99���~9�"�\���jp����%a��k�;S��#����vy��z�V����1�.����)�{�8n����
��(����mp42.=�w�a�U������Z|��3�vr�8O���Nx���y���1�![Q�!��X�K��#��JS0^q5�����"n\L)�2������=��JC�:�!sA���z+@�E!B�/Q���N�J��7#�����h8y3{�PQ^5��Wb������
�?�_����a
�d7���hx�����A�L�kvx��J�����GJ�_�(�
e��Gt��B��������zB0I{����hW���������`�U|��&+X����L{�$�R�e��%G��=�;R�����e�bv�+�E��v>$��x/��L|D�w��VA���c����_����g|�i3��a��(w5�e���u��q�Q�zH�G�C`Z|O{J�7]�*���J^��xa#f5�Z�9�~#�?�]����=Y^��1�/��U!�����S�+So��&��Q wF��+�/F}�x!e�>��y'3h���c�&�.� ��2M�]'IZ"�J�DU/����M�4f��EL�u��Ag4y2
��}����w�<;��k���T f�.��\�D��d��/���f��}���)"���N��$���FT�2��@~0�z������������x��r����>����:7�)����~Y,��e�u	:�`�44y{%����F���;z\���_�����8��*�Uu��$P@��OEp[�F�)6A�1����K��%3=xqJ��v���`{!�K��6~4�����<��������,�����	5�e������f7�g �V��X�7����nn�W�.�z\�l�X������!�t�B\��;�|j����D>�lu&�H��z�Uu�Md4lcM�!��^B
�E7_N0���<�^��
Ds*^��G�xq
�21P]7Td_S�%������
/�W��0�d��z����Y���G���G(l}��H�����eX
8�_�:�@2�J�NC#��+�:M�eg��/���F���j>��;�O�n�m�mnmm���rxv~tz�l;G�����Q�a����K���gc}U��fy��=G*�MN��R��.�X����D�R�y6P:a����*4J^&��Xu��\U��eQl[�p�x��V����"���l������-��`��!t����SA>��rC6�n���C.���v�K/&��(��9�k�'�F�.N[Z�?j;���^�4X�����{�?���w�������\���0p�$��j�I�T�w�6"^U�\����t+���	H~z��tO�!�?���oT"���1Z*�P s��[�tt�T��"d}d\�9�x�(6����K�9c�3:�xH���������[�m@�T�v�JFe����_^�������81�
c�D�'m����A������J�+]�jB��#fjr����'��?���u�.[V4;� ���/C��;� ���������v����l�e��f^VC�b	������&N�1���W���H�-�Y/����7����E^!��;a\��=�N�$6B+�C�����/�b���Yc	5{�S����c��T��1�a�6��n����Js=FF��Mm�`�-���<��4��{t,a�J�	�g��3<�7![*L����2����N��8�mb�QJ�32X�2� }<1�3
��3�cZ#��
x��3AG�~�0x���t@��a�j�b�������c�:��$��E�Om���8+6������e�M����CV?�/�D{�A�U��T���g��v9B�������!��H	s�1����)�.\M�9�58&�����P�U(K�������x��s��3��u�OG��K�R,x�7�H:R!\)L�-�S[+��;m�5�_,�V���K����0�a3A+����,I?�"�$d���E�z�zD�v�~�k=�FG���|*�+��j����|��6c-*��O�������	-�f�
,("��R ��!�3_hd�	Z�ysI���A���@���t%��Zxr�W����X��l$8�Fk�WsV�,��c^��cs�
9d1������]/�[
	V�t��-��|�N7*������r,��k�
�~g��X�.	O�������4[O��T3��cY����ACSik��</��MFe�K�M�X'��UZKz=qr�}�g2Xx�w�T�&���.��n3��%e��������d�����A��?����{���������h��n��g'�\�����A�t�;)��:�`�_����M���y�VO693�9������U
��X�D����p}���Bxei����VK������!�m����n��*�w�n�nvU���)7�}Hk����O�:�W�H����D��=��	����������)���������w���<1��-47���
�;���]$��o������_�NO��~������d��?�G�[Gg����k��W���A ]���V�Eh:t��F���
����E�#�X�1��_��xf��}i���T�����sv��YEZ!Q��
Is�TI�q��4S�A�8�']��$�=y�u0}��

!D�&z%y�x,�%�W���])������t���PYcA+W��<<��]MFC������
U��@��&6�c���������V��
Z�����V_�$�Y�TZ6���_�P<|*-L�����b��l��b6����	�JYs6��NKa�����9[�g��eO�h�3�(A���k���?�e���f�cr�D��G#����LlQ�K� ���|&�H�B�}}���7Jx#�����0�,Z�ca��"N��������{��G����p^�ZV(�[�)� �[��7K�X��h���(������P��by�~� X~�X1��c��c�O�on�Y1������#�S��q��*���p'4p����V0�����AI@1`�V�Z�kOKC(��s	�eU����#
�!�����J���[�4��9CQ���T�45�GTqm$V��{'G�t�#hYt"JqP%lSn���B��)�0���"�U���T����=���l������82�.Y����P<���9'��PG��QY��Kb��;�h�F�=�{=���C��Pb�?��b����(/��F����Sq/[\^�&�D��l"���.w@��g���"i��fn���&�3q�(
��4���i�E�4�>��PO�V���L4KyX:
�BTe�cz�?dr��s�.:��f��i,7�;��	8
Hd��\)]~�|;����������U5"c�2��j?�Gu���2a��_���h���������6�lI�n��l{�<���]�ID�����J������V9;���Q�K�;H������G;�A^�v`���p�$�����:g�!<�r�cv����r��W����^~I�����WE�~�\�����������q��t������K�2d%��5�i���������*e�t��_�B��L9�9���>n|�P@t��(~@����r���? }��F�4(��r|��Y
�=�2������4���y)=�$��
P�*����2�,��~��>��"k�cM�.t>�!_]���}�oF�O�f��\J+�m0�S����L�Rxl�5Mm����r�8?l��7���1��)BS���E�./��V��
cH0���&��{�������
.\������^�X�G�J�\8>o���Y�����.�4Vv��^~���\hT�FpA?���F.F�1�9PY���B<���x��g�N^����^0��8����#]�;��(��a���A	X2��M9��m����t!xA2��Fg�1~��������Ff�{��XfT�4R5�����,d���%�8��8qj����vX���,������Up���'������X��@_�an��[���:-l����`��S��?���*��	���9���5�9�x!�k����U��y��	����?��~~A���3[�o��`�k��T
;�������3��<�
jusL��~������l��;
��g� U�����C���XLB�]{q_2�m��t�P7m'�������l�8K�w��f����;�S�/E��,(�s��&�*��x:���0��{�+L��f�eX`��l�	��������,Y�[T�${�����)L���_J���_v�P�>��� ��,�t���V�����]|B;��h�s��w�i��U����'js)P���5��H�*!3�tc�����N�o��Sl�
U7�������b���Q�]R��Pw�c�1�G��Ar��ut~v��&�������~��tI��d��~:��cM/�����'V�n������#	Iu/_s:lmG{@^�l|<*����]����8�b�.e�v���T�F���iPo9
�����]���;���7L��t���6D�9�n|>�X�_%����C�rzI����z�p�Ws�tH���
���Yw��A� ��/�@eo���y0�^�j]�g��*��#:m;.����k�F��N.��<?b� �y
\�����*�'?��Q�[�FCas^����6�����*��ZI���cc��hI�����W������3c��)&��K�}1%@��M�z8�,��Ra:�.X8���f5jb�	9<��"�R�BJF�ya�p�#>n�@��9ZF���J1bXl[)�[Y[�H��RJ����['�k�<�9����%�?.&
�����mv�����(~���y�y��j6���^l��N����?}�������������l>}�x�l��/�������S��p�� �4��������FS����.~�Q���+�����$���� u����'��0�P"I}�
?R�:H�}�'�&�8�Az�rf�b��C�,�$�YxX����/6��d4���&�B,_�A;��+��������~���}��������'����{f�rx�v0�JK����pq�_=����~�"���p}����7��rF0b����MM�7K��(�����F�h5�!�1)���y��bpR�m���L��;�3���)z����;�N�,����E������+���9����-:c��V�fB�3QK�=|+�\[3
	�H���4����.��v��8��(j�����y�E���!��#������H����O�>�]���>y����4�x��I��Vd�������]�4?X�d}��,�HM�!�L@���Fh=��^
�Wp��^
q���l���%���u�������=�U8u�����5���q�=Gb��\S�\)�f��N�~�A���a��U:�x+N<����a�u��7���	C���ng�k�%����4Y[�J�Qpa�N�W9n��k�|�1�PV{��1M����Ww�mA2�Y%������9����-4��^���l��#�g)&i�|�H
�_��aZ����a#9���>��rH{���#A�o���d����"y�:�?�����NZ K����O�N���w�x��������<�x�������g�O#q���X����n.`����n�!�\[�-����f�F�^�[]ZG�]D��q.�A:d��.4,II��5��Y�d��(�o�/��j,�'�(�TY���8UK\Z8���$f�������{�<;X.��dJ�?����`�7I���&�6	V���C���p���� �4�P�(�&���(K�>��l�e���<�%>�}�6,
��$�l�@���	tcm��t"�o��������Ahf�����`�Pf
�2�u�,�)T�^%���'����Qn'��9�l�R�)e����"d������u`�J�O����?����f�����^�7�r��Aw����n�!o��<x�A��i�KAG���nb'$l��Gr

E�R����\����X�n��E�V�r\3W�w��w����"�W{���:����@P_������������V�i<�r��\��rIL�������Cn0�	����g�T����)�C�i[�N���N���/���X+J�D���.��� T�gI�L<h��e�O��K�"��q������i��L�"��S#�5@�*��d�(���<c+�����/;[����������R%��U��
�L
Zt&u�X�O H��Fk�cE��e6!��!�K�<&�!���I�Lezb�( ^2�������A�lF�Q�R[@D�x��ii��r�(������������W2%�S��������P�c�OP�����A�MQ�&_i�t1��.%����I>��
e/'�������N��.��&�v�lZ���w��d9���?RI"g�	!t���������i�,2�&�1�����j���~(�|I�c��Dv�����=��E*�c�����f�$k�'������9���SrO&�2��S}�$�~m�r������E+E%��(Tw&s%��g=��
�9�)����Y��"�����$-����6������*���\RF_Q����
�����d�{we>T�T�ZIPW��<`uQ6,�P��J�������y������l<�y�x�*�<h}8�'�[UBU�E}m�$��93"v�#S��u��>8;��:=i��! k��#��p�3a���	��D/Icg�����!�/���Qq��������!��/W5��e�^�sE�:K3O�����6��#����U0DM��$�=��_3O�O�,����+Y4��dT�C�J��rU26�����9�}^�)]L"���%�u�ml"I�k�^^�7�nD�`,���ZV_�K��`I}8a �;��W�
*�H���%���o2'*�j���H�&F����k�������e���C�����~_2����q�J��`�4�d�D	��������Uc;���7a��(�d�����c4�K��������D�9'��@^���\|��1���N+�����^��N�}�Q�u���{�����pZ
������_�?�z'����,�J#d��1��+�>�������b�PT�)]^��S��	Gm�&�$�����W4��{�`��BA)�F�&��`��zJ��D^EJ�,K~�6�D����������]�W�
���������Y�q���&��H}�U�I�j�O������*Co���If�J�*
�u�����X�
�?�#����w��!~��B����U�M-o�t/�B�0sMk��r�+���7H6�����i�@�W��h���H�&��=����Q��p��Dn�����f�y��5��c���I���ny����	�7�w�@���5j2@���&�TiwN�M�m?�i��7L���wHui�/t�}���:N�����fB�%�_a��Q2�z\�H!|�h����Z�T�'R��cF�#l'=5�GCn�j�����Y���v1���T�����W ��0c�n�J��n��A���v�(~m�)��8��ho�X�N��W]��9�=w�M�;���Ia��8M�T�e�W�LNo�wfikQG�L�T������
��Q�r����������@!�Q�S��ei�"���*���S��d�e)Y��L��l������Q�W�	�#�psT�����b����n�|!��sd��qx�k���\LK!UHk>�%O0�87�bbP���E��I!��<�N��i��*��[��/���������$���uQD_kk$:�&�M��i�j�����vn:��X��B7�
��1�M��Y\�X(��H���K��7��Oh�vp�VB����h��J����fn���Ov)te9W�9�jgA'*^������a�`�)�|��u�y���|�:F#������x����=k6_�z�${�]>X]�Y��-���,���?	cNZ��.���w���N���;{wN��+i���v�%KDh�d��
>�o��T�5B�N�u���Q�9�c�K�����H�b-��
�%S>�����/[���g`8���Ev��c60]��
�C�����?������������\f���{���Z��=���h�;�h�~<>���������������-��4|I���<�
{���8��:�_��^�BYu�����q?;�����]�i>$�+���?%���S�h���e��^=�kDrD�S~�B���6mv�,){r�x��5%����Oq��p��/��F�M�^2�yR��'q�|�	
����j��Z�
�$�J���+��R����f��]����g�h"�gO����=klo�Lm����&7�#Xkp�:m��}�&����	-�Y��kf�0���N��qe���x���o�m��@�P7��o���gx�7�����U��6�����9(�U�LZ�������JU��.���^���G��e��<�?�����8O�wb�[t>Dw���\lV^����1�����#���o,�r��B��"��H�������f�g�K������d���R��N������/�f����^.'7�=����tL�����7�	!�5��u�������fY�b�;UD���,(�g��I�CH72
�P����m��O
�	�J�R?9E�)U6����vKIu��~��,������V��[��;;������g�o��g�F����%?��R���r�l6^-������� �u�\��J��D��x������9����g�d~`� ��j�O���Qg@��c
�c�����9����1�ndc����	#��8�n�L�#����_0
�(���G'��4G���[�����u��T%�\������h6��-�T0:����W�G����Q��`�'�5]_�T��_��a�
�[%�{�M�|�j��������U�.4a;w����]T�Rv�rg{�Y������>}��fU���EUK�"JY�O9�9(�n}���*�n$/�������;�{&"�v��z��:�*u]����_�&_�M.q5���/Ec�6���h�}*_P�M��DK#G�6��������Op���=��
�!i2y�`��P'p���I��l?�j���;�wR�'t�^N��	�������.ar��v!9�#�%D�(�Js����[���$�.�����GT&��r,��M������� �9��e�Y:��u�=K���MYXd�k��PV�
x���o�u^XF�w&�
a�.'s����-<������j{�F�|����2�V�M��*�����������/��%�<��E�=��&m��T;�m���bc����U2H���
:��h���	���]8���u����	�x��,��oL4w�0WlA���������}��igg���w����Mae�������D�^����L��N�9tec�������>�,W6J�to�Z={�k�b�}w!��^��N���p3�EI�-�G����B�4gC20��%�-�2ZO:���r:R�����kGV���Io6a����-���� |_�X�/p4�q��iL�J�����e������)	�H����6�n?y������FqM�gm�;)bB���G(�u��~���>�������Y���x������=�iE��mt��P���V��&�{����0�f�`�y!���^v���B%�����+����A�e|N�=�T��H���(j�_I�O�cP�X��
�^o�L��8��kr90���PoZ+>���T�Vd��<���5��a���;�
�(���4N�������Y���.�&e�yO�!@��WYB�OB�`s�<y������++,^�;��k%C�����V���������r���<�6��AwX;��o_��r�9���+�~��d���������+?So1W8���7�~�O�kq��m��9���s��!�����.����X�-��0���V����c�I���0���&�'���f�fs���;����tpT����REd/6������Oy��T��b�����O�/���Sq��x���������x�g�Wj��s�Ea/ gBZ��B|q����?�c�^����!P�7��V���
Ry��l��R@Db7>��w��p�X��N�	�x$�Lw�aN�lRW$eC,M(��CF|�|t�_L%��P�$p��}�EX.���w�	�y�I���Y���QD'�)>z �Z8;����1����;�/9_��z�+�Wk�~q����\�V*8�Q��xX�i��3D�.% [��3d���:1�,AL�� %�n	��ph0�EH�\`�|�����N���
������E^n;f�3�����d��.y��qR��S�Ap?XV��h�i���\t1��Z��J�� �c�l��Z�����!�
OYj"�&�0X�$��9z�����e���������@�(��@��>G���8p8.����f���nU{h �,�4��T��G������	�k��K�����J��:	?�+�W�p_����t�C�����:�qp�;Wp����9@JU0r�V
��Q�������]t����l^7r�/��g[?e��J���"cpm/����jk��j��,���Y,_��?O{����.��L����!�I)��r&!y�$'y��-=���2���At:��:������}2�.0;���~��F�L���9�^�E��md��VX��FLzTL���(��N5����P����C��O9#���qf���(J3����:�g�ZL��Cw�[���02�'�������������~W�Mz��r�SR��r���$h\��`ny���D����f&5�����N8K4��������� ����I� ZtKi�e�^����������
@D8,���N����DG�8��)��b�f2�������M�\�K��F�����hC�?�ki���X���?�L�(s���/on?�,:�����QY�Bi\�b�9XT'�����=(��3��C�Sg��,d��A��G�>�	��^e��e���F��Vpq��8s�t��=#T%�0�gu��\�S��@�@>�����`fb�J?��]E?���q�tu5����O�~����5�o�Q�*�����H�R�]�n(7���k�]����K�h8u�F�g��8�!M�B6z4�b\3%��a�����N&�<W�K}Y���q-|�^l1��?��������(��k��������:�����I��R�/�f��=���	�6n�d�����#_��z��O8���Q�k:��+�LJ>���9��9�K)����q�0)����%��~J�u���]+S���@2��>�:ogE���fS������Qt�4���B[�)�$�|��}S.��c��;�
�
��sW�K������z�'f	�u�<(k�4��p���L�{��Z��
��I64-�+	�����u/vG���1~�I�����`yp���G5g�R8g���?�����l@�w���a��_lj����!�Bq0��v����_k�$o�$�4K���J#��q'�����o���	��0f��FH)wuN�����0�2�A��$��S{���P�p��`~�'�X������"�������wX����eW �rE�SW�u+�8���]g��]%�>�&�d�8Cu��<'������O8���S<�o�e#���rd2�%F�$��'����X�,����H^� `��Q���

���i�
,D�Z��"��0Xg9q9t�c�w�+��7�6
BK7�rh@����z�/�Ew4��E!�H��hl��	�V��lC�
d&F�Q_�	�@��S�E��.���Ad�(���[O�b�f��z8/nZ����hy'�t&Y�����C�[���R!��?7�����^�Yo�e�lf;O:;[[����^���v���f���2#�.�������H�����K)��n�-��J=��"�1�������H����@�:�z�4�:�4��j@t���+81OM����2�q�����G�%����{�q��j���	�X�6v2�w`��
FL��5Xe/��5��V��V�Y�������v�&��������L��2�c0����/��&�~	�G��x�7�`"V��l�5�Jg�b!��/QdE�f�����<��KR���$#5�B���NK����r����8������O_�/��O�����b>��Q��V���q��su��r
�!��npj6?1�y�c�
*��@U3c��$_��
)��v~�����(�7�7����[lI{�\�\�~h0��+�D� t����oy#�?������.Z����|t�N�:R��Z����l��-2��x����|��,BC{���;Lc������7�|�}���p��Hz�����Vv=(�����D��:W6�O���#T\�>�������R�"\{}���<R}�����1`E��t��o��;O���C��^=���S(1|�||�s�8�w4s���AZ������m��m����bV�<Fw�c�������b{���)eO^>����Lp
>��|HA������NCr�����+��������C�v� �����^x�����������#W/��B
��Rh6p���<?����i�<���Jz�����!?��6��
<�xZ����/�OP44���Sh97D���nh�r�����a/bb���5$;)XqB�gT�m���by�z^�~?�%��=���%4�lR�t�y�`����@�J����1�$�_�'R�W���4��;h�cti�%DZ[x�t�I/�j61�T��Xe�k�x����?����&*ZKT,����U"9�)EE�C�x|
������@��1�`��R�YR�'��s�A�-c�+0�����e�7Yg6��q~��j����|�<�
?��{����0��	jO�mqY����*�����d
�����x��<�bX�j��-��a�:��#v�~I���xaBTd_:3����{@��B�(�})�Z�_�R�m$D��r{�����Oz[O��dQVt3����$D�@T.����\/�%t5�z��������5o��0I.�R�m�#�}9���+&K�J��y"����8�	�xhm0x"��]��K���\R��I�)�%��*-��BZ��9L�v�/x/DU��|>���v�-Xp�����1!%�po~�<�O����=�#}-������S�9+@���p����G"��2�1�j87�W��%�a��G��17������1��5���s������
��X�rG�s����v^<+�Wo�K�x��j�ed&&�O}�1��J	�#�
����i�j\�e}s��]���}d>e���[��a2"�m�b�+�H0~��\���F�������L2�-&�k�hQ��$�yI�e�X������)������h<�^���O��4��&����~����5@���a�G8�z��U�q�)>x`g�f$�i�5��~�M���l�`�����m�;x
���7[�\���i�h�T��H!��n����J��w��|�[M�7����O��L�n:�U�EU�h��m3�����[R�D5��u��&���D��"��^* �V/�o<�����S�M��)v�� 4��������H&������^�h<�q�X�"T�u��o��Q�c��I�5u�f�}�!W.J�:3�����D�pE�����T���������(��5u�hr��Z�
�I�[������!X>1ei���:0v��2���bJ-�e�
�?�j�C��>�Kj�9�
)��NJ!9��0B�q��M��p�bDI���bu$`n4�b��&�o�1b
���^�.	+�����leq��&���b1$���#�(;�J�uz����"�	�8�AB����j�phG8q�CB�6�����i�n7Gb!���x����� S��<�������P�+��5{"����1@�#���N4��C�M/P����[�\Cl�2c�_���i�2(�a��V����]�<iX�0�I�,3:
?�Sm�@����2�z(~���7&��TH>^D������;�8�8����H�0�M�8�i� ��������Y�����I_�FFq��w��n7\�l;��u�>�T���X����\��J���h��o������Ka��e;q$+�9� z�$��	�z�t&����FA�I����z��
F�H:�CES:������\pr$�a�����R����������S�������]7���S��l�x��E��(�c�(Q���
8F����{��@�����9���L P���9\���G?��R�P�����U,�%4�|�X��le���������M�������N�������y�h'U6�������Wm�2*�;�}�:����sx���Y������w�����7�������������;����)�%�Z���s.��@l���J��z������?�9�R0��� �w����sP��WN!� h��6B�GarC�ZL'�X����CE�9%C�-K�o�?h'���mRTR�XL
5*����C��$K����P�� aI��d��/Q�M��.n��E�=�S��(�l�F���)j����n�&��c4�<�d����%�X9=[���,?����O0��Y:�-:o#�����^V��Oy�@!��9Y��� mz�'	��Tf����`�1�����Sx�J�����)F��L�`�)$��������mR�_I�"3o��
>�0��
�{�w>6�o�����3�!7��7�)w�����sn+i�&�w��x���'��<}:'�$����J�=E����f�����c��z�#_Z��C������~	�i{����<,���B0�;������A:����[�����
o���/+����K���[p#���n��Y_?��HV ~T�	�^����9�u(��3Ho��J 7T�����l�X_����������
�m��a�n������`����Tx&������]����*�7�����
����
f�j��p����H��QRl����;��9�O<ad�^��]��2��l�V�M��TA�y����0��5�8#�����[��@�1�5����ab�2��R���)����	Xm����CX��(_�0�m�[+��`�P#��%.��!���v3P�q%1ooH����9�"K'���z�BYd[1��A��]��F������A��yf�vB�..���� ������F�����%w��j����6�������{��h�VJ)���?����p���A�vt�����uM�6���RfR����S{��cr�s�pGm�6��+�PyJ���U�$_�$
=j{E)9�����
��}��*����a��;������D�4�Q��o5�/�M���t4�0z�>���.
c8�@���\����P���o>'��3��$�c ]�<u��>{����!�����z�1C��QB��G%�
�}�l�<%�]NC�p��aP���X������Sg��g��>h�5G�l ��	��
�Q�n��~AG�W�������x�AlTe0P���V�FO��j��7��# gr�-��U���,S��j��[�a��
����AT9&�#a���K�P9MVx(�Y�'B+��t�S;M#/F��'��T�u�:U��hZ9D�=J �h>��dg'�o����+a75T����1�,#��\m@#u��0��S��M�9%F�K�]��T�&�W^>S�2���u+�2�i�~��W������	D���c�G�Oi�����0�����`;|��L9Kdf��}�T(���-1;����������l��������)Ea���" y��}��N9�X9�S�a3$#�`��5/�v����|����M�N����y�=��uxB��y;7�7�`J�2�����Ah���^=�Gw���0��*����f��:� -*@@-����?�c��o�8�����z��Y)��Y�q�	�_�{���rl4��>��P��3&�u�)�����M�Q���~�����4�Sj&G����T�P�T)�/�eM�8(���O�l$���a0xiiw	��:��~f��R�E���VF�AZ|I�H��������/{�G�b���a����T��������t{�:>��3���'��YC=��u�!��aP��Y�IZxK��i�y���������(z~x|�AYMoO�J~|������!Z)2����.Yb��[>_��+��?�1�s�^�f��M��#n�7w7���AwU��j92"��y<��]nt{���/{��0C�z*��0��78�Yt��)��d�k��mj���~}T�����.�+#2��&8L��tP�rW�O�W������������2�;^Y������|�G�g�
$$(QS��Ct.P���;��O�&4C��{�2����.��%��\������[R���:�>�������T\���t�����a��vv���������v�)2� �
S��e~�!Q��:9v�V��I��C�������.h*�"P��t�X`�K
j�K��5����u9�9�&4��!�Pk4�F@�)�3�k 6�W��\�!C�n�	M��J��0G{6a�9_k[�,�����Y���J��l���?\����&���`�65tM�PC�������4'�����aA{d�d��y
$,;/�J**8��S��:�fA'@1��f��kb�\��/S������S��"���C���_�_s�)��|@�	��i>�O�fN�NF����f�2����
���#<��������9/��FM�$dkI�t�j7��%���2�R.:q���"����Qx�����+|m�K���A����<�29e�:B�:���
.-���q�����HU�l���Q)7�!$(�gluL���F�}A3-��~,q�����q���
��hl����g����H�(����
�^����I�����Fu���5����1��so�����3����9���F�Grq�{4T�hN��3�yg��d�^Ew��:lv+T�?;��#�
��0J�%����v��2��5��~v	�������\+
�`2&���i	*��Nu'~�G���S�N�{WDb�
�8��.����b�+���(SQ�p[h���#��D�r�YP=��2��]
�����'�1Ut�H�q._���X����)5��m��G�k��c�����
�)#�4��n?������O���i$�&��H��|����?8f[�����b����*��)�(�����a��i�_�;�O���4����}X$���|
����cs��%N����pfyu%�����}�Z7�t%�1���w����OR�����'�^��{n'v��6�xJ������L�!Z&Ie�4������z��E���A3I>���?O?~�;����C�K�*
~4�2��n��b�a�gZ�nvZo�������u3��p�=;�����pm
�XO"-���N����������Ch�3��O0����0�'[����3�h�TPO������av��P�|25i{y��8&2+>��I��u�~l\����S-!Qfm�E`m�2&�-D�T7i&��4b���Y�=���U��n��>h��m���I�s����������*�olf=6��Z%���&�KV��0�^:aS�`�M1�tD��3P�������@���������
����ps�
F�[����~>]�e���	<OF�V���������$��v�E�u�������r-��0������$���e��G�Z@
!�z��<uA`�������l����2�1�p8#`E���HI��S�s�D�z�������]������H��&�)�t��$d[[/�F����m�
9����s����������$��x�����IGnK�������d����%HM0
J��� .��g,�#��2\��*. ��^@[�^�[p�|���zO^@~'����D��\e�)W���Dx=_/�q=K�(a�47 ��o���*��A1��nil9;[�Dp;�@`'�����Q�q�����G�'�y!��~�|��)6�
���!���<�w����W"q�>�YT�0V�-��Go�}��1D�6��S�IY��u���������	�c� Y4�&;�O�Cf���:�4�r7.��H�3��w��/xC^"~=�%]`�+��.w�DEn�����pl����C�@.U�b��^�n�T�r��p\�����x	�N�vCM�;�
��~��.k���6���&���� �E{�Gx�U\�z����M�u8-~����
;-�S��C���Y����~O_?�K����q�&����(%��:����&���8��gu�_���<y������H�F��������+����f^�`j���9�(��Y�7�==��w����l�pC�����3�~��A\��|,>9��`
�Gp�A�N����?��\,��T�q�k��^>y����6���/�f�,�A��f�Pr�#cq�m���jlh��0z����v=R��|�S�7���}��[Oj��f�_&?�1��	�)�����+�@b��q�0��v�!*����q&l��H��=q������S���*�]�n�4�q��i���j��AR;=:�'�`J0;�8Ap!M����`TVl��B(�Y��=��4��W��o��,�,��j�r[���E�:�x����G�2�@���!�
$���5
����������i$����������������������_������W��3|x�w��d���Y3z��u�������)����m�����r��5g��Hm|����r��a�i����`�FJ�t
�8O"u���Dx���
���$N����D��&9�s�d6t�J����	r���B�e�)]����M����Ku2��k������xE�{P<�2sxR:�E�����YBj���[K�e�����b���#���0�A`��>������[B�_��_����OI�KYN��u�y�<V�Kv�;HB6g��\u��>%e�����C��SI���S�n���F��p���!U���8t��0C(��yBC��t(����MF�YD�	ez���������������ciz0������"������Ouj�D��%�yN����n����}�%���y(����
Um��Cs~�mk$����(�m{�Z��:j�p[��������@\�vj��K�������,l$ ����r�G������>p�w������@��*�=����F����$�����yj�2����w^��i����W���E&i����%^i;�:"
B��
5�S���?����U^G�n��Z��'v��M0���9�D�?Z����m������%|7;c���A���s�~d[�o���qjl7���������b���B�kjb{p�C���|�f���~1����������EP�!U��7�����S|�e�w^t�)��C�:�m�[��q���6�]'x�jL�	H{���x�*�%������X�Za}���������'xr�9�ZO���j��Y`��t	�=�������w'��2/���9���>��y�2����~����V�G�{�����L#��<�����e^�����b�4��pbp��';;O_%��'�������{��~��y�x����;~>j������
Z����o0vB��1NG����w(:�������Y��5����?�p�rx�����(�����e8�F��mA�����W��s��Zk�]���Y�m��_��m�j��`������[�pQ�o2��0H&_o�
tm��a6/E��
��1�/��,���h�Q
�Vi�k-��<sk
��5y�.|�t�vJm���3�r_�����7~k`�:�5��U�|��Ac������/���ek�f5���Wo���z��ZD~��k�4���,��/J�����F���Y���KSblK/�����8v����'�jY�g��Z��-iO��"��PX���nZe�b��n��xo�<i�k�Y���O(������[~���c�\g�~�o�?�.�#��z�0wr�;P�p:U�X����y��h/��<���#O���<G(��Jm�s�"��G������b�	z�b����3�y.c��iqqI*��#�f$�Vz�qU�����S���o)��0�������6�����
&`�d���o��a<n����o���`�q��m`��� H�4��!�N%�d%2�5Y7���������5�/z��u_�$��'�>F��PP�HD[�- !�n��������c}�U�z�����S�!2��G##E'�������G��	g�:�dgk{g�y�p�d�����Gc��}7����w�Z���=���������g?qC.3��������d�	�h��v�~�B����G���9��K����3�q������l�5�����!F�f)r����'/����������?�����/�y&���H����}�Q�����~��eWx@���uU�!��UN
���H\���;�������5J�NL���<��>RW��c~B����U��b�^�<������cx��/_�B+5�;���m�X��{s�?���?r)t���p�,9~9zT��z�O	�E
����X���c��&)�!�y���pT��(z����:~u�GHm���7#^*�G�Z��;@h������[�[a���f���h�%,�o�A�b�����c��O)Q��&~t��A�8��)R�#��[�]aq��9�_�p(d	��1�0K)�R�F��Z� 0��`������6dd��MM�}��D]����|�xB
S����ye9��;<������%������1��������l���F'��Xz"�Oe��v����v���!���?�,��J����;�	��F&�cU|o�,�Xh&���a�bS4�
����m#��G�	����!����ti�g�	��|r�����5����yH@��>��/�O0�� ����\��8�����68��%���`n���;��T�"-2���&x��������h��������+.�.T��<��~*�	����"r�_��������n="�����p)�~����:�]d{}�#��<�#�{}��j��l5���J"��O'����|���jCt�Z��(V�L���J�������
B������I����f��������(8��S�x�G������2���bX���.����Ik����sjMUn��=���W������%���	�9l!h���<}��y�Y����q�����	�Xf@r�]�%|�c@[6����_���~���������������X�|��( �Gu=O-��@���G�_�����|st�w��-��Q��������c���x��N��*��]R�
�D��llt��$���*3�E�p���=��;\~��7I6���	:���A$��_���2��RX<���`�X}K�3��/'\m�A��^�Gp7�����'��BqP��#7�r���& wn�,Z#�t��T�qK���:�@���-�}.�h���`b��ZZ��\�A��h/G������J\,"�`�����`�#�A��������'|�������9�����l���7F�1����z�����URY�_�K��c��mR�_B������!�P�r���h�����nV�_f)�`bi!�-DI
�LY�O�G��a|�vrN��T�$��3Zu6���w�N|>�f%����x�@H�3B�l>�1����Z
�?q�\����2����h�f�.�@�\t��-G��hr���z��U�U���?�e2�>z	�:�����K��4PR��m";��ib��,97�}��Ak�~��pjK��$����:���T��T�@:���8GX�#p-�������k�$���q�'��E��"*~K�������V�cx2H��Y�<�w��e��K�g��g�go>�}{x�J��/"�:� hu�)"s��} �=��yQv*AA(������k�D+}����Tl�}Iu�t0�"0��f�� Na	���\��_�J�W�?�l;�_��Lh�Fcfd�\q������$���Td�a�A���^S�T��N��+�;C��������X�����_�?E��9�8uS�Od�qZH	�4y��=��))�O���*PBm-!���{'�[G'��g�A��g�����/aR���""�%�kC+9P]����$$a4�;I*�����#�9��
�l	~W������L)
�N"7��(��$.�2�M�`�B*�����q��'�@,n�"G���w*t����;~
�1�'J�l3
)l����mk�R�Rr?K����Z-h�X����H������=��1��w������H8���G
�M���w3��c�,"N�����<o
`nJZ���U��x�:y$d�S�oL�2C��uSVqWU���7EEy:������d}[���#�������)Q`���q
�s��{=���	����{2�4s\)�����8��Z�!Jv�s��E��"@}JE7��S��k���
��i�+�B/���!v7��DpC��K�����gR���R�������%9���g\��q�D!,�~a>����!)�x�%]����W�����c�-�b���C,�$Tt���a\���l���t-��.�a���;�R��at]������������p-8�-M,����?��+X�c����E{+ZH��N�����(���drKh0�{�<���7P�.3IJ�Z����A&�x��W&C�/����d���4
*���P���X^�1����������H%a+~��5Gon�����S�k�|����!=,?
Ki���
�Y!��)y���l@����
9�g$��#P����F�0�05���������Y��������]V��k���U�sg�l$��}C��h��*��t�@>���I��"(�it��,R��]��P�]�����C�J�Ks�-`ka�{����O]_P�������b�C��uF�Z��Lm��9|G����������������6#��8�$�:�h�������A��V��0e��]Z��J���`+Ya�hr��=��`
�JD���;I���Vq�=U��)"m1�x�`��Z�_g�4����B$;b�t�\�_���R=�t�3*i0����/��!sF"EY��#��'���"��|c�j��K��5c�_���d�F�z�bYU������su������,�6�@���]��D�'NU�S�%�`YbSu�,��/�@��f7#��J�{�j��]R9���u	��XX�B�L�|>�4�Q�w���x45j6j
�[]�Kd�M:��y���Y��t{���k���"6JB�(q8n^���!t���0�c��'�,���sW�yF��e9�.|���l���g�n$H����qR;�H��*x�,�z�����"�{��52blx���p�v8�s�9��"E%6lk$~�G�Zc
�M����z|WmU������&"����]�/8�*���&��
��������4
��
���e������Y��L��7*�D�z4�:�b=����/}��)����*������ao<��V9�B�5y4i��������7�E5�?��AR��$+����02�.E�b�0�*�W���w�v���W%1.����L0f#��r��C���E��v���C�����/C�������K�v;c�4�5�(C��[0���<ko�[���
��h&���7acr���������M#Q��*FQ����"�+����6*-+:����B��K���F�|����>`�qx,�p�5l��4��I�G@��b�
��,��������!��?��v17��� ����)�i�����L�����U80�<[$_}�i����A�2��
i���@�g6�;�
,�"����[o�)�zz�k�~�D�6������P6c��#����Y\���|��tk�Esj�r��d8_ {LZ���_��Z�����@������`�������'�|�+��>OmV'�T�~��������q�J�k������kW�6X���=��,�jrV�P���jA'|eT�����eS�&�I�}gT����F|�DK�.��C8&�|��iD�[Y�H_�1�fYUW����`SE��"��j�^a��`��@,V��4�8������������]���R9�������o��F�dQw\q{�uu�p6(�T�����a4����)���N�2
;9�Z���H�����q�J�Wa]S2{����*t��{q���[��]�����^��-����,`~q�oq�U�5|���y8(.�F2���
p,���^wT|��F]���z��J�"d,�[��DF��O��{���
�P�
olT(����u�W�+?�$Y���<g�����G��'���U�]2aN�7�p����[�����W���^�p(���`8i��C����#j�A\W ��d�wch�?�`Q�|4��|`&6@�d�JF�+������
�9'd�A:A�4-���g�G��'dt��E�c)dR�Q��H��0>zG�Y�������g{�F�s6&Z[�#�q���n�m{�st��Q�m����#
���V�y$�&�8vn%���e�������W����h!�g�i
�B��+������_�X5����v[�:��%v
�~j�r�'��gH�O����/��lZ#�`��`ym��*m<9�-�F-��e:��
���k��Zc�U��7 !�j��h�����I�������lN������U���5h}����2q�����\F��N�U���Ycg�kH�TP$K�������)G��.�bo_�b�4coX�@a�����W.d,�J"�]��d�s*����������k�9����T��LE�'��_�@�`^���*BGv�S�A{��g�u���TU��9���JC��n�rI�\�l�Ic��bzaZ%�b*�C�k���9Q}������-�����9>������k����$��tV��TT����XS�1�=�����Q2�9n�����_�G�/d��G-�&A������/f�l���x!i�y�a�������bmY6`��B2����~��Q7'�@\2�H/�"�"�b��3�H.A&d�41�l�l�Q��^~� #Ht��E_p(=�/M���7��������{ ^�@0���/���h����s����(�}�5&'���i����[7��9�W�*����\��<�����@��\n�E���*-�rp7�F���<��!6{p�cg,.3.,����|���� �g���B$�����dzPC^t����A��U	:��5��d�1!#�"���K����i&@A]�J1����1W�"^�-<A7X�!x���U<|�E���G��- <<���
�^�z����!a�
Es�?��LsFM�{��`������;
Wc��6���E�&�2���}��"���M���s�y`�L\�3�QT� �rz�08�|���Z.K����V�l�,1�N���'�'u9od����)�D+��3��?)�,�	q~�������7U���U��9c�K��pul?t/�o[.l��h#�Q2�u�Pq�5���/�(����W	����3%��hvy����^��U�A[��Q"�(C��b��"��X=E1��U��"��EPC���8>��j�ge@����$
��
��
��"2L��h�k�)e2MP�E+��U�����q�<,�[
�H?Y�+P
Q����F
��X|-A��V��+#MRI�����1��M�����s���%�{���F�A5El���'b�A��A�����q���4�K!Z�"��gv�dB�� �gm8���s��e2�FKBY����<��J�X8��|��sPI~��Bv�Ew�Q`D�e���X�x�:�����1Dk�8�G�d����\Kl%����
����������w������s��:(����D�K�9Wj4��Ed��!�����zd�	w�Y�X�J3 �}������2�i���N��[���������<�\_���Hv��(��A3�H�bN�G��ru�����V��!��.��5�<4d?�/r���4�~�{�6`)p��zO8�3f5Hp�J[�f�BB��<�?+_~�M@L��Nb�������Tsa���O�����^�^���/��n�
rx��v���j�U����^nCz�x���+�d��9���kJ:�������\���5Q1T���8/��qCJ�t<X\���4�{�v)}$'\��"��#��c	�(>�}���;�I����LM2�gK|�n���[���Z
u��Z{t:�h��&5�g��Gk%�_���O:0�W��������Oo{e����HD��d�OC�����w�Y����g��Xu����/{��>}X����/N�b6}M;���/��O�
j'-y����<S�Me�~��[)��b�d��?����x�#�����������[���}�;;�tr�@O/)�Y��t*dNvj�����2Y�����bG'���oB�-I�J�BF�^?�$"����S���������a���I
�{X�����j(�����{��D�.V����bbu1@��������/�m:?Z�����:)E��k`N����$��{�����v��e����y����������1��i+<p�����r��r�y���i�cd�e�	�-}T
?������Y�������D�����A�w~9M�_�@;���;��������T��S����O��=��}�n�/��ZAz�/>@�����e<���+�m��{P�*�����	T�D�{���/���s��\hX�/�M�}��|�~�9��O�����6n���gVE)p�J�:1�b<��{pB[+�Bn%��F���-��G���#x��	�7�����������BGU�)�Z���4{�������/�m-f���j^h�����E�)���d����D�A?�7���&�m(��>��h��@J���>�>T��7D�����F>��:�i�����S �N~�As��M��������l?�z�y�l>�~�<��S���������w�-y���\��r����}�����!I����V��������p�8���w��(�����Y�hA�6,��])�������/�H����z/����U{a[P��d���[����-������~�����g�
�6��	�����v�[�m���g�Eq�Yd_���dh��5?�k&lI���gO=�C�������lE�c}@�e{�~�J���P���d'���|4��{�5$�	1b94vG�%�LN�>~xw�O�6��&���p��ig�e��hg'{�[D��t��D�;D�;D�f�>�;8��Uv-���@��
��`&11�8��*�^$U{���l3�T�����dY���KmI��g�������t�����l���g�t���#����\������[���*~uU��|�j1)T�*�T�@�k%�����{����%o��H�J��C�����l@0h:(
G�t�7�A��K�g6�������"������lPF��S��������yx
9Wva���-�s-�AT�]�K?�%�6�,�{]o������a�z@����D���(���k�����e��\�_g!���	�Zh�Z�h>���!}���Owo~/�F;wp����3�U=�!"�i�^����R��P�,[M��b��35V]����(jL���X��O'|�Be	�#s�i�<�?�\������:����1�G
�*:t7���FB�&����&`�6[�����d=�g�TSWJ���������|7zEi����`_� ������K��l����R_9��,��y>�Y�
H-�IS��#�\����O���Tb���o}�}��w���6����r�|.%qg���5�(@�h������l�
���EvN5f,�
��9�{�a��z���x�*�����%����[��Hc�����,k�Z����J69�!�=���l�\��(% _��O
I���5FI�3c�>YR���E;�#��@����Z7@y����rT�����z���D%���P3��<�z\V���r�9�dD{��F����!�>��d�������FO����y&�E[8��&����'�M"\��n�v|������V	�v���h;����������C�.�4y
afQ%*at;�����-��������J��K���t��a�QfbI0��~�1��nK��&=
J��E�$���x"�/!���H����b��_��P2n�@Cs&z��z���$�
�
<D�1hO>R����{a`c�W��OGt��2�����F�?�t��w����B`31V���^�I�~��s��*�
�X������}�!�2&il��Q
����u�RT�#��}�m&���FF����)Y��/Sz�4[L[W�q ���2rw�>��`#�i����>Bj�������G���B.���d���w��w��7~���N�y��Y��u���y�Y��[���D��c|�)����A�q����My���u�
���������:��K9�����Y��bG�?����[��@��:�u��8����r���T���85� ZRW�?])ndaB�Ua1�.|�Q(��!^��~�h�|R!kk9\��
yw�eq@�$�6�� $���3_|�9,�r��5D���	��;l���}9�'�_Xz�������U�^���e��?�o?�
0002-wal_decoding-logical-changeset-extraction-walsender-.patch.gzapplication/x-patch-gzipDownload
�aS0002-wal_decoding-logical-changeset-extraction-walsender-.patch�<kw�8���_���;�?;i���G�;yM���gf��,��neI�#�g��~��(Yv����nv��IA@x/}w��3��t��i����l�:����90x�������Ny�]�q��Y�yD�e�f�U�2G��1}�K�G��������}�On7L~R>�C~�t4�>d��;�����V���g�f��,����r#<b��������~�_�I�'&7\�r���>X�n3c�;<�!�����<h���ef9!�g������
�s`2��b��������S:{�[������$�M=�Y��)g>7���MX��,}�/�I6��9�A� �<��r�t���:n�g�.p���2���������XG���4\�������
kfedh���.]��!�hg@�8��V"_�������Yp��+;n�\�^2�)�������u;�l�0�l'^m���3"o�!�`��%������bC<���v��L�6��z�b0������=�
]��������X��j���S������z|)6�"�!7�}��z_����+Y��VWVDLO@��e������C)�
;��Z��7Q��-�����C�W�E�e��c�$B�c������b9�����D^�SqR!!K�?����_B�������c�����p^���#����G�|)
����!�Xl[������&�
�uU�����Y683��L���}0����~P�U5j3��\�����i�f�^���o0����2�����v����F���S���>�v��7�.��m���/���4�Z��j�����2+�7��N��%j��U��ry�8[��x����7��@�O�7�'�/���A��a���|+]"!�mII�	���~'����5�:���������qg*��$�%�r]��FpX���������/@G��E/M,Z�����,"t��(6�T�\��"8�^
�p�P��#�DD�G$T��("�C*�^[+�;=P��tw���;������l��*Ww����~8�.A7arx{�'����rM�������4-�C���}�:�����d�A��4�P(F�
�{a�D���#����i�h��>���#�?o����'�sb�����q�2x�G!Q]�5[Blp{��x��HU`�OV8���3��r]����	���O�M����>Gaq������fn�'8r�r�	�����ASk�M��
y������(�_��ro���(h�"����%���Y������<�g��"T������U#���R���x�l���gO�r���\m���m��e7=�
3��0��n���^v����6��2�~W\�G��:�s�O��?�P�O��i[��]��-����W���~���9��f����������v/�Seo��f�0�*�q��	��	�}IUc?��I���j����{�7�c�%+��'�7Q�=Xdj��[���w29�t�$�t9�-�X ���K�]��8�<K��$$(��������6��d�"U7��S1��e0�l<4��������`��D�S�(��%�&Q��	�/����No��t�����.~%����>��F��\��O�49X*U��C��+��g�������^
�'w�������	|�pQ�����e<Tv,��c��������U�����V��.7�)F����$�]'d��M�55�������>�'V"��Lpp�� ?k
Z���@y�6w*�!��'hWUv����h�Q�7$����<�����w�h�7 ��=�19]�9��}+<���Ah���{AU�W��a�U�.���DZFz�hB�Q�k"h�v����Z
�_Q�V/(�B�q�F5wY��
�)aBS�����3�)g��cB�MU�����P�m*�[�0���O;��a�{0���7���_�y~���d�'�>���I�M�%\`���Z�+����lr���/'�m�~���nYN�����v�s�X��_���"��T�*
��T����U �����BZ���a�Y 7N�[U�<9�7�`r`I��ea�AX�(�K�
������~3�{������|{/�W��M�� 6�dx��N������[��s��	so1����;2�� ��k�I��$|�
8���]r}�5a���3���t��
�	���x�!]	(7����������@I[6:����6������og�*��6�B�vR����H�n0u�S0&"�H�u�Q�������i<����\(Cw�?��gUK��n��H
4���S}��+����OJ2�)�3���EyNT&�DL=���$�A+L��VGs��B�
�����y�zi1"���$S��(�Q��(~��	��g�^J�#p=��'%��Jv-����r�!�(����R���9*�����.��DL�H^�bD���w�T	���Ec���U9�rT�`��?0�����l�����##~0��v����/���f���������y�
>V��V��	�+� <��8_L�/�������22F���I+���N�a�/n���������vt�nh�-L�GL��}���T��T�������2����<f&���2#�
��x�@�2B�R��<����$K���!��Z����0��{G�Q������e��Q����f4��O��*g�����O,6U<��J~$�{�����}qv7�gYw v#�}��^��JGe6�1�o5/}��~�����J@K��� g{�a]==���G�}E�^P����������:���z�����`��J5�������Y�#��1�5���\f�,��5y?�o�?C���B���.z��AS���NY*�$�%��6+��Z\+�b�Wdt�V�+q"���$����"�DWd�##��$k���'kb�������v��)XKR���
vx%a���9������� ���Uy��f6�m�E-��:���A	�@���<�HAp*|H��_�������	������ ?"��g/�X	Q��d����F�z~����|�e��!�����?}}!Oe���=��ht[�����)�-�����?�K!��X���0�1v_C�����`Bn�M�X�9B�3�Rf�x��V��R$v�HD0��N8*�m'3	��3[i��O��H������^����V���NT:��@�D
�B��c5��n�G����)�c�������@n	����g����?cB-W�n�
���
�3���Oa��4�3��,r��r�TF������z���Vc.,'7�IN@���r�������NT �X�o5S{q����M��
��J���4�ls�����"k���!@�7jiN����?���1�B��^�1v�e	�������NR(��v��-��)\�'�������;]�!S����������N�,�6t�(��6�I��G��C7��)��c���sl�1�K��f��>roC
J�=���]�`?��<��0�	���RDxQ�\����$.�c���`y��E�`N���;�7���!�W����V���������&���3sIa�(�ANc��\x�?!�	D���0��c�y�?r�Fpq��9�S�Z���_���h%Xj��op"*FHNu�.��yx�D1�1%k���na���N6)�&�,	�?�-[�cB��D�����K&�;w>�!�P�v{�����Jq���$����/Zc�=Y����'9�rr���?�6�/������<��)�������'���z���9(��!>��T��l�E�l��H1�R�.��D�������X]������[�1F���6A��I�
��.t�a�i���u����&M��N��>8?f�*���:�e��v�=�l/.&���#|N�l��	��|�B���w����U�"=K���-��������{/�*p(7�W���w��q8.���5������b�{�0�%�4^�I��^@����1����b�"o4dV5[C%N=����M
+DX��������e�,L�7�0�a�����B�2��]�d��W��h����n(�t7_�'��Rn�z�m$�h�;��]xiG�\��h(k�#��V�EaAsm���Qy����	�)�&�U���V��'%�%~f�;�HY���Er�B"�?�����y�{��7��:�Mj����}�E!1V�fgsn|��6
7h��Z��}+��u����8SE�dh�g���J���+^��B��O/'(�f����Ah��{{
|����9����=��}m��jh=�3|����K.nj��%76�,;Q����U��{��[(�*����u8��F7��1/����������r����keZcBF1>b��L����
��y�=�l��E��S�50�]tV�K^D���G��dIT��c��������;KA��e@�4��?���������}��1c�PC 7�\�W�����*M*��S��V�)����%�(�.<�@|�5�8=������BWq�$U���'�����u|�
�:�kRScC�QU����Q%K���~o��u����~�>�t��SW74��l	"�b�i��qU�H<��8>���a�=i%�~E�����	����\m�������s���T�P�[q��u����L�a�� �Xm{�����!�� �����H~9-��-l~�_�"��R>Q�r���p�%�a�",'�U�1S�?�+?U5�ax3>�N.o��O�����6�����Y�,*mT��4~�;�����
>�w�UVz�NN|T&�8y9ak������OI�{K.D�����e��A��kgB��)avhZ�eC7@��pF�px��pp��
�������3aVQczX)����@�F!���':6�4�Wx�V��[���Vx8�4�e!��
k#_� X@+77v�����.1"���'�n�o���8�G�+y_'S�`9r��3]t��]zs���2�PNt4���zI��$XZ����]Rx@������x�$v��Z�N�XThlaR���(����Zw�	�2�L�P���H����~�h�XV�Hw�L�xf|�i|�>h
f�����j/m��d\p�b�rJ��a-��n��p�;�m���_p��f=})
�A����Ko�n�yNGjI��*��
�����n'_2XW}R5Nb���V���eo�Q����e���.p1��=����y���`�4]�<�h2�����@@�Cm����>XZH���vZ���5d��.��ny(D�!�u����'J����~u�J"�u�J�D'�]���F�v�X|��/C�c�fuQM������5Z�����!��tE���v����I�T5�@Q*�H��d�+%�
'�e _���YL3.����5��*�������v��k���w�^P�`�O<t
�������,��n��b�A�#~KOP:1bp�B���d�&~���.�u')�3�z�E~4"&�-5�)�3�+6V`CR�?��%��d
=
r��X����Ci�#G6�R7i�+�h���0��<�O�=���)z��a�;�����Q}��
t[v����~
����_��e��ad|5�U��Af���FU������>������������%���p�bQ�C�����,��*~(�{��-E���Z�������Ow�`|(��nU>$�A`�����>�}Q�`4�]��t�v�o��p�)I������8��S��*����=�xn�c^��~�6��6����7��oO~��'���0��oq���+��
���^��%��NT��#G��6���-�G���Gh�G���F�.@��_�������cZK��hRz�)�+������/�=�n���$������9c�s�1��������b��6U`���l4)�7�pox(���Po h�]CF[�F�I|�?&q%Fd�����d������18-����e�NKk����I:�?��r�~=,a��j����4j���A������,�����T>�M��<')�8+�����s�>�8��l��������Ae��U>�TN��0k0������@��t]��R�I�l���~�>��~f�	�}$2R~<f`����n�V,!y�=P�����cJ.�;������`��
�X�8�w������2@�7q
7��YA-����=��E>�j�������S)�:Ra�����ER�S�=���!�J�y�F��p����\�����1���l���`��:l�����m�#�,��-���Jr��k�nA8C�1	D�h �����{�S	PE�����[��6��fc-[	:�yRJ.3��jV��������/Xlo9aC���W�������e���8�hbs���!����j_d��
��+���%����]��x)����D����hs�����2V"b,i���Qd'��LF���(��l���}T��������E�R��a4�����<������	'6�����M|��7�E3���>�%���a�����'6���;�$k"��7s�B;�����5\d[�u��1u��*���J�3&�`�td%��o]�2#�<UZ
�������G�T��.V�Z�5�6�������T�=���O=1dR�|����������_��6W�OK���X��m
��>���F:%7����d��Pp~���R/�V��$"����?�03�J��y$��R`4�T�[������e����VU4��wkM��U{�<���8eC�4�rK���bE��&W*T[-�X7k.
��w}��	��xpg�!}�_��l"��0�h*53����]n,��2�����h'�_�1�1���q�9�"��!��}�3��q%���[�������7�v��Ve��+y�9}�� �;�E���$��e����s���-��\8�rz�|J�E4_�@k(`�h��2���l�f9
4�bY��S�
��8.�N@I��f:o�� S�%y��&�__r8��I�7d���i�
dCi���^�}�+_f������T0���<����	�,C��M���d
���\�����n��&M�x0g�PbrB�0��NH�$�	�[|N& ��1�FZNR�
�����C2���Jj�0��au�������2[w_�a��,~��6a�v����'���t������d�I��z�!h������U�Q$eJS������W=/���@�	��3g��*m�
�1����v�D( ����tA�7�$ ��?�@�lU�Z��$\�1H��"��
�cX�iY�,\^f*����������>�k/�3��d)���G��~�n���w��#����n��7B�NT\;
^���9u����p�<]�O���t��-�����R�����u��K�����?�K���g��!�`K3��|�s�~��?T��Z'�"�F.���f�$[o��lc���!n:��S������:�NGw�c����C�U�+��NyY�C>K�A�>�� b0�N��5j���w�v�@��TB����g�@�~�Yf1v�?1ixD��%v���h��GEJ�8p������������6���������L/KC�&�|��.���d�9~��&�N�"^YCnY��*���n�����<���)rw��"#�M6�a�kdW�i"�)��u����=��L�[06/|��j�����PA{y��^5�%d^Z����������8B��1��VDzK�-���e��jPP[Ra��=��H��<X��X���c�ddD�S"\#5I����4 �G�I5;�1�����&Y;:��o����}�lz�����mp��'��c[	�D�������o���L��p�����c���A|����e���Y_C��oi��0
�gb���K%�Da�}>�FC!�Flte3��o��:����n8���'%��+����{r@@(l�\c����B��:�������@�.�-L5N���h�&��zuy�-�3{�i|�OJ��;e�	�h���A�(u�qrr
�2����$�����������H���db��������|k���N�����/������l��<��(;]AN��
5#g���Dw���E�P����H~q�m
.3OC8��Z�w���W�4����$��+�����\X�G!2�XZl9�w}���6�$���z�;"S�<��%z�����pu;�K��y��������_��/��q�����_���O������o�r�^=o�J.�����K}��p�!�zI���d�����P*�n�2���1�����zI�,��Gf:������1b�v)��>���k(5�<$<6f�c�j:t�6u�n��c�os
,b�B��F�Qb����)d���1�X$�����/B��Ot��9���/xi85�a��~�yLf�K�*��%ie�>6�������W�������g�������;vq���f�Dr�8sM][�$�b�Np 
��URki�5���`�n$�\dc����L����{�X6�2���)k�_��|������m!q���T�������u��Y\
��w��j2����X�o�Kv]/�v��2�h��{K�?��?�&��v�GA����������������j�e�km�R����n���r&jS�VK�Xh��9���{�X"*��9�s�������5�:���l�����M85����]��TD����dkC�y�qdD�v��]��mi�w1V��)pbm!uP���
|k��_�����D����,<�(H!���}Y�X>�]�������JC����&`��1��-�s�f�'g4�UL�$
"���LJ|��;1L� ��&��	�P�$�e"R����>~�e�/��h+1���	s���U6� ��{ds(��n���H�V��O�{��ms�%��Z@�����I���������5��@`2+O�f�K�� ����������c�g��U �8��y3�@��w�7��(X���B��?�'.Q
C*��zic*6�3�h����qg��-|��O��K����M�>��{�~4�XUj�@��j�d^_�.��n�|Z���� 
gO2���e/;�y}G�J�[\�c3shr������g�W1�	��Bw/��a�:�`=ZqEZY�J�r�K+������u��w�
�*���MFi����W}X_���qk[����[H�F���fH�+�apnIs�ehFj)�����������H�[3��[�9d�W�������Oq�Kj%j�l����\��zz���"������0F=@j���ww90J�@�.��r[�:m�8��^	���_�_~|��c��#17�rX����$�����!<�*��=&D��b9ka��Ri����RZ���rP��P�&v���H"VU-�r^����5�Crx��C��h��^�qcfN��Dy��8��>���qV.^�m��w��b��FS�2�k�R_^�����P�/�K�S����������������H���[����e���q&���cR�l��y��{G���������G\�����}�Gc�l���O������*D%AI~`���UR���s���,)��	���PCX+	
��t���{ �)�`r2��-X��*V�)�F�����@�%-�a$�h�dc��!���c:�F��"2o�\P*N=[��$>&�1M���f3��I�;����{B��	x�LS��>^�S�r�3���>���_�j���SpRy�v�M E_�9�\h�n0�`�^�����%"������0Y�X�1����Po�ron`���C����d)�S'Mw��l��x.�����n
�{�j��v,�
��6�R�s�K���?����]oQL�^������4Z�z�m���������>�:�L�x8�K�X������tb�`���d4��jR1�����%W������X�}�b���^CU��n~
,N�z���~���f���l"���e����2ra�l�aA�����K��|e����D�z^L�������������I�(���-��d���oS��`(w�e���.��>���P�c�}�����B��^I�m+�@���	��$�VI��*�i�N��;Re�����2�2�+S�n���'�
�J��z����>����R4��A�<$^�x}Vt�J�3�2h��vG��`&���}�X���nO��U%E�*����0���<�<�P�s��k�Z*��&xE��%�9��X��g�Ovm�8��
����r"U�fI��X��e�(!��J��~��3�v��*��d�|"U��"arJ��q�@���f����A�u��
e�������]��W�����j������0���c��.�,�p��E��)'{��f���#�|��o�`���J���fK������s`m_)x���\��t�������=�U&��wmE<�VrNL/�Y[i�B��^v{�e`�WJ��?	v�&�v�6rxP�i�6r�8Lq4g��1g=s�[�9����i�y��b�V��k�s��!k�}j��W"��wj��s���n5��T�a`���s�f���M��,a��e�r�?�����)��y��@�k%��rY�����.��PSq���N�N["��w�-r�:H�4o�Ix; ��M������Y���^k�iaT�p�s6Ay�o��;����+����j�q5D$e����E���GFL)lD/������=B����'����S��3��d<�m<ek���Gg�G���������t�W���-��G��V�t�����X��UD�d��B$�j����r�Q�y!P~�����*;
��M^t�4]����c1=��O��W4$7i�p�6*0��J�����94��&�������?��zC���1�}�
����V�X�����0�/J	��&0|L���t#�Vp��6jb�XGc46�>H�l�jr�L�,��` ���������W������y!�c_Z|��u�W�Vt��d���7	�:����O,%��_LM�9q�����fS�S_�i�%�/��
i���VVA����\x6��<�HPeg�����JE5(�M!�Jg�/�����Z.x��L��l���u�S=���%��W�~��~��P�%��!
�qBw��1�{[U�qwO�qw�8jA�A?~z�9��#��w����!�~_�������������>8#�"����bP<Yft�����;G�9������xF��\��aW\�R7���	��=����3d���N�A���,��=�/�&���V��z�dn@�N5]M�7M��!�P�����)��%�~�J�x�>�������2��S�R������/���-�&/%�����E~u�F�����`����V�C<S��y�&���U�Q�$	���B�KC�cA�@��M�7��\q���F�}#������Ica�l9�%�OAj,�a��$����E���P>�~X^�w�E��������c�VA�A
.)�C��	I��w[��f]�t$�P���	m-������I����w��fR��hlj/�#�vr�$�F��R�]�������l��Sy@�����A<6
,I�w����9�+~2\�l�����I���4e�R9��`nHX*Vegp�.op�����c��~M�mW�D,�����*�&R�����w�Qo�����w�|�)%��G��������b�-)�o������`ic^S,I�!c~X)��S���
i>�W���<kN������M#������Dj�iK��f����f�G��*���D���+UV	*UJs�>s���[Kr��R�t�s��X8�j�-�8���i5a���7����C��4���L�C�l.�6��({�M�W�lQ�
?���Z�1��8�m#[�&m{Fo�7l����{���{6BR���V�����z}��w�-DI�ww7%Z�M�Je��q>�.�(+r�����PG�2�Te8���>>��_�A����a�%����%��=�ay�L�[�s�������'���������N�������������lDLi�gl����T9�#����$��	��ve�7�&��}�������o\��WcsK����b�71�'Ny��>)�mP�LZBN��hr����.5��;��s?i��c��z=/��h{r�A�#$c6I�+�e�����f@���5[9���%GX��+x��n��T�]|I7����������%i�;���]�	�79��D����uH�;�t��h:���������t�C9M�]�e{���2��?������)�i�r�L�S�k��!nz\�SM����t������7�"���r����-}K2n���f���K[&y�a�����������������+�aQ��a�D�~�$����`�\8h���[+k��KpO�U�F��F�y����A7�i���*���J�,�d��b��|��@r|�V���j=�
"�����T�;�y��\Q�TRk�{�jQ�?h]�^����������Y�A����k��I�4e�3�#�T>{�!����9Gd��X�]�t�+3���KDZ}���n�r�Eu"�*6�g-5�|�\E��4����W��������J8�
f~�����������.�K��j����'[����\������D]���v���@��GM��+x�L'�8�}J�p��V����r�i�37�W�M ���d)H�� MQ-�By?�F4�S�����7��=�6+��:;~��j�����������8��8K�R�uXE�I��T���1��[|�4��J�L}�=3��O���AG�(��&6y7n.�t\
��� �����.�������r�X@��_�������<%y�i3�����8���q}�A]z��g�h�����?
�noo~>6�L���D��i�#[r�����Z�������f�<���J33?�gn��>������J�3�=���y��a}��v�~M�66�A�lL0�
0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gzapplication/x-patch-gzipDownload
0004-wal_decoding-Documentation-for-replication-slots-and.patch.gzapplication/x-patch-gzipDownload
0005-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gzapplication/x-patch-gzipDownload
#101Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#99)
Re: Changeset Extraction v7.6.1

On Mon, Feb 24, 2014 at 9:48 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-15 17:29:04 -0500, Robert Haas wrote:

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

+       /*
+        * XXX: It's impolite to ignore our argument and keep decoding until the
+        * current position.
+        */

Eh, what?

So, the background here is that I was thinking of allowing to specify a
limit for the number of returned rows. For the sql interface that sounds
like a good idea. I am just not so sure anymore that allowing to specify
a LSN as a limit is sufficient. Maybe simply allow to limit the number
of changes and check everytime a transaction has been replayed?

The last idea there seems like pretty sound, but ...

It's all trivial codewise, I am just wondering about the interface most
users would want.

...I can't swear it meets this criterion.

+        * We misuse the original meaning of SnapshotData's xip and
subxip fields
+        * to make the more fitting for our needs.
[...]
+        * XXX: Do we want extra fields instead of misusing existing
ones instead?

If we're going to do this, then it surely needs to be documented in
snapshot.h. On the second question, you're not the first hacker to
want to abuse the meanings of the existing fields; SnapshotDirty
already does it. It's tempting to think we need a more principled
approach to this, like what we've done with Node i.e. typedef enum ...
SnapshotType; and then a separate struct definition for each kind, all
beginning with SnapshotType type.

Hm, essentially that's what the ->satisfies pointer already is, right?

Sorta, yeah. But with nodes, you can change the whole struct
definition for each type.

There's already documentation of the extra fields in snapbuild, but I
understand you'd rather have them moved?

Yeah, I think it needs to be documented where SnapshotData is defined.
There may be reason to mention it again, or in more detail,
elsewhere. But there should be some mention of it there.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#102Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#100)
Re: Changeset Extraction v7.7

On Mon, Feb 24, 2014 at 10:11 AM, Andres Freund <andres@2ndquadrant.com> wrote:

Changes in this version include:
* changed slot error handling log by introducing "ephermal" slots which
get dropped on errors. This is the biggest change.
* added quoting in the test_decoding output plugin
* closing of a tight race condition during slot creation where WAL could
have been removed
* comment and other adjustments, many of them noticed by robert

I did another read-through of this this afternoon, focusing on the
stuff you changed and parts I hadn't looked at carefully yet.
Comments below.

Documentation needs to be updated for pg_stat_replication view.

I still think pg_create_logical_replication_slot should be in slotfuncs.c.

/* Size of an indirect datum that contains an indirect TOAST pointer */
#define INDIRECT_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(struct
varatt_indirect))

+/* Size of an indirect datum that contains a standard TOAST pointer */
+#define INDIRECT_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(struct
varatt_indirect))

Isn't the new hunk a duplicate of the existing definition, except for
a one-word change to the comment?

I don't think the completely-unsecured directory operations in
test_decoding_regsupport.c are acceptable. Tom fought tooth and nail
to make sure that similar capabilities in adminpack carried meaningful
security restrictions.

        /*
+        * Check whether there are, possibly unconnected, logical
slots that refer
+        * to the to-be-dropped database. The database lock we are holding
+        * prevents the creation of new slots using the database.
+        */
+       if (ReplicationSlotsCountDBSlots(db_id, &nslots, &nslots_active))
+               ereport(ERROR,
+                               (errcode(ERRCODE_OBJECT_IN_USE),
+                                errmsg("database \"%s\" is used in a
logical decoding slot",
+                                               dbname),
+                                errdetail("There are %d slot(s), %d
of them active",
+                                                  nslots, nslots_active)));

What are you going to do when we get around to supporting this on a
standby? Whatever the answer is, maybe add a TODO comment.

+ * loop for now..
+ * more than twice..

Extra periods.

+ * The replicatio slot mechanism is used to prevent removal of required

Typo.

+
+       /*
+        * GetRunningTransactionData() acquired ProcArrayLock, we must release
+        * it. We can do that before inserting the WAL record because
+        * ProcArrayApplyRecoveryInfo can recheck the commit status using the
+        * clog. If we're doing logical replication we can't do that though, so
+        * hold the lock for a moment longer.
+        */
+       if (wal_level < WAL_LEVEL_LOGICAL)
+               LWLockRelease(ProcArrayLock);
+
        recptr = LogCurrentRunningXacts(running);
+       /* Release lock if we kept it longer ... */
+       if (wal_level >= WAL_LEVEL_LOGICAL)
+               LWLockRelease(ProcArrayLock);
+

This seems unfortunate. The comment should clearly explain why it's necessary.

+       /*
+        * Startup logical state, needs to be setup now so we have proper data
+        * during restore.
+        */
+       StartupReorderBuffer();

Should add blank line before this.

+ CheckPointSnapBuild();
+ CheckpointLogicalRewriteHeap();

Shouldn't the capitalization be consistent?

-       heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+       if (IsSystemRelation(scan->rs_rd)
+               || RelationIsAccessibleInLogicalDecoding(scan->rs_rd))
+               heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+       else
+               heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalDataXmin);

Instead of changing the callers of heap_page_prune_opt() in this way,
I think it might be better to change heap_page_prune_opt() to take
only the first two of its current three parameters; everybody's just
passing RecentGlobalXmin right now anyway. Then, we could change the
first check in heap_page_prune_opt() to check first whether
PageIsPrunable(page, RecentGlobalDataXmin). If not, give up. If so,
then check that (!IsSystemRelation(scan->rs_rd) &&
!RelationIsAccessibleInLogicalDecoding(scan->rs_rd)) ||
PageIsPrunable(page, RecentGlobalXmin)). The advantage of this is
that we avoid code duplication, and we avoid checking a couple of
conditions if pd_prune_xmin is very recent.

-               if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval ||
forceSyncCommit)
+               if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval ||
forceSyncCommit ||
+                       XLogLogicalInfoActive())

Mmph. Is this really necessary? If so, why? The comments could elucidate.

+ bool fail_softly = slot->data.persistency == RS_EPHEMERAL;

This should be contingent on whether we're being called in the error
pathway, not the slot type. I think you should pass a bool.

There are a bunch of places where you're testing IsSystemRelation() ||
RelationIsAccessibleInLogicalDecoding(). Maybe we need a macro
encapsulating that test, with a name chose to explain the point of it.
It seems to be indicating, roughly, whether the relation should
participate in RecentGlobalXmin or RecentGlobalDataXmin. But is there
any point at all of separating those when !XLogLogicalInfoActive()?
The test expands to:

IsSystemRelation() || (XLogLogicalInfoActive() &&
RelationNeedsWAL(relation) && (IsCatalogRelation(relation) ||
RelationIsUsedAsCatalogTable(relation)))

So basically this is all tables created in pg_catalog during initdb
plus all TOAST tables in the system. If wal_level=logical, then we
also include tables marked with the reloption user_catalog_table=true,
unless they're unlogged. This all seems a bit complex. Why not this:

IsSystemRelation() || || RelationIsUsedAsCatalogTable(relation)

And why not this?

IsCatalogRelation() || || RelationIsUsedAsCatalogTable(relation)

i.e. is it really necessary to include all TOAST tables, or does it
suffice to include TOAST tables of system catalogs? I bet you're
going to tell me that we don't know which TOAST tables pertain to
user-catalog tables, and thus must include them all. Ugh.

+       /*
+        * It's important *not* to track decoding tasks here because
+        * snapbuild.c uses ->oldestRunningXid to manage its xmin. If it
+        * were to be included here the initial value could never
+        * increase.
+        */

This is not clear, and it uses the " ->member" syntax which I find
confusing and inelegant.

lazy_vacuum_rel() takes the relation as an argument, so why does it
need the to caller to compute IsSystemRelation(onerel) ||
RelationIsAccessibleInLogicalDecoding(onerel)?

Header comment for ReplicationSlotDropAcquired() is bogus.

ReplicationSlotDropAcquired() can easily avoid using a "goto" with a
short else block. I'd suggest if rename() == 0 then fsync() else
ereport().

+ * GetOldestSafeDecodingTransactionId -- lowest xid not affected by vacuum

It seems to me that this is the lowest XID known not to have been
pruned, whether by vacuum or otherwise.

+       /* ----
+        * This is a bit tricky: We need to determine a safe xmin
horizon to start
+        * decoding from, to avoid starting from a running xacts
record referring
+        * to xids whose rows have been vacuumed or pruned
+        * already. GetOldestSafeDecodingTransactionId() returns such
a value, but
+        * without further interlock it's return value might
immediately be out of
+        * date.
+        *
+        * So we have to acquire the ProcArrayLock to prevent computation of new
+        * xmin horizons by other backends, get the safe decoding xid,
and inform
+        * the slot machinery about the new limit. Once that's done the
+        * ProcArrayLock can be be released as the slot machinery now is
+        * protecting against vacuum.
+        * ----
+        */

I can't claim to be very excited about this. I'm assuming you've
spent a lot of time thinking about ways to avoid this and utterly
failed to come up with any reasonable alternative, but let me take a
shot. Suppose we take ProcArrayLock in exclusive mode and compute the
oldest running XID, install it as our xmin, and then release
ProcArrayLock. At that point, nobody else can compute an oldest-xmin
value that precedes that value, so we can take our time installing
that value as the slot's xmin, without needing to hold a lock
meanwhile.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#103Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#102)
Re: Changeset Extraction v7.7

Hi,

On 2014-02-24 17:06:53 -0500, Robert Haas wrote:

I still think pg_create_logical_replication_slot should be in slotfuncs.c.

Ok, I don't feel too strongly, so I can change it. I wanted to keep
logical/ stuff out of slotfuncs.c, but there's not really a strong
reason for that.

I don't think the completely-unsecured directory operations in
test_decoding_regsupport.c are acceptable. Tom fought tooth and nail
to make sure that similar capabilities in adminpack carried meaningful
security restrictions.

I actually thought they'd be too ugly to live and we'd remove them
pre-commit.

There's no security problem though afaics, since they aren't actually
created, and you need to be superuser to create C functions.

/*
+        * Check whether there are, possibly unconnected, logical
slots that refer
+        * to the to-be-dropped database. The database lock we are holding
+        * prevents the creation of new slots using the database.
+        */
+       if (ReplicationSlotsCountDBSlots(db_id, &nslots, &nslots_active))
+               ereport(ERROR,
+                               (errcode(ERRCODE_OBJECT_IN_USE),
+                                errmsg("database \"%s\" is used in a
logical decoding slot",
+                                               dbname),
+                                errdetail("There are %d slot(s), %d
of them active",
+                                                  nslots, nslots_active)));

What are you going to do when we get around to supporting this on a
standby? Whatever the answer is, maybe add a TODO comment.

I think it should actually mostly work out, anybody actively connected
to a slot will be kicked of (normal HS mechanisms)... But the slot would
currently live on which obviously isn't nice.

Will add TODO.

+       /*
+        * GetRunningTransactionData() acquired ProcArrayLock, we must release
+        * it. We can do that before inserting the WAL record because
+        * ProcArrayApplyRecoveryInfo can recheck the commit status using the
+        * clog. If we're doing logical replication we can't do that though, so
+        * hold the lock for a moment longer.
+        */
+       if (wal_level < WAL_LEVEL_LOGICAL)
+               LWLockRelease(ProcArrayLock);
+
recptr = LogCurrentRunningXacts(running);
+       /* Release lock if we kept it longer ... */
+       if (wal_level >= WAL_LEVEL_LOGICAL)
+               LWLockRelease(ProcArrayLock);
+

This seems unfortunate. The comment should clearly explain why it's necessary.

There's another (existing) comment ontop of the function giving a bit
more context, but I'll expand.

I'd actually prefer to remove that special case alltogether, I don't
have much trust in those codepaths for HS... But that's not an argument
I want to fight out right nwo.

-       heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+       if (IsSystemRelation(scan->rs_rd)
+               || RelationIsAccessibleInLogicalDecoding(scan->rs_rd))
+               heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+       else
+               heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalDataXmin);

Instead of changing the callers of heap_page_prune_opt() in this way,
I think it might be better to change heap_page_prune_opt() to take
only the first two of its current three parameters; everybody's just
passing RecentGlobalXmin right now anyway.

Sounds like a plan.

-               if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval ||
forceSyncCommit)
+               if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval ||
forceSyncCommit ||
+                       XLogLogicalInfoActive())

Mmph. Is this really necessary? If so, why? The comments could elucidate.

We could get rid of it by (optionally) adding information about the
database oid to compact commit, but that'd increase the size of the
record.

+ bool fail_softly = slot->data.persistency == RS_EPHEMERAL;

This should be contingent on whether we're being called in the error
pathway, not the slot type. I think you should pass a bool.

Why? I had it that way at first, but for persistent slots this won't be
called in error pathways as we won't drop there.

There are a bunch of places where you're testing IsSystemRelation() ||
RelationIsAccessibleInLogicalDecoding(). Maybe we need a macro
encapsulating that test, with a name chose to explain the point of it.

Sounds like a idea.

It seems to be indicating, roughly, whether the relation should
participate in RecentGlobalXmin or RecentGlobalDataXmin. But is there
any point at all of separating those when !XLogLogicalInfoActive()?
The test expands to:

IsSystemRelation() || (XLogLogicalInfoActive() &&
RelationNeedsWAL(relation) && (IsCatalogRelation(relation) ||
RelationIsUsedAsCatalogTable(relation)))

So basically this is all tables created in pg_catalog during initdb
plus all TOAST tables in the system. If wal_level=logical, then we
also include tables marked with the reloption user_catalog_table=true,
unless they're unlogged. This all seems a bit complex. Why not this:

IsSystemRelation() || || RelationIsUsedAsCatalogTable(relation)

Because that'd possibly retain too much when !XLogLogicalInfoActive(),
there's no need to look for RelationIsUsedAsCatalogTable() for those. We
could decide not to care?

And why not this?

IsCatalogRelation() || || RelationIsUsedAsCatalogTable(relation)

i.e. is it really necessary to include all TOAST tables, or does it
suffice to include TOAST tables of system catalogs?

The latter would suffice.

I bet you're
going to tell me that we don't know which TOAST tables pertain to
user-catalog tables, and thus must include them all. Ugh.

Not sure offhand, but if that's an issue, it needs to be fixed when
setting the option. I dimly remember thinking about it, and convincing
myself it's not an issue.

+ * GetOldestSafeDecodingTransactionId -- lowest xid not affected by vacuum

It seems to me that this is the lowest XID known not to have been
pruned, whether by vacuum or otherwise.

Hm, yes, mentioning pruning make sense.

+       /* ----
+        * This is a bit tricky: We need to determine a safe xmin
horizon to start
+        * decoding from, to avoid starting from a running xacts
record referring
+        * to xids whose rows have been vacuumed or pruned
+        * already. GetOldestSafeDecodingTransactionId() returns such
a value, but
+        * without further interlock it's return value might
immediately be out of
+        * date.
+        *
+        * So we have to acquire the ProcArrayLock to prevent computation of new
+        * xmin horizons by other backends, get the safe decoding xid,
and inform
+        * the slot machinery about the new limit. Once that's done the
+        * ProcArrayLock can be be released as the slot machinery now is
+        * protecting against vacuum.
+        * ----
+        */

I can't claim to be very excited about this.

Because of the already_locked parameters, or any wider concerns?

I'm assuming you've
spent a lot of time thinking about ways to avoid this and utterly
failed to come up with any reasonable alternative, but let me take a
shot. Suppose we take ProcArrayLock in exclusive mode and compute the
oldest running XID, install it as our xmin, and then release
ProcArrayLock. At that point, nobody else can compute an oldest-xmin
value that precedes that value, so we can take our time installing
that value as the slot's xmin, without needing to hold a lock
meanwhile.

I actually had it that way for a while, but what if the backend already
has a xmin set? Then we need to reason about whether the xmin is newer,
restore it afterwards and such. That doesn't seem nice.

Since the time holding the lock isn't long (we're just iterating over
the slots), I am not too worried?

Thanks for the review! Will address ASAP.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#104Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#103)
Re: Changeset Extraction v7.7

On Mon, Feb 24, 2014 at 6:16 PM, Andres Freund <andres@2ndquadrant.com> wrote:

I actually thought they'd be too ugly to live and we'd remove them
pre-commit.

Might be getting to be about that time, then.

-               if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval ||
forceSyncCommit)
+               if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval ||
forceSyncCommit ||
+                       XLogLogicalInfoActive())

Mmph. Is this really necessary? If so, why? The comments could elucidate.

We could get rid of it by (optionally) adding information about the
database oid to compact commit, but that'd increase the size of the
record.

So why do we need the database OID?

+ bool fail_softly = slot->data.persistency == RS_EPHEMERAL;

This should be contingent on whether we're being called in the error
pathway, not the slot type. I think you should pass a bool.

Why? I had it that way at first, but for persistent slots this won't be
called in error pathways as we won't drop there.

I was thinking more the reverse - that a non-persistent slot might be
dropped in a non-error pathway.

It seems to be indicating, roughly, whether the relation should
participate in RecentGlobalXmin or RecentGlobalDataXmin. But is there
any point at all of separating those when !XLogLogicalInfoActive()?
The test expands to:

IsSystemRelation() || (XLogLogicalInfoActive() &&
RelationNeedsWAL(relation) && (IsCatalogRelation(relation) ||
RelationIsUsedAsCatalogTable(relation)))

So basically this is all tables created in pg_catalog during initdb
plus all TOAST tables in the system. If wal_level=logical, then we
also include tables marked with the reloption user_catalog_table=true,
unless they're unlogged. This all seems a bit complex. Why not this:

IsSystemRelation() || || RelationIsUsedAsCatalogTable(relation)

Because that'd possibly retain too much when !XLogLogicalInfoActive(),
there's no need to look for RelationIsUsedAsCatalogTable() for those. We
could decide not to care?

But when !XLogLogicalInfoActive() I think we could just make this
always false, right? I mean, if PROC_IN_LOGICAL_DECODING is never
going to be set, the values are always going to be the same anyway.
I think.

+       /* ----
+        * This is a bit tricky: We need to determine a safe xmin
horizon to start
+        * decoding from, to avoid starting from a running xacts
record referring
+        * to xids whose rows have been vacuumed or pruned
+        * already. GetOldestSafeDecodingTransactionId() returns such
a value, but
+        * without further interlock it's return value might
immediately be out of
+        * date.
+        *
+        * So we have to acquire the ProcArrayLock to prevent computation of new
+        * xmin horizons by other backends, get the safe decoding xid,
and inform
+        * the slot machinery about the new limit. Once that's done the
+        * ProcArrayLock can be be released as the slot machinery now is
+        * protecting against vacuum.
+        * ----
+        */

I can't claim to be very excited about this.

Because of the already_locked parameters, or any wider concerns?

Passing down already_locked through several layers is kind of ugly,
but also, holding ProcArrayLock more is sad. That is not a
lightly-contended lock.

I'm assuming you've
spent a lot of time thinking about ways to avoid this and utterly
failed to come up with any reasonable alternative, but let me take a
shot. Suppose we take ProcArrayLock in exclusive mode and compute the
oldest running XID, install it as our xmin, and then release
ProcArrayLock. At that point, nobody else can compute an oldest-xmin
value that precedes that value, so we can take our time installing
that value as the slot's xmin, without needing to hold a lock
meanwhile.

I actually had it that way for a while, but what if the backend already
has a xmin set? Then we need to reason about whether the xmin is newer,
restore it afterwards and such. That doesn't seem nice.

It's not too far removed from the problem snapmgr.c is already
designed to solve, though, is it?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#105Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#104)
Re: Changeset Extraction v7.7

Hi,

On 2014-02-25 13:47:49 -0500, Robert Haas wrote:

On Mon, Feb 24, 2014 at 6:16 PM, Andres Freund <andres@2ndquadrant.com> wrote:

I actually thought they'd be too ugly to live and we'd remove them
pre-commit.

Might be getting to be about that time, then.

I want to leave them in until the slot semantics aren't going to change
anymore, they are pretty useful for testing that. But I'll separate them out
into a separate commit again.

-               if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval ||
forceSyncCommit)
+               if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval ||
forceSyncCommit ||
+                       XLogLogicalInfoActive())

Mmph. Is this really necessary? If so, why? The comments could elucidate.

We could get rid of it by (optionally) adding information about the
database oid to compact commit, but that'd increase the size of the
record.

So why do we need the database OID?

To ignore commits from other databases. Since we don't decode changes
from other databases, it's really confusing (and pointless overhead) to
see transactions from there.

+ bool fail_softly = slot->data.persistency == RS_EPHEMERAL;

This should be contingent on whether we're being called in the error
pathway, not the slot type. I think you should pass a bool.

Why? I had it that way at first, but for persistent slots this won't be
called in error pathways as we won't drop there.

I was thinking more the reverse - that a non-persistent slot might be
dropped in a non-error pathway.

Well, currently EPHEMERAL slots are documented to be dropped at release
since that's what changeset extraction (and possibly basebackup and
receivexlog) need afaics. You'd prefer DROP_ON_ERROR semantics?

It seems to be indicating, roughly, whether the relation should
participate in RecentGlobalXmin or RecentGlobalDataXmin. But is there
any point at all of separating those when !XLogLogicalInfoActive()?
The test expands to:

IsSystemRelation() || (XLogLogicalInfoActive() &&
RelationNeedsWAL(relation) && (IsCatalogRelation(relation) ||
RelationIsUsedAsCatalogTable(relation)))

So basically this is all tables created in pg_catalog during initdb
plus all TOAST tables in the system. If wal_level=logical, then we
also include tables marked with the reloption user_catalog_table=true,
unless they're unlogged. This all seems a bit complex. Why not this:

IsSystemRelation() || || RelationIsUsedAsCatalogTable(relation)

Because that'd possibly retain too much when !XLogLogicalInfoActive(),
there's no need to look for RelationIsUsedAsCatalogTable() for those. We
could decide not to care?

But when !XLogLogicalInfoActive() I think we could just make this
always false, right? I mean, if PROC_IN_LOGICAL_DECODING is never
going to be set, the values are always going to be the same anyway.
I think.

It seems confusing and bug-prone to use the wrong horizon variable just
because right now they'd be the same if wal_level < logical.

I can't claim to be very excited about this.

Because of the already_locked parameters, or any wider concerns?

Passing down already_locked through several layers is kind of ugly,
but also, holding ProcArrayLock more is sad. That is not a
lightly-contended lock.

Absolutely true, but this is very far from a operation that will be
frequent enough to matter. Creating a slot so frequently that a lock on
the procarray hold while iterating the slot array matters, will be
painful long before the contention on that is the problem.

I'm assuming you've
spent a lot of time thinking about ways to avoid this and utterly
failed to come up with any reasonable alternative, but let me take a
shot. Suppose we take ProcArrayLock in exclusive mode and compute the
oldest running XID, install it as our xmin, and then release
ProcArrayLock. At that point, nobody else can compute an oldest-xmin
value that precedes that value, so we can take our time installing
that value as the slot's xmin, without needing to hold a lock
meanwhile.

I actually had it that way for a while, but what if the backend already
has a xmin set? Then we need to reason about whether the xmin is newer,
restore it afterwards and such. That doesn't seem nice.

It's not too far removed from the problem snapmgr.c is already
designed to solve, though, is it?

Hm, I don't immediately see how it would fit in there. PgXact->xmin is
set by procarray.c, all snapmgr does is reset it. And there's no logic
about resetting it back to higher values and such.

I'll ponder on getting rid of this, but I am not of too high hopes.

Thanks,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#106Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#102)
1 attachment(s)
Re: Changeset Extraction v7.7

On 2014-02-24 17:06:53 -0500, Robert Haas wrote:

-       heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+       if (IsSystemRelation(scan->rs_rd)
+               || RelationIsAccessibleInLogicalDecoding(scan->rs_rd))
+               heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+       else
+               heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalDataXmin);

Instead of changing the callers of heap_page_prune_opt() in this way,
I think it might be better to change heap_page_prune_opt() to take
only the first two of its current three parameters; everybody's just
passing RecentGlobalXmin right now anyway.

I've changed stuff this way, and it indeed looks better.

I am wondering about the related situation of GetOldestXmin()
callers. There's a fair bit of duplicated logic in the callers, before
but especially after this patchset. What about adding 'Relation rel'
parameter instead of `allDbs' and `systable'? That keeps the logic
centralized and there's been a fair amount of talk about vacuum
optimizations that could also use it.
It's a bit sad that that requires including rel.h from procarray.h...

What do you think? Isolated patch attached.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-fixup-wal_decoding-Introduce-logical-changeset-extra.patchtext/x-patch; charset=us-asciiDownload
>From b23fe717c699ad5e7cac217c3a5725b57c722ff2 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 26 Feb 2014 18:23:55 +0100
Subject: [PATCH] fixup! wal_decoding: Introduce logical changeset extraction.

Centralize knowledge from GetOldestXmin() callers into GetOldestXmin()
itself.
---
 src/backend/access/transam/xlog.c     |  4 +--
 src/backend/catalog/index.c           | 12 +--------
 src/backend/commands/analyze.c        |  4 +--
 src/backend/commands/cluster.c        |  4 +--
 src/backend/commands/vacuum.c         |  9 +++----
 src/backend/commands/vacuumlazy.c     |  6 ++---
 src/backend/replication/walreceiver.c |  2 +-
 src/backend/storage/ipc/procarray.c   | 50 +++++++++++++++++++++++------------
 src/include/commands/vacuum.h         |  4 +--
 src/include/storage/procarray.h       |  3 ++-
 10 files changed, 49 insertions(+), 49 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b6b2cd4..9f48fa5 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -8619,7 +8619,7 @@ CreateCheckPoint(int flags)
 	 * StartupSUBTRANS hasn't been called yet.
 	 */
 	if (!RecoveryInProgress())
-		TruncateSUBTRANS(GetOldestXmin(true, false, true));
+		TruncateSUBTRANS(GetOldestXmin(NULL, false));
 
 	/* Real work is done, but log and update stats before releasing lock. */
 	LogCheckpointEnd(false);
@@ -8997,7 +8997,7 @@ CreateRestartPoint(int flags)
 	 * this because StartupSUBTRANS hasn't been called yet.
 	 */
 	if (EnableHotStandby)
-		TruncateSUBTRANS(GetOldestXmin(true, false, true));
+		TruncateSUBTRANS(GetOldestXmin(NULL, false));
 
 	/* Real work is done, but log and update before releasing lock. */
 	LogCheckpointEnd(true);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 8c1803e..877d767 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2154,19 +2154,9 @@ IndexBuildHeapScan(Relation heapRelation,
 	}
 	else
 	{
-		/*
-		 * We can ignore a) pegged xmins b) shared relations if we don't scan
-		 * something acting as a catalog.
-		 */
-		bool include_systables =
-			IsCatalogRelation(heapRelation) ||
-			RelationIsAccessibleInLogicalDecoding(heapRelation);
-
 		snapshot = SnapshotAny;
 		/* okay to ignore lazy VACUUMs here */
-		OldestXmin = GetOldestXmin(heapRelation->rd_rel->relisshared,
-								   true,
-								   include_systables);
+		OldestXmin = GetOldestXmin(heapRelation, true);
 	}
 
 	scan = heap_beginscan_strat(heapRelation,	/* relation */
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index fe569f5..a04adea 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1082,9 +1082,7 @@ acquire_sample_rows(Relation onerel, int elevel,
 	totalblocks = RelationGetNumberOfBlocks(onerel);
 
 	/* Need a cutoff xmin for HeapTupleSatisfiesVacuum */
-	OldestXmin = GetOldestXmin(onerel->rd_rel->relisshared, true,
-							   IsCatalogRelation(onerel) ||
-							   RelationIsAccessibleInLogicalDecoding(onerel));
+	OldestXmin = GetOldestXmin(onerel, true);
 
 	/* Prepare for sampling block numbers */
 	BlockSampler_Init(&bs, totalblocks, targrows);
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index fc5c013..b6b40e7 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -850,9 +850,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
 	 * Since we're going to rewrite the whole table anyway, there's no reason
 	 * not to be aggressive about this.
 	 */
-	vacuum_set_xid_limits(0, 0, 0, 0, OldHeap->rd_rel->relisshared,
-						  IsCatalogRelation(OldHeap)
-						  || RelationIsAccessibleInLogicalDecoding(OldHeap),
+	vacuum_set_xid_limits(OldHeap, 0, 0, 0, 0,
 						  &OldestXmin, &FreezeXid, NULL, &MultiXactCutoff,
 						  NULL);
 
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index ceeac77..ded1841 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -398,12 +398,11 @@ get_rel_oids(Oid relid, const RangeVar *vacrel)
  * not interested.
  */
 void
-vacuum_set_xid_limits(int freeze_min_age,
+vacuum_set_xid_limits(Relation rel,
+					  int freeze_min_age,
 					  int freeze_table_age,
 					  int multixact_freeze_min_age,
 					  int multixact_freeze_table_age,
-					  bool sharedRel,
-					  bool catalogRel,
 					  TransactionId *oldestXmin,
 					  TransactionId *freezeLimit,
 					  TransactionId *xidFullScanLimit,
@@ -426,7 +425,7 @@ vacuum_set_xid_limits(int freeze_min_age,
 	 * working on a particular table at any time, and that each vacuum is
 	 * always an independent transaction.
 	 */
-	*oldestXmin = GetOldestXmin(sharedRel, true, catalogRel);
+	*oldestXmin = GetOldestXmin(rel, true);
 
 	Assert(TransactionIdIsNormal(*oldestXmin));
 
@@ -796,7 +795,7 @@ vac_update_datfrozenxid(void)
 	 * committed pg_class entries for new tables; see AddNewRelationTuple().
 	 * So we cannot produce a wrong minimum by starting with this.
 	 */
-	newFrozenXid = GetOldestXmin(true, true, true);
+	newFrozenXid = GetOldestXmin(NULL, true);
 
 	/*
 	 * Similarly, initialize the MultiXact "min" with the value that would be
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index bffe153..d5db917 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -205,12 +205,10 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
 
 	vac_strategy = bstrategy;
 
-	vacuum_set_xid_limits(vacstmt->freeze_min_age, vacstmt->freeze_table_age,
+	vacuum_set_xid_limits(onerel,
+						  vacstmt->freeze_min_age, vacstmt->freeze_table_age,
 						  vacstmt->multixact_freeze_min_age,
 						  vacstmt->multixact_freeze_table_age,
-						  onerel->rd_rel->relisshared,
-						  IsCatalogRelation(onerel)
-						  || RelationIsAccessibleInLogicalDecoding(onerel),
 						  &OldestXmin, &FreezeLimit, &xidFullScanLimit,
 						  &MultiXactCutoff, &mxactFullScanLimit);
 
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 3d67333..43db108 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -1147,7 +1147,7 @@ XLogWalRcvSendHSFeedback(bool immed)
 	 * everything else has been checked.
 	 */
 	if (hot_standby_feedback)
-		xmin = GetOldestXmin(true, false, true);
+		xmin = GetOldestXmin(NULL, false);
 	else
 		xmin = InvalidTransactionId;
 
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 101d47f..060d5f0 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -50,6 +50,7 @@
 #include "access/transam.h"
 #include "access/xact.h"
 #include "access/twophase.h"
+#include "catalog/catalog.h"
 #include "miscadmin.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
@@ -1110,21 +1111,23 @@ TransactionIdIsActive(TransactionId xid)
  * GetOldestXmin -- returns oldest transaction that was running
  *					when any current transaction was started.
  *
- * If allDbs is TRUE then all backends are considered; if allDbs is FALSE
- * then only backends running in my own database are considered.
+ * If rel is NULL or a shared relation, all backends are considered, otherwise
+ * only backends running in this database are considered.
  *
  * If ignoreVacuum is TRUE then backends with the PROC_IN_VACUUM flag set are
  * ignored.
  *
- * This is used by VACUUM to decide which deleted tuples must be preserved
- * in a table.	allDbs = TRUE is needed for shared relations, but allDbs =
- * FALSE is sufficient for non-shared relations, since only backends in my
- * own database could ever see the tuples in them.	Also, we can ignore
- * concurrently running lazy VACUUMs because (a) they must be working on other
- * tables, and (b) they don't need to do snapshot-based lookups.
+ * This is used by VACUUM to decide which deleted tuples must be preserved in
+ * the passed in table. For shared relations backends in all databases must be
+ * considered, but for non-shared non-shared relations that's not required,
+ * since only backends in my own database could ever see the tuples in
+ * them. Also, we can ignore concurrently running lazy VACUUMs because (a)
+ * they must be working on other tables, and (b) they don't need to do
+ * snapshot-based lookups.
  *
- * This is also used to determine where to truncate pg_subtrans.  allDbs
- * must be TRUE for that case, and ignoreVacuum FALSE.
+ * This is also used to determine where to truncate pg_subtrans.  For that
+ * backends in all databases have to be considered, so rel = NULL has to be
+ * passed in.
  *
  * Note: we include all currently running xids in the set of considered xids.
  * This ensures that if a just-started xact has not yet set its snapshot,
@@ -1135,7 +1138,7 @@ TransactionIdIsActive(TransactionId xid)
  * backwards on repeated calls. The calculated value is conservative, so that
  * anything older is definitely not considered as running by anyone anymore,
  * but the exact value calculated depends on a number of things. For example,
- * if allDbs is FALSE and there are no transactions running in the current
+ * if rel = NULL and there are no transactions running in the current
  * database, GetOldestXmin() returns latestCompletedXid. If a transaction
  * begins after that, its xmin will include in-progress transactions in other
  * databases that started earlier, so another call will return a lower value.
@@ -1154,14 +1157,23 @@ TransactionIdIsActive(TransactionId xid)
  * GetOldestXmin() move backwards, with no consequences for data integrity.
  */
 TransactionId
-GetOldestXmin(bool allDbs, bool ignoreVacuum, bool systable)
+GetOldestXmin(Relation rel, bool ignoreVacuum)
 {
 	ProcArrayStruct *arrayP = procArray;
 	TransactionId result;
 	int			index;
+	bool		allDbs;
+
 	volatile TransactionId replication_slot_xmin = InvalidTransactionId;
 	volatile TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
 
+	/*
+	 * If we're not computing a relation specific limit, or if a shared
+	 * relation has been passed in, backends in all databases have to be
+	 * considered.
+	 */
+	allDbs = rel == NULL || rel->rd_rel->relisshared;
+
 	/* Cannot look for individual databases during recovery */
 	Assert(allDbs || !RecoveryInProgress());
 
@@ -1184,8 +1196,8 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum, bool systable)
 		volatile PGXACT *pgxact = &allPgXact[pgprocno];
 
 		/*
-		 * Backend is doing logical decoding which manages xmin
-		 * separately, check below.
+		 * Backend is doing logical decoding which manages xmin separately,
+		 * check below.
 		 */
 		if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING)
 			continue;
@@ -1271,10 +1283,14 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum, bool systable)
 		result = replication_slot_xmin;
 
 	/*
-	 * after locks are released and defer_cleanup_age has been applied, check
-	 * whether we need to back up further to make logical decoding possible.
+	 * After locks have been released and defer_cleanup_age has been applied,
+	 * check whether we need to back up further to make logical decoding
+	 * possible. We need to do so if we're computing the global limit (rel =
+	 * NULL) or if the passed relation is a catalog relation of some kind.
 	 */
-	if (systable && TransactionIdIsValid(replication_slot_catalog_xmin) &&
+	if ((rel == NULL ||
+		 RelationIsAccessibleInLogicalDecoding(rel)) &&
+		TransactionIdIsValid(replication_slot_catalog_xmin) &&
 		NormalTransactionIdPrecedes(replication_slot_catalog_xmin, result))
 		result = replication_slot_catalog_xmin;
 
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 311098a..058dc5f 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -157,10 +157,10 @@ extern void vac_update_relstats(Relation relation,
 					bool hasindex,
 					TransactionId frozenxid,
 					MultiXactId minmulti);
-extern void vacuum_set_xid_limits(int freeze_min_age, int freeze_table_age,
+extern void vacuum_set_xid_limits(Relation rel,
+					  int freeze_min_age, int freeze_table_age,
 					  int multixact_freeze_min_age,
 					  int multixact_freeze_table_age,
-					  bool sharedRel, bool catalogRel,
 					  TransactionId *oldestXmin,
 					  TransactionId *freezeLimit,
 					  TransactionId *xidFullScanLimit,
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index 284d746..c43fd81 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -15,6 +15,7 @@
 #define PROCARRAY_H
 
 #include "storage/standby.h"
+#include "utils/rel.h"
 #include "utils/snapshot.h"
 
 
@@ -50,7 +51,7 @@ extern RunningTransactions GetRunningTransactionData(void);
 
 extern bool TransactionIdIsInProgress(TransactionId xid);
 extern bool TransactionIdIsActive(TransactionId xid);
-extern TransactionId GetOldestXmin(bool allDbs, bool ignoreVacuum, bool systable);
+extern TransactionId GetOldestXmin(Relation rel, bool ignoreVacuum);
 extern TransactionId GetOldestActiveTransactionId(void);
 extern TransactionId GetOldestSafeDecodingTransactionId(void);
 
-- 
1.8.5.rc2.dirty

#107Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Andres Freund (#106)
Re: Changeset Extraction v7.7

Andres Freund escribi�:

I am wondering about the related situation of GetOldestXmin()
callers. There's a fair bit of duplicated logic in the callers, before
but especially after this patchset. What about adding 'Relation rel'
parameter instead of `allDbs' and `systable'? That keeps the logic
centralized and there's been a fair amount of talk about vacuum
optimizations that could also use it.
It's a bit sad that that requires including rel.h from procarray.h...

relcache.h, not rel.h.

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#108Andres Freund
andres@2ndquadrant.com
In reply to: Alvaro Herrera (#107)
Re: Changeset Extraction v7.7

On 2014-02-26 15:30:55 -0300, Alvaro Herrera wrote:

Andres Freund escribió:

I am wondering about the related situation of GetOldestXmin()
callers. There's a fair bit of duplicated logic in the callers, before
but especially after this patchset. What about adding 'Relation rel'
parameter instead of `allDbs' and `systable'? That keeps the logic
centralized and there's been a fair amount of talk about vacuum
optimizations that could also use it.
It's a bit sad that that requires including rel.h from procarray.h...

relcache.h, not rel.h.

RelationData is declared in rel.h, not relcache.h, no?

Alternatively we could just forward declare it in the header...

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#109Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Andres Freund (#108)
Re: Changeset Extraction v7.7

Andres Freund escribi�:

On 2014-02-26 15:30:55 -0300, Alvaro Herrera wrote:

Andres Freund escribi�:

I am wondering about the related situation of GetOldestXmin()
callers. There's a fair bit of duplicated logic in the callers, before
but especially after this patchset. What about adding 'Relation rel'
parameter instead of `allDbs' and `systable'? That keeps the logic
centralized and there's been a fair amount of talk about vacuum
optimizations that could also use it.
It's a bit sad that that requires including rel.h from procarray.h...

relcache.h, not rel.h.

RelationData is declared in rel.h, not relcache.h, no?

Sure, but with your patch AFAICT procarray.h header only needs Relation,
which is declared in relcache.h.

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#110Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#106)
Re: Changeset Extraction v7.7

On Wed, Feb 26, 2014 at 12:29 PM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-24 17:06:53 -0500, Robert Haas wrote:

-       heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+       if (IsSystemRelation(scan->rs_rd)
+               || RelationIsAccessibleInLogicalDecoding(scan->rs_rd))
+               heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalXmin);
+       else
+               heap_page_prune_opt(scan->rs_rd, buffer, RecentGlobalDataXmin);

Instead of changing the callers of heap_page_prune_opt() in this way,
I think it might be better to change heap_page_prune_opt() to take
only the first two of its current three parameters; everybody's just
passing RecentGlobalXmin right now anyway.

I've changed stuff this way, and it indeed looks better.

I am wondering about the related situation of GetOldestXmin()
callers. There's a fair bit of duplicated logic in the callers, before
but especially after this patchset. What about adding 'Relation rel'
parameter instead of `allDbs' and `systable'? That keeps the logic
centralized and there's been a fair amount of talk about vacuum
optimizations that could also use it.
It's a bit sad that that requires including rel.h from procarray.h...

What do you think? Isolated patch attached.

Seems reasonable to me.

+ * considered, but for non-shared non-shared relations that's not required,

Duplicate word.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#111Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#101)
Re: Changeset Extraction v7.6.1

On 2014-02-24 12:50:03 -0500, Robert Haas wrote:

On Mon, Feb 24, 2014 at 9:48 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-15 17:29:04 -0500, Robert Haas wrote:

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

+       /*
+        * XXX: It's impolite to ignore our argument and keep decoding until the
+        * current position.
+        */

Eh, what?

So, the background here is that I was thinking of allowing to specify a
limit for the number of returned rows. For the sql interface that sounds
like a good idea. I am just not so sure anymore that allowing to specify
a LSN as a limit is sufficient. Maybe simply allow to limit the number
of changes and check everytime a transaction has been replayed?

The last idea there seems like pretty sound, but ...

It's all trivial codewise, I am just wondering about the interface most
users would want.

...I can't swear it meets this criterion.

So, it's now:
CREATE OR REPLACE FUNCTION pg_logical_slot_get_changes(
IN slotname name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
OUT location pg_lsn, OUT xid xid, OUT data text)
RETURNS SETOF RECORD
LANGUAGE INTERNAL
VOLATILE ROWS 1000 COST 1000
AS 'pg_logical_slot_get_changes';

if nonnull upto_lsn allows limiting based on the lsn, similar with
upto_nchanges.

Makes sense?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#112Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#111)
Re: Changeset Extraction v7.6.1

On Thu, Feb 27, 2014 at 11:06 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-24 12:50:03 -0500, Robert Haas wrote:

On Mon, Feb 24, 2014 at 9:48 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-15 17:29:04 -0500, Robert Haas wrote:

On Fri, Feb 14, 2014 at 4:55 AM, Andres Freund <andres@2ndquadrant.com> wrote:

+       /*
+        * XXX: It's impolite to ignore our argument and keep decoding until the
+        * current position.
+        */

Eh, what?

So, the background here is that I was thinking of allowing to specify a
limit for the number of returned rows. For the sql interface that sounds
like a good idea. I am just not so sure anymore that allowing to specify
a LSN as a limit is sufficient. Maybe simply allow to limit the number
of changes and check everytime a transaction has been replayed?

The last idea there seems like pretty sound, but ...

It's all trivial codewise, I am just wondering about the interface most
users would want.

...I can't swear it meets this criterion.

So, it's now:
CREATE OR REPLACE FUNCTION pg_logical_slot_get_changes(
IN slotname name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
OUT location pg_lsn, OUT xid xid, OUT data text)
RETURNS SETOF RECORD
LANGUAGE INTERNAL
VOLATILE ROWS 1000 COST 1000
AS 'pg_logical_slot_get_changes';

if nonnull upto_lsn allows limiting based on the lsn, similar with
upto_nchanges.

Makes sense?

Time will tell, but it seems plausible to me.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#113Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#1)
Re: Changeset Extraction v7.8

Hi,

Attached you can find version 7.8 of this patcheset. Changes since 7.7
include:
* Signature changes of the SQL changeset SRFs to support limits based on
LSN and/or number of returned rows (pg_logical_slot_get_changes() et
al) and to make parameter passing optional (by adding a DEFAULT '{}'
to the variadic argument)
* heap_page_prune_opt() now decides itself which horizon to use,
removing a good amount of duplicated logic
* GetOldestXmin() now has a Relation parameter that can be NULL instead
of the former allDbs (existing in master) and systable (just this
branch) parameters, also removing code duplication.
* pg_create_logical_replication_slot() is now defined in slotfuncs.c
* a fair number of cosmetic and comment changes

The open issues that I know of are:
* do we modify struct SnapshotData to be polymorphic based on some tag
or move comments there?
* How/whether to change the exclusive lock on the ProcArrayLock in
CreateInitDecodingContext()

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#114Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#113)
6 attachment(s)
Re: Changeset Extraction v7.8

On 2014-02-27 17:56:08 +0100, Andres Freund wrote:

Hi,

Attached you can find version 7.8 of this patcheset. Changes since 7.7
include:

Hrmpf, prematurely hit send.

* Signature changes of the SQL changeset SRFs to support limits based on
LSN and/or number of returned rows (pg_logical_slot_get_changes() et
al) and to make parameter passing optional (by adding a DEFAULT '{}'
to the variadic argument)
* heap_page_prune_opt() now decides itself which horizon to use,
removing a good amount of duplicated logic
* GetOldestXmin() now has a Relation parameter that can be NULL instead
of the former allDbs (existing in master) and systable (just this
branch) parameters, also removing code duplication.
* pg_create_logical_replication_slot() is now defined in slotfuncs.c
* a fair number of cosmetic and comment changes

* the probably-not-committable slot changes are split of into an extra patch

The open issues that I know of are:
* do we modify struct SnapshotData to be polymorphic based on some tag
or move comments there?
* How/whether to change the exclusive lock on the ProcArrayLock in

As usual the the branch xlog-decoding-rebasing-remapping on
http://git.postgresql.org/gitweb/?p=users/andresfreund/postgres.git
contains the latest and greatest.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-wal_decoding-Introduce-logical-changeset-extraction.patch.gzapplication/x-patch-gzipDownload
0002-wal_decoding-logical-changeset-extraction-walsender-.patch.gzapplication/x-patch-gzipDownload
0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gzapplication/x-patch-gzipDownload
0004-wal_decoding-Documentation-for-replication-slots-and.patch.gzapplication/x-patch-gzipDownload
�MkS0004-wal_decoding-Documentation-for-replication-slots-and.patch�<�S�F���W��U��`��a�0�$�2L��R)�-�q/���87�����n�d����j��\�`I�������1M�B���r������v�����NwW��za?����+�R��OI,n�D��D�{@���n������8LU&>���Cq(��{�T���N��VNe�NKl��������Ao���/6��nw���]��������G��z��x��]��$����8M�b��\�5LR��I����$�,`E#��L�B=�����Je�-q�J}/��J�j��,�����E�V�����`+K���q���(��:x%��7����oQ��_�&v���������Tkl�_���"f���^�L__�$��{�Q���)&i�'A5
��m�"U�-�*��� R��fM��T�^����������ea%�}����'�@:�T�4��77�QwD�"�7��R�1NB���������J��C�n��\��5X�pE��z������^����'A��J�Y�^B,���������k#����"Vi���#�&>����T	��k��aH��8|��H�*��f9�n�h{����������x���B<�`�l�.���x���n�
���vh��9�J�'�^����
�N�a�E�����IT���p��w�������:�En��y��o����L�rd����LU(R�"H@C�0G�"�����	 ;�3"�	�.2�@���"R���4sc�Nm1=����5=���A�h@��b�6,��Cd�_��	�����6L*S�v-������}`�C���Q�fv����,�f��nk�����y�*Vy������D!�C�g,�2g6 ��J�1�E��)U�Ii1�����/�J�@�1�I�8yT��_��5,�PZp�)��TD�HSM��%�lb��w��v��9�	S��O[%,8�]�1P� �$� ��,Wc�T�R�Z �`�s��wQ6OMB	�C/,�K{{�����
�<��'���16���N������[�z�B��h���"�mu�f���H��������n#m���]��OH��\�`�N��z���
�-���-���`�S=�@�f��)A�r`��M%B�bo��_/xz��r�J��"EU!�N�=��X�LLT
L=6����@H���mK��C�f�i����~p�C���D���}
v���IZv!�P�h��3��XGt���o������G�&n@HK���&�c��Ukp�>���_�������o(}Ti;��+A����#9Er����mi)��:�w� �8��C@�,�@�����~D�F��$r\E_y����@Q1
�Q&��~�Y	*34�2Rm`J�����_G(���Y"���0#8�2D�'�K�83<D��R�N-�_���(��N�Q��3h6l�a��,#O����@�z!�Pl���>��k5��� @����L(
X*-P�����P�d<�=:�|sv}{�e�[���b��#r	p�"��\������
4��g�~"��el�uzvq�����k9{�i�J�����'@�L$�a���`-3�����@/�����h�\����g���������������������yD�c��co>;��j�h�P(�
���%��-G��/�6&X�
��4��*z1�i?�<�P��G�b�@�D���I'V�m�:� g�F�#�) �i1I�L�<�h'���X�����W����S]��d�������k�.	����3`��<��6Z������H��Lc�`%O�����W��{�!9t�����+0?�!�c���E�Q����1�_u�`s9�F�.�eGQV@/�����
���Iq3<��C."����b����MX6f�"��"����+�c�|�1�����?�w���M�eg`R.�s�m���?F��1�����`�=,�4���6�a��n���D��@�.��3� m�Y}���?�(��O'�o*Mhk%��S�D����_�����4>X�l7���z5��L}�$��.*���[f3$@
�M�Y[���$�����
�M���|�1�)�X�H�ah���D����P��%�����xp�yt���HVn+0�w�!A�������_<�>��y/�*��3A=��7��PQ~g
��r����4����8K�&��c��|`_U�N����;x���J�I4j�-��+�eSpRNn�X�/?!����5�����Md�:���/�0�	\�#~��������
E6g���Y�W#P���%�h���KK��!G{-UX4��e6X����5ixC�d��L����0��O�|��0�fb�p^��M@�[�7z�{�?�-fuwvy$�[|�4�0�,�<��}-'��K
�����A��lww�Qv*������}����!�q��}��.�zG����P�o�����LH�cg41��/�/�_�w��ne��_sd��AQ	�X`�%hF9M ������8���,JNO�E���2��Q.��h��f��D�����Y��c��>u�UQ�
��t����z���p���g�n��uw�v����O��o����<�w�f40���k���[��i5�4@X���� S����8������*�8on/�
��
���������)���o��3Q���L��Yl���-�q���c����r��)���Dvp�^�!]�����g�_�����emWm����������������w��u���	89�W�A��M��$��E����!�+��������~����n��e�S!�NI��% K`�g}g�&�r��"W2����/Ndf
��E��x�U
l����a���
�tQ�v�����'��'���U2�u�S�Z������7���n����Nw{���XD�k5V���5�4��
3��F	��Q���h�DhO8��$��CR`���S���4�,�]�
_�2��y�ys��weG]j���r��pr����9��'��������+?Pt��eS0q�HE�0�(���/�1���6����	S��*��m�����us�,0���F��<|�)u�����[����&Y1�Ku�T�������P���E]������Dm�Rd��P���v��x�����:���h�;���
�b�_����/��*�Y�\F������;!�1k9y�FP^,&g9�p��GK�&���_�_P�8I�L��Z���
/�������X�*V,K\����>D#:l��S����-�u��.��t�����v6�� ��D�����$��)��!6���
k�IqMR��p.wb\����s�2��������hVQp����S��~���	U�f��)����=
��	u�������K����Y��w0mA������$E�N����k�X�l�0�*�rd��3��a�V&]S�,�X��_'�����]�C6~0������87�=�9�?���-��
0oHI!
����j3w���"mk�	0��5&^,[X��e�$��8e��#��)���Ry��/���"�:� �	�����@�H�B3Ax�AT�b��#�!t���l�$����V��(~`>UIZ|��BQ����m��&^�P=P��LJjQT�����i��#��.I����~�[~�o�gNK��#5�hTUz���Zk���A�d�TK�R����MQ�X�x�*g��K$��r��]�����$DO��l���Pu���>���3�eOq�6�\HGD�(������uG�(�N�#���,���1��6(K�s0'�m�l�u��RO�/�Z�}�1eJ��S|�VU\�l�aXI{��|*�\�'�[*S�C���8T��?_�A,���)F|� ��:��c�^?P$�kV�wS�q@�F=e��X*Y��9���p�b�Sn
w�+��n<|�e��N�������!���orD	5c�����B��m�#����}b[j����be��4X����--�S\��s� ���;�H���8<b�\��,�#��S�:Qa��r�Vn��|e0\��
�a��~���F2�m���U��!��s"V?�)��V�r������Ji�����0� I#)�.�U�����S�v����4��)2���	���y-0�
`���J�@�E�&�s�s���M��k�@b�Ql�����?0���Q6�R���f;�K/����'��s ���<
���-��C�6�S�Nqt�9�"
m/(j����f��~�4!:��n	�q�mJ�w�O�E�AU�-G�$�:��JM���3����� ��5�A-(:@�����Vc�����4!���&�+D��k6Qvk��e:���|����#.=M�R[i��a��h��5��t�s���G�\�1P{��fg�$�E7�E��y��H��XN�z�_���k�~2
�!;��y*gg�|�E,�]�f�����q0J�X�fB���2����g=��&)-����C�������I�������������C��c��E���Qx��U������[q{}���������t����������]�P.�zn"�������tT5����f���vc����O/����B��e1�T�����$�%_�-9���\��*5Q�d��u�/�}_���Z������i�`��t.C�i8a;�#0w;���l��������\�������7E�(�wz}y���=/������������50,�(��E��"?a������"���hJ�]\;���� �e�>��`����*�6��$}(m4�e<�R3�-����[�H�R��nj~��!��1�j��L��a�L��O����_!.��b��}�x:>��^,!5M�(�D��F.!��.	+?�`r/xr�[�����-�[&E�Jf���N�-�8����2���w�,2�F�	L 3��(���1)�YnoL��/�R+���������L>�bX��qZ�-k���M�5_s2���~�f���y]��"�v�6����1)��6����9��+�JS����eTC�C�R���r�/s4��	A�!-�"{J� �*S��Y����m.�/!��\����gs�|\�b����6L��S�s4�����Z�Q-���Zc���{n���YB�; �K�yIN,�ARMGU��x	�����$�s`|\��h�����9W/�~w��O|������H�W;q�@�c	24%�) �
��rh~|!�����W=���<�38�u���s ��{m�<��D���5����>0��8y�*�	�������(�����J3�6 �+m�����`L7A����%Hw.�{����s��W�����9�U0��x�n(V��Gd�HG�����o�$����G6���N�j��/6���G�X�28��]��~���NQ:�
��������`��a���>�n3�cX3� ��y����9��/sF���<L�p��|������w%�~�;��R���I��``��;��������)-����������h��
���KKy���_JI��&�p�OGn��OU.�����������UVS�'������k������������f��9E��W���H�b��X�UC�e2��h�����@4*�������'��d<��������V�0w��AU���$<)�>P���F��:)������]�i���,���d��2�>���8�U��4{��)���5?5������ks�����d	���7��P���_�:x�<� ��������{O�:�s��x��;?ld�>��y@��#=�&G#���c�#-����UF��
0���E���)�I{:.s��uxg<�����X+�d�i��XV�H���	��S�UNE',������]���#p��.�����Q�#�R�5X�b��d/����U	���kM����j���������R���*����@\�$��D���{���'yJL��6�����
�$��K���)������q���.�j�7��!��V����tvuy��v��}u�8�����eS;T�%��l�m������F�I�������:%��*�@YF���
��GS�����F&����Z��Du	���(�LbZ���0'S��&�T�.���>8��!ek�����e�������M/qg���n�On�W{�������_�g�������s8�3����\E����V�T��8���~�9���V���q�X^q�\r8$g����rL��3'�aA�T�:�������I��;P�n*��H%��e��v.������Q�r1�!�]���������O��B���j>�6:P�8���]��������->G��V�2�<ah�w��-�Yz�{��������&�;����c��U�7���J�!���h.�Zm��RIh$h��x �,7��a1�����F<�fswI@�����qI;`��I#��/����B��3����
�w��	�8\��1p������b@D�K�n;�={�����o�>�~�����W��]�={������!%w>>uv��pc����P-�I�n���Q:[��0��m���:�m>����?�+��P��HmvB������{��c�c�����S�
�\Pb�������3^A����i����r����K��f��������q�;��D�0�Ugk�h" ;�C��"oT��e9���:���}�[�	��PK����*�b���J�9V��u�q������5/>z/�V��rdM�����u�������:@���7Z�c��}:4LC�=1T�@�%<������$��Ap)r��=0o�e���T����H��}��n���vW�^E��o���n�R����S>�.>��n�&�o��W%��
�������9����$��Q%�����"�����h���S���#Yb[Th�����a*���p'�LL���}@���@|� @B��)�b��d���V*�'�L��U�|
�3�����J��ac�,��y�Q@��)S��|&�<_:WGa��Xd�,�`�{�2���-�,����1�����M2P.�X�=!'�����x��qR��<�d�CYP��wd1����=�hS%c�WW��1��GU�u���PMX��[3��Y��;����5�QA�(��(>l:�s� _{�%M�����<!� $!������O	�r�S�]a���}�n�����+�)��e�v���!���U��$p�=M���S���<��W//^�x��QBq3On��.�W���__\���Z��5
���(�jQ��^y��%���������>@�N�F�{��������e=������]D�J>9�{��7s�����:xrE=T|�qXu�lhu�O��
Lf��f��M,�����38G�b�NmSy=�p��'��-P�R�{r[?����VbD&t��Ti��~k�4�����\�^�a�qD��}q^��*��CM�
��%h��F������L}b|�����Bo�y!+�'����I�����J�� i�l�=�K\qi�b���i�&|��Y#�����/6M��q22�-%�V��xi&�:������rQ+��.��r:�A�a��k�����n�u=y]X��[3O������`�)~����0��.z.����1U��N�2��3�����]��]v��o�"��
��R�,�b���Y���l`K/Q��w&Q?���T��d�j�urD&��:����Q���;�O�?)@
�c-��`)�B��n�1�IC@�q��ez�tT�x/��/���<�6��y�>7_*P'��j���7+��4)-e�YM�4��F�I���'M�'>�!�H���>H����Fd(%�z^�h�'��n�I�L���qmY4�T���]��R�:�O����R������ �[��d���H�������0'm�e��di������R�y����fG���gf�+7A���H�-g/K����v����-�({_Y��u������^aq��|)P�CMuY�$e�s������N�{��q��s��0�N�u�v�Kn�~�i��Q���;�i�o�2��"l�^�m�z����k��_^��/�A�l;��'��rK����$��B��	7�����89�u��_5�����f�DY��w�F��������a�"����phD}�#&��!YL����R���q����C����H#I;��k0"-I�2�t��c�J�*���F^��i�Vy��������i�Q���?�Q��G�v�so ?b���5<���Rss��$l~�:��f���[s��r��|l�!T�K�h��5�����EW*�%��������bn��A����|��@����|�>/���
�"R��C�%HiK����]G��W�W	����H�rd{��`k�@@�f��6�T�m�r���$S�
�u�1�����O>�#BYD�V�E�3�&������Df�s!�7�c	�-�d��|���dx�i]
^��\YL��
���x���X�N�`���uvy~����2D�����/_B���J/�)D�]bQ�0��J^i
]s��q2�x��K��Am�w���i`F�(�}���@_0Q�bBp��jQN���.�T�-��f���d���E�j#����X0��2d�^"��'���y:�'����=���P����WSW��Q
��Tu%�F2�L��*#�D����`�D{�#;l_K�iv�{�x��7�wW�������{��\����SQ���s��'�GIn�p����5�H�N#J�$�ITu��)�0(���l����������W_l��W�m���o8z��I��m�Y�^��.g_pv��6��M��zz1�G����jk��1�Mbq3]�&��#6"�
fx�\�hKTP#G�������7��f���~��1h��d+x���7<�����}�:VX����p��C��'��_��w|�MS�g>�]�W2C��������(�s������B���������V����~��\������
�x��n�D;�����Bu������9��W����d���rp c�����]�i5�����}K2N�T7�rm���%�1DT-LU�����g���'fN���@�	�:��
R4|K���M��Ly��4�������0���������F_� ��x��l���<�oT��|
a���c�N��
��}��0g���[�Z�4=�G�:�J��-w:���h��t6�HP���:���&A���bsO���9�-����D����o:���'��(81�SA�\dM{�+���#���ZA��H2�N����&�Fhd����-�H 0��-MlK�:o*��Y*�B�gG08	Lu�i�Q�+OSM�@7�K���IZ1��^n��s���hn2�S�s���)��;����&=e��U����K
�+�)Mk��<n��6��fG�T�%�
�
kW"����OgHu��
}�*�Y6	�G��h��U�.f� F�eB����4}��<O��8�?�F[*�G� �tW_��x3�(��}�Q������)�m �&pW?(C����:%,��u�d_�-A#J��Ij��0X���t�&e~z
���?&�<���|�?���$�6b'��#L���~")���"=���[da}����k
pn+��!��q��-�0��hn �D
3z��peD�������5<l�A���QnvC�[!��2�d��H�9���� ����\t�=�L���b4��X���f��|$��bFs,�!�u��t�P�2�ei�'�q�4;�%�D1�V��}	�����IEC|0��1�v���laW����*;���\�t�Df�@H�KP�72������ �Sdvv?l�M����(=�UE�Q�[��e��*F\*��`����
|���?MJ���s�h� �4�eW)��
:��(�SP
;N)�3`+
�
���������T���Z��{�k�7�����	��t�s{rPR�Q�n3y+J�s����cy���o5�P+a����l%��d��TP�3�����Wg#x��Aa�$��f���S����!�P�A�0VdO&����f�����G��l�8�?S�bh����R�D��&3�6��H$� �	yF-��B�������ZF��%�:)�&0-3c]���5$��>�~�=�������>u.ty��N��mo2cI�8��-Ck���\?�:�e\���2�wW�>���~�hUg���Q���TN�F�� NW����������k���x5/����wF�]b3 �%0����U�ro�0?~���~��l2��f�%�d�n��G���Z��o�n��H�����k�
����.�)w�>�A�sA�
!�JdE�g�&���f��R��k5�k1�����MM�����U&l���ge���/IJ���ReDFq�}}�w�#�HbS
��Ce����k�%�N
:�
k{����=X����-8��/sA���?���;s�&�%����.�~|f��d��������+|�:y����y�t6�z������p�H��D5�K�03��z��$����N�xx��O��%]��d����z�T�e.0��g�����������$��%�3�,�*|��c>I�)�D�����[��~Xx�Ap\��pD��y�E����utr?j�����qG;J�^�OZ����_�[
}��Y��;�����sx��g����yh� �l8��=/�������`S��BN t�n������*P<F����M��~o��E������b@\^7K�"���V��������Q�c=PG@J���&:�>����6����W�,|����V7K��9E��C����������b���m:����C`=(��R��(�Ld&�����A�����u����]�������<�o=?6�������a;�h���~�w������^�hc���HR���
0005-wal_decoding-Temporarily-add-some-uncommittable-slot.patch.gzapplication/x-patch-gzipDownload
0006-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gzapplication/x-patch-gzipDownload
#115Thom Brown
thom@linux.com
In reply to: Andres Freund (#113)
Re: Changeset Extraction v7.8

On 27 February 2014 16:56, Andres Freund <andres@2ndquadrant.com> wrote:

Hi,

Attached you can find version 7.8 of this patcheset. Changes since 7.7
include:

Try again? :)

--
Thom

#116Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#1)
6 attachment(s)
Re: Changeset Extraction v7.9

Hi,

On 2014-02-27 17:56:08 +0100, Andres Freund wrote:

* do we modify struct SnapshotData to be polymorphic based on some tag
or move comments there?

I tried that, and it got far to invasive. So I've updated the relevant
comment in snapshot.h, inl

* How/whether to change the exclusive lock on the ProcArrayLock in
CreateInitDecodingContext()

I looked at this, and I believe the current code is the best
solution. It's pretty far away from any hot codepath and it's a short
operation. I liked the idea about using snapmgr.c for this in principle,
but it doesn't have enough smarts by far...

So, attached is the newest version:
* Management of historic/timetravel snapshot is now done by snapmgr.c,
not tqual.c anymore. No ->satisfies pointers are redirected anymore
* removal of the "suspend" logic for historic snapshot, instead the one
place that needed it, now explicitly uses a snapshot
* removal of some pointless CREATE EXTENSIONs from the regression tests
* splitoff of the slot tests that aren't committable into a separate
commit.
* minor doc adjustments

I am not aware of any further things that need to be fixed now (in
contrast to features for later releases of which there are aplenty).

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-wal_decoding-Introduce-logical-changeset-extraction.patch.gzapplication/x-patch-gzipDownload
���S0001-wal_decoding-Introduce-logical-changeset-extraction.patch�]ys����;|�.�T��#�7����������{I�{�j��h�M*���Z���c��J< �,}�_�>j�-sB�����q�06899`�c�6������2����1ri���D:"�F��G�FC�|6mrj���G���J~���/�����u��\�@�F>U"�R��0lK�v���5�F��s0�i�����}&������*SLU3Fmrn8���
#�9��eL���C��cQ��L�^���5�u\�����M3P�	U^W�C���t��u� ������3T��1���2���f��Cm�ZHL��5�y��10���*S�y��1�j���1]g�:�`PVe�&�#3b�f�3�����H3�*yk��4���|�*�@�N���x
���k���T%z����l'��j������B��
W*�;�A
�Y'B43L�&6���m���LM�f�+?��n[�m����&p"����b����>bh��)�b;0fB�!h��)���^��A�W�U����m��C!X����c�m�1�q�(�K�����[�8��k@�	��`���V3��]������U��
�fD-��oh��7���L4����j>���	��~����
�CNh�3��f9�3�v�T���I>3��TNc��!��0�Z��3�j#����D��0�*�O�t1��^���
�(�4f����Q��2�'Ks��r?3��N#�a�;�\����i�����q	.�L'7�OWf=m!��F#��s �H���V�U0�p�����
5�������D�����g��G9������N��f61{��1u�h��Lq�����,B����a�T/'����� _�e\�'���0�� �����#�o�	�?>)0w��t����������$*2b����S�]���K�Fb�=@���l$n vL@	��'9���{u\r��&��@S�E��_��[��=I?��H,/$����x���?� 7��`�R�d ��NSz���!�IN����n��G�+����@� �R�sb9��/���� G���ZM�7"\�1V����$��<{'�q��G'US��-�4��}Nu���q�XJ��Z(0�7����ZQ���V����dH�53�}�(PX�CI8�?�$i��X���eSO-�`�.����Q.�c"z��O�z@i�J���pH��TY��O�����T�&#��l���o�iL!��{U�d�'������,�!5`qu3��_�z3�z���Im����>�dv6S��zj9{ve��/�!=(T��j���x5�+���&?�T��*�+N�@t:G�:�k�%Q%A���:��o@��^s&t�b��MB�K��,�1p�~^i)��(�����p��!��w;��^iW�CXw�8��������7�C�}l�U�K�f���� �Z�/�2���7 ��)���M!xx���������"���t4G�aSj1�i��l�����p�+�M���f��#��MXmL�Z��[N��RC�h���<lJ��: >.6z8�	�i;���G]IJ�l�u�=��Ay�>�	�i��R[L�o2�����=jG�0�0���@j�M�v�t�����5��9���'�`���������,��\�f>u���"A�/���4Y��I���g�>/CE��rHH�Ee���oT���Q�'Hn39%:���P������/3��:I*.�e5�FbQ�)�r+�������]�:��l����$n�>k/���"b��=^���kX���4���PE����h�JD�c�aJ�(��~d�G��NR�����T�C�|J��\q���p&�c�9W�f:3}��@oi���������N��3;��#��vLdNG�M1�}g6e*�u]�S���<R�O�����V��B���Y�;���[�
��Lg���n�(��{����Z��-A�5fK���P�;��p���K�
����I�f�a3y��.�2,"��e��nm	�h��Yn��4Q��4�y��i�q[��o����jK�HtlKRGZ�%)�~m	:q�vY�2�vj����B�������v�R�aN?����/�"�Y�G���I�W��"
+�e����i��/E���K�F��JE��CR��4������7H]���0QNC&������j�|�x�[����_~!��F�p�yD�c�����yG�]!�}gO����������Q1��=xMp�K�4�Tt��x����_���������>X0���J���|�5�W�.)�t���T������	e�G{5�����G����?���������/�ilLe���m��w~}�����?Su������4y}�{������L����`5� �u��	�	���o�H�Oy�����O��(|56�)tu�/������}�g�=��]tNqN5�|�3�}�}����vQWm{�����|��W����?���x�	h��;/�����;�e�q���w!r��Gd�g���\`�
�����Y�P����cN�<�Q��~�e�~w_p[/9����<���pr����>h6&����?�`�?]
�����tv��w>�m�'�����7�A9T��1S���3<O��\�
���NCjM��������S��{[@HI<�d���k6�{�g�������10,���3�{��� ��s��W�N���t&��*(��>#������iA<%T�
MK���������#�mz�_���)�8$hp���\�������<���v&���f���/�'$Hr���n�^��v>u;��������wP>�%��$���$�d����&j�6*
{����Po�v��.��;���j^�g�T�Y�?��������y�c����������A<���Z#��+T��w}qzK��w�Q#�=I�%9L�$��y��N0���/g��av�NzvE�_��E��|����-�'�����b������a�@��������\��NUX�H*S���#�]�Wvx 9n���4���/Lg������9"EX�����Nc�/�����O&�����;���VQXL��7dp������ @Y�g\9~��;K]/�
�I�,���E����FKb%�$�u����D���h���Z���{�i�����c�P������E���l���m��{}�KO������G���[1;��j�_�����������C1uwb���b�������D,���,�m����
�t��.t��t��4�@�B��y�P�@WT�?bN��%��W_..���<Kk�Uq
Ow�<��m��v���j:��Q�������^w�$q�
`;P����7i�$H`Hy��dX��Y��yT�����	����B��9�Z��/��R�U�2��/����8EPPQN����eP0Cj�C�����A>���O�����j����a��z+
TR
����O�x���t��r���D�I�u�:�!2~��GrE�i �M���yY���a�x/^������2|�m�������������������?����a���R��Oy������N���i7d�6T��^�v�����E�p[y��/�\^qn���������)e�"�.i���������>����������v�
����m���.9�����b���Sj��j�1�����������'r!5��1��@ ���l�����0b��7a�s�V^@��.'���a�q&)�i��'1��'��I�b	*e$�������q�����N��u�	��'+u���o&��f�FiK"
�M�V� ���
.,^��N��m
;xf�5k�����������6lp^t�dk�U\����x:[_xA�����k����H ������JR����Z�ma�+����!(&6��z\x�dS=�)�x�C�V���X����6�f����7R�,nYn*�5�bn��o�
�;�W\	!���Q��n�>�|<D�WGon��u^.�g�������f���WB��+�
���4�3��\8}%��MU�|���zoJd�l�s��d���;�!�u�	XE�~��������ZZ�����ol���d��j���W5���R��BS��,��g��������������4���mr��o� �o/�}�I�&��|�t�;)n�|��?�q�����umT���/������`��_�Mffh���ovY_��X��\tFgFy�F���6|��>�� �[+4^��%*�M��A��A�M�Q���R/8~����#�w 
����EX��2�u�H]�����/D60��I�FM���j#mX��#��Y�iAz�Z�����V���V���{}U�	�o����3i���\������B'q�d�����^)'+9��A���2^��Y}�Bj]�SX,	�O)��E��R
xd��� �: ���{,]�2�6�q�D��v~[��x��
��y��~)�3wM�����9ynf��V�]��V<^q-��;����������_k`K<	���\%�d��tvo��T����:�*Q�3��J���+�G�Un�<��_���f���W��{s(���@����jwh^���J+DNs��
Q�W�FV�g����E���nV��Z!^����"(�+x�n���\�e�oVQ��0n�m�onC������o��d~A����7����$_y���
����7�%��lL���T��T������0o��k�2���D�������?��_=?8i����2�<�3��-�g����b���=5]sf�w�o�=3��e�k����+�������bQ�?P�j���S�k3b	5�A
uF��fs4GQ��r���"�\*�J�o��������J:aK�~�3�&%�F�d+�`�`xQ��P��+{��OW��&:���g�3��*1�����U��q!�-[1-6�^��y��a�)�0o��]\=�f����sQrh���b�TLW���AP��B���[dhZE��,���p|��S%��S����b���(|
�����q�E��*w+7�a<~����)�;� ��d+M�X27�f�����X#3�sD@J���0�Bj*s�{�Ji1r������D8��%�W5��<�`e��;�u��DG(|��`6��	���\C�<*w�$�9�T fTO�3;s���%W?_T�
�(T������MD��i�	y��)��DyNl���z���~�=�d$��:�M������3-`�E�X��T]����c���q'�
[����]�_�Z%h�{V]�uu}�t(L���"�=���^���|��0�[
o�Ed ��u���;`;���nY�
�+aa��3i ?������|�t���'!�(~�������N�{��7�Y�����WBQ�+{���@�f<:�z�B>�q��7$�D����Kx-x �r6���y
hoUJ.`���*X�tF�����< ��n����o��c�o��@-;���r�=�<��N~��^���X����v������.fS����EV����	�2����h�@�(����gVZz)�*��	�Z�i~����|�+�����R��vg��|��c�����c�	��R&�v�N/;�x��Hd��R��4s]Z�M�2up��:	��e+�RE�Wt�`��+��*���%��3���z��kn	\:�uij��x:z
�%�]��$��$y[4���)�E��5��|hku���i"4YN�A9���	>,'���u0�-2��5���D�-/��'�$5�3��@�V��,6�N��������X�.�/"|���?�����j�+�3!�>�Y��U�U2oR��@�k�b���o��>��e��#oQ��X5��U�`��'���gU�>��N��*���}���AL	yY=���!��h��x�N����`�n��&��*3���Z��tt�g!:FoP��E���X��D��@���J��*-��fZ(�A"�DQ�%P��VEN��(�vN��!�XSY��(xV*r����g�M�b�� b��6���/{���������������-�~!�{o��^�If���n����4j����y��u�S�]�j	�q�����uWWW�9u~��s�����4�9�q/�zGL�J��&O����*�*U+yR�T����<�]���]�PcL�c�q��B�����2�!�Q��E�
������Wlj��>���J:G���^<��4���$c�������~	�<zhf�]�5w����*{#�MZW@����j�+m���Xj�)��c���>��W����Xa��_��d8��v.�R��Y����
�������A4��	�^��Z��+�y���r(�t���w�v����+�
j~x��^���o"}{���k��k�<4�,���t���rOH��ivG�5�t��J9��
t��3���{���>}{t��}��oA<=�'c@��u���@���CT�����9����|��yo�/��o�bo�r�m�T��r�Z7�_��l����-��%�J���m����;�$,|C@N�G��U��F<�H���+n[w�5����A���������:*������5dE�;�2��KJF!Z������>E������\pG�-VB�s%6��C���he�������~�}��Ax�����[�P������ ����i�W�����W�E������g�9u���A�XJ��/cic���<<'=9�d��6M�
�����zq#�V�E�4
���/����]o����[�|X�d����������@��T��C'S��wD����Z���yk8z��e���0�����g{_IC^�Rt������������|���]^��a��N-�����JX��pv�����s���m������ek~C�[5�:�R��63\�2�Hed���G��$G����to���r�m��z^�
��7�J��������J�]3�O��~��w'y;+p�3R����
[���[m�&��RZ�,:&�|�15h��:�������g,�rp��5���G������sZ��:x�����(��L�x0)�yT^lk��g��x��0E�8�'
��	��-p��y��r�6��{�"�n��&Q�{������I2����^���9�v���g��gZ���v}���UM�T��"�^����2N��x���/�1O��-���F�4��\�/�I( ))��
o�,1��c|�k���U�@�<|�A��w�}P�������.��@�j_�����C�u8�������m�b�>���M�w�n���������d8������$����Nw�==��������^
.���"���=����Qw��p����S���1��l�~���?��CwYA�~����gG ��5H�U$_�s���+��s��%����D�����u?W~T8���{�=��E4}ca|��}��?�=|z��x����\I����Ke;)�L�0��C���������8$5?}��"?��n�r�`������_�7.�/]�<�{��;g�Z����_�~��	��iz�8=���uw��;�a���+�qz3
\F�1�N�77�:���pct�Nv��FS)��Gz�}V��"�v��{�h��D-H�Z�g mgG�G�9{�� v���G���������q���VV���[u�v(���lvS����Sw:f;�?���g��_���kA���D��gX>���-�Im�'�����g{B1c�+K�����5f:f�ca�r�m���Z�f�F��3�wQ�L|���SG}��e/F�G/�gO�@|!��L;����q�����u�d���q��xz������6�����g8U���;P.�f<���Gh�]U��JL�cC����z�����m�����0���j�{�zzX�3/�"�]���<q9^��~�4x��~o{+���=8�;�[�����~���3.�I}=*r[/���yt
���)���*]M3S�m�r����va�>�����.�(Q��?�6�v���upx�����/�R�)_�g���|a����"|��Z���AM}����������$���.�
�G�]:�e+3��h0�M�E=���������I~3Kf*�Wn�B��_�Xnx�.#���[������������G�Q��yp�;8
��1�t� si�hGQ�$'7�/W�x�����lSzSJT�E;�(�J$1�5RL�h1�����d3��}��a�Dn/K+�-�
Z��k!�e�v��{Q5�������N���2���BrHN�t������Z��s�|������s�J������K_���J@|������P���s���w�OzX�+������
�<]�DWV��������3P��a���`��"�0���/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/�����t�I�G��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��_|��������/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/����/�������O���o������w{'��Ix������������Uor1�N����������������7�D�������NB����������;���'����`�:����*]�KS��l��E}��W��_�����������X��`])8����2��y����X��jh��c!.h�K��i�h��o��`��9��5Pu�/��������9	�Y�=�����N��O��`8i���������%;��/g��m��R^�_�f��A�b��%���������.�;,�}��/���\
�;vbun/��E�k���a<�;���������_�y}����q�Vo�776[�J�Z�U��Fu���nT7��Z�V��j�Z��^k�6j��V�R��k�z�Q_�7���z�QiT�F��h�7����f��^Y���������������z�YiV��f��h�7����f��Q��n�6����������Fk��Y��m�7���������V��B�Z�X
�P��>W�m��B�I|
�}T�!qP��qa`�VmUk>�a��j�Q��Wk�jm�Z���Z�z�/�1!n�Z_�����F��Y����
�k��
���^m4���jc��hU�+��z��^��c:1���Fu}����6+�E�Vm���F�����lT���f��Qa7j��zu�Q�X�n����F��Ya�7k��zu�Q�\�n6�����S��0I�V��jT[��V�����J���Wj�J�Vi�*��J�V��U6k�S�dp:0f�G�|�U�k����t>!j�Z��)��:�Q�����Z}�V���[�F�����#`�z���56j��Z�U[�p���z��4�4k�����z���&�T�^k6jM`!�g����5[��
��^l�k���zmH
d��m�j�B���6����f��	f�*2������z����6j-�8p�B�cX�z���W���f��Q�l�+��
Q�x���%���
��3����10�]D?Zu�X�����"�*�2����
q
S�'
���z�Yol���F��^!bv��:�W���Q_������
1����z�+m����7[��
�0��6����/��f}�U���.�b�Q�\�o6��X�X�Xr�< �b��[��V���������+\
2�^i4*��J�Q�hT6`a��#�R�z������
�Q
�rf���*\^��:i������b���U�PBwHy@z@{@|��z����)��u��fc}����Xo5��W�!f/5A�@�6��F����p)C1�hoc������h56+\�@^���\ol6��y�V N�5��^�V5Z�Fk��IM��6�It���^i�W6�+��,�
�)Q�}'�u	�:�VHQ����
���
�THl�mu����Kt�B:���s283������*W_#�&���^o�7+�^X��5L!�4A�7�������F��
�h���K � ������
i�20��6������ ��C�r /`�O����6�[`�RJ�5��^T���F������UHDI���$),�(h%"Vr���D�N ���p�:�w+$�\�u���K�HhUH���u������
	6��N��La:0f��d�$Ql��.G>F�l57*$��^X��5L!�l��m67Z��
9�+����6�#���*`�yX��PL<�l��B�C+� �X�@^���llT67*`���:���S����������$��#�(h%y�������@r���p�:�+�Q\�u..0�K����}G�\CD)�@�+�l�J�������1�6��*i9?� B�p@�`���Y!?�����a
�d�D�
X%8�+���� 2l� [T�E�@������x�W����SV�`)�������Y,xC���l�N@.�d/�T@
+d�$�u���&;H2��_!�&i��l�5�w`|�����N�������T�
�<��NbClkr�D��B���q~��NGk�����
�<�F�
R�f���d����)��W�J�2X%8�+����*�Z"H�D$j�p�1�%GKD��-a�-a�-a�-a�-a{-a`-aE-a*-a-!�-!�-!�-!�-!�-!m-!R-!7-!-!-Y�-Y�-Y`-Y*-A���oK�%(��h	�[��L}K&�%�������-�XK^k�,Z�<���Q
��H)�R&�PZ��-Bk��'�L��)R���GA���2�^�(FQX�HD���
��*H(vP��AA���>Y;8�4�1Y.+�'�$Y!��Y�
�
Y��=I:	7�3�0I-	*�&�#I 	��I	��	I	�?9�2,�%��Q�N4&�%E���Ja�B�'��q�*��$r�8x��f���V��	�(P��hO�b:�q����R���z�y5yi+i�Ui�N���"�dT$�$,\0T"�S��HJG���f���>\UT'�;�EM�P
��H�I����XH�����(?�/����q}R��aZ)�Q� �$S ��"��!C<(�Rb�$BK�A���N���C���U�T>�}P�����Ut
�T��pA�<��p��5Y���>Z��H����l���d���hpTMP�j�	�T(�S�<\u�z�Q��h���(��� < r����z��".�< �)��[��<RlC=�L���D
\����I��PD�NE�����z�#.�m�<����\�x�)���J�Er\4���z�H%.�<@�pQ��(����"qA�<��p��B	:4�b!�����<\�x��I#�Q���F��<������(�T�P��
�*)TE�p�t����C��I���uy�}qQ]��z��0.�<d	��p�^�z=eH�<���D+�L�<�P�����2��t)���P���EKe���,wpA\�x�o�B=��m
%	�t��U��� ����-�l�� 4b�����0O�����U�:
4�P������YJ~���B�zT@(XS`� DO5�$�*��=�~�U)*LT���B�("�h �B�z�\�x�< ��B�&-)�Q��)�(9< ��B=�"#.
��x@�S�	x@���z��%\��P���R�
��"p�����V���^��.�2�Z�$[\��u������Xh��
�/.�<��)	�Q�C=�:.�< ��B=�C�|�$*u�x@���z�����Zkh����
Q���J��*'��G*�b����zT���Q<����p�^��+jW�x@���(�<�
�B=��;.j�x@�V�x@��z�dW\��Q���X�����p���feq�tB\�x�C���dd\-���
����h
4�b�� ��a�5���x@S����"�J+�N�4�QqD=�*.�< j��V���qQ�D=��
.�<�B*[����#�DD�G=�fT9(JS�%��*K��j�X�b��E*����w��.�<�L����z���%�P��"���G�:�+"&@X��z��k\�x@ �EKeEE	�z'.P��gU����m�hE��]
�!+���K3Dr�#IjTGQ��6��I1.�<����R����)�PLq���bMEE��).���x@���z��Th��hv���z��)\�x��D�(�}�c�>#v���H���8�(��T��"SC.�Z���
x��x@G��z��:\��R��>Uq�.�<���B=��	.��+*��mq�Poqa�iT<6E�%W8��p�uY�
���jTyQ�����h��P���N�4`�<���B=��������t`\T�Q������*f��q��M��(��P�Q��^�����SUF=��D����4f�HK�#�j4�����,@��*>y��T��z���j4�����Pcq����P�������1���2�0��M
��D��E�MnA
�UAHTY
���5���x@���z�kn�@��^�F�l�<�`�B=�
,�������l\T�Q�������*���qqk�
8�P�q��!"?���5�Au���P	*���q��E�s�<�����Z�i1�%�>Z��"C��B���9.����������?*��q8�V���q6�:��7����&�)��6�
w��f6��]'-�
[�m��?����[m���6��>�b�-��p��p��PQ��@�@���Ok+������#UD����P�t]xpEh����4C�G�L�5��m�mi�����#��"P�����i�����8��;4�@|��wh)���MZ�h��.�����3�v�9�fb�?i���J�E�=�p�7A�;m�����G���F�!n�p��y�iH����/�r@��]Z�i����VDZ�8�4�T�x�P�F	7h�����H��@�������ih��y���EZ

1U�*jbhT�4���J�)�F�l��T���R���Ju��&����TT;�mT��nQ���D��MK�.*�	�
T(�S|�hN����!�0�\��O)zR���Hq���#"�/�V�(Q��(C1��(&���|�s�j�a�X������4�+�"�c���~�u�bV�����D�����l�$�����tc��x���Q<j������j�?�Do[��&2���}Y4��*�q?������&�)���C#�������Q<j�G
���EC �Q<j
n���Q<j�G
��%Hc!�Q<j�Gm�[O�x���!��E��x���*����!K�FG��x���Q<j�z@=�C�;
��G
��5��x���&M�bR�e�N�G
��5��x���!dCV���A7<��G�� yJZ��W[F]t�u��"�n
�CC�����-��}&��p_��n�(S��+����X��r7�{��%������AQ��u��x��Q��`���z�G��Bi�<��G���&��P��B2i�<��G��u����} �<���x��:�Q<��G��orD��b$�u:yu��x��:�Q<�<��	$�?���G�h�JKI��\kbWj�=c]t���
�"	��A���`�<�G�h
��x+�����)�z�D�� 7����M
�����d�'F=��rg�����%K���h
����MY�<�G��C9��<�G�h4�)�z�G��D#:��<�G�h�
n���!���v��x4���<�Gc��R��"����<t�<�G�h
��l��s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����s��=?����p����NO�Q0G�^�~y^Y�hmrF�����������w{'�������;	�-����M�a<�;���w�Nv������$:���<�R#��;�~��I�y����`4���M�W0(��T~����t
`��e ~��`]���
`&�&�\��
�����������\�X�\���`M,��z���hn61`X�����Mlz$h���������|���>�BC-Tj�G������*�
��Z�reP��qa`�~B&��!p}|l\L�l/��`�A$�����j� ���H�$8�c_OKGC%k����S@�0���&)�(�(�>z������lcV6�=�<)���C }Xm���`���`���Mp(E��u�J�JpJ0J�t��+t���&�����K�8tn��q�03�����>�HL .�
@�\�,��'�� ��� ��n \�IdrU������U����e�B�Ve{� �@3�LL<,��0��� ��+�B��8Y0��^l��c�����������9���&h�:�����6P#k�e�J��{�y�w�u��qqX�W�RA@@��[d-D)��KPi��pk\$3�����GK�Q�.�Kk�������)��@P7.�$�P��*g/�c�aq5����~�����x��m���J���!��&����:�
�
x
X
"��B/6A���c�b�a�`�*� gt�J�������B ���b������<�H���j�
���
�m���j1�0�X�,��[�dp:0f�G[��D(�;�< =�= >��dU��O�A��`�
`
d(X�@C�.^j�j�&m�#�!��`)C1�hoc��|l�L����S���� ��� �dO �z}l���������S���M�����^6��Z!� %���$� X�@�
)
�^���R�z���
�
���9�3`�NTH�8�uN�c�����:�Q���k$�$��� ��-0UR/,J��O�������f���
�h���K � ���-0b�<,e`(&�m6�7�@�A����"b�|����Xo�UP�"���K9�����v�V!%����� ��� �X��W�:�L�������rY�	�",� =�U!U&"��� 0`F�*$���:��3����1�V�]��D��FS��]���d����)��
0���F�9�+����6�#������?��a5I1�hr���NJ�AI��aB��0�
Y
y[�xMV�����s��U�mH��Dy_�d���BFD�U�j �A�A8@���(��:
F����@V����u�!�
���r6B����IlR��[�}���k�D8�x���@F~2��E	\���&d����-�@��d���`����;�(����P�$�7p�
,��:W9yv��"�o������I�����
�a�l���N�@��dIF��+��$mu�
R�&�N�����s1�IQ����
`\!�'��Il�mM����QU(`u�!�o����hmr`U2=������(SA���
��d����)��Wb���W�v�hH[
����A�%"QK����)-8Z":�Dh	;o	cn	�m	�l	�k	k	+j	Si	{h	�o	�n	�m	m	Al	ik	�j	�i	�h		h�bn��l�k�Ri	��}[��-A�� GK����d�[2�-����%]l��Z�ZKd�JU�n�����H��E�S�=��b$� �zh������Vh7�M��V%�SP8�}�����S����R�����)�P���J]�z&u��Z�D���Fy���zu$�?�mZj�#"�!S!� �  �'I'�+�0I-	*�&�#I 	���X�@�HfHLH2H�������`�Z���%�����EA�'����DI�)�R��A�I�@b�E�j��M&�V�	��90v���ZU�&��@���=x���)rS����Uj��Q� �&"m%��Z��S����z�	0	�X�)��R$�#r}r3RiR�*��;�EM�P
��H�I������.�G)gQ~ _$�'���#�xPh�0F!���L����X��:�A��%rXrRD�t��*�<�zP���A���V�Z7�ZCOMw� \ ���X@5�Gk)�����<��P�
��	�Q��2A����
���\u�z�Q��h���(����DN\[Q�_��z��Xd	v��.*��P�S��R�-Q�������2)������]��6��0F\d��x���(x���B=�L�V���X��� ��P����z����Z�� ]�[]�=�=p}\����X�eeu�@���z�X��Z����C�H�z�e)�Q� O%��j�e!�5�!��bC��J
U*�js���qQ�@=��.�<����x@��Eu�24�`��Zj�< ��B�&�z���x���������H)�(C��!Vv.e������h)��K<�;� .�<��p��N����z���T�*��Q\��E����	$�?�< ��B=�C��$-5�Xuhp��A�$\-� ���/
-�Q�`M���<�<�(�lb����zT��0Q-����1��.H�����WKw!H���P�IK
z�<��u����������(���!�$���/\�x@\�E����x��B$��z��\�x���j���l����.FP(J�$[\��9�Q�U�.�X+�_\�x��
Ix�j���p���WKw`H��4 Q�C=�
.�< ��.
Y�5�B�v�z��(�Sz�TF�����#�D1IQ�C=*oT���q��,��F����]Q�B=�r�����p�����<d���	��$�����h
�t���%�/���P��D���`�Z��$�f5�h�A�L�"�WKw��{��B5eeM�kB����],��UE�<�)�@��H���EvZ����#�P�p��QSw��r����F�����cF�LMG4����zT��rP���K�MU�
+�R�R�D=��T
��F�x@5��z��)\T�P���9���\�x@��E�#U����QL�������P��@����|��Y�M�
��b�< m�N�HR5�B���?�<d��"I��(��Fq5i ��z���(Rl��HJ��(��P��p���m����������3I������fW*��x@�����K�H����G;�3bw@=�����S��ZM��*2a1�R�E=*����x@G��z��:\��R�l�N)�1hN�P�����h'�Z��*��5�0���P��mU�������T[��)c]V��@��k��,E�U^�<���B=�%����R<��,M�(��P��:���!������=��L1��6���n*��x@����]b����b\���E��2���t'��*��4���H��EbA=*�4P���OE��:�r��bc���i��Pcq����P����]k���f270�iNx@���Y���h{�HS�"�&� ��� $��%���kT�Q��V��(�� �r��unP�F=�
6.�<���.:Eu�z6.���x@���z����S�<�q���p�<�v�j�n<E~��7.�kr��8���u��j�-�P�qQ9G=�Cv��:p��uZ�i	����+��P!��?U��Q��h��/���0�m���6AO!��	n��e5�Y6���6�h�������l�� ���U������{��G'����a�n�������xww�$�'���������z���#�����������<D�p��h���R�p�+�y��������`:��B0<��3t�?�����8��_�t���Q��S�;tz�����d�$x��������=�
z]�X�>_�� ����*
��v7BG���I�:�>E��wL."�������p����N�^���@�����P{6:o����N�o����}M�:q��8:G1�+��������{�N��V?��1�=�<������/����/����/���}��_|��_|��_|�.�n��_|��_|��_|��_|��_|��_|��_���L�S=a�
Z��O}�S���?��O}�S���?��O}�S���?��O}�S���?��O}�S���?��O}�S���?��O}���=�OI���%����r'	({_'_a�tU�v��������=@�������{�~���=@�������{�~���=@�������{�~���=@����x���^��p3�g��t������(0	��q4���	��?��I�'�����f%���<>�Gm����/J���/��������O?{t.���`rN��0G������P���q�W��gIW�$�O����Y��L�(������2�_�(���������v�����0�d����	~��������f~��
����K1_�
�
���I��8�O���^�w��A�=��x�����)v&�i�_sn�VX��i���-scq$���������$�u����w�l���d��
��E�GQgu��;����9�L���Ipz������D�d�M����{�n�9�hY[�5�:����Z�����>}z�o����V���i���
���:r��u&�i�l�B8���i��//17/Yx�,������������8n
��P�Npu��o�A��W��E����P�41�7����sRZ�W*\g��)R�#��q�,��M�K���d�J_����Ls@�2�(Dh�����yt���'za���U�e4	���1�5����Al~
���`��������4~���p����_�4���T�T��XG��
�v�~�}�wpJ4>{�/>���a03�,,�i�E�r��������uG=�X!���y���0�y�b��O�3�y�,�����6�b���p�W��v�BYS��p	,���!��]����ct]V���H�������+�[�v�K���MVg���j8��q��P8� ��S��Ih�I�%�f��q5�����|^_�@Z.v���)�VQ�>&j�]�{=�i��q�����}�Y�ef����@V�4V���9�����v�$����������KK������zm�n���'I��)���p���� ��Jk �2�1� -���O_N'2����z��*�k�����?UJ�K~'���h�������������`����(�����_�/��W�t1w�m���7[�O��N�K?�wd��x�O������'�����*�e�y���LG�C5��Q?��B��v�?|*S�.{���[2�%�������G��r�HQ�wX������:�2D��h
�\h�_���Y��	�z<�0�����0�������Q�U��f�s�rYd�h6���2���l������z\�/BP��N?�c ��]���\�o����&X\�|e�^��������=)yq�6�cg8�&�d%xT�����B���Qp�����J��;%.[+�N���N��d�����\�d������_���~�C��Cf�T��${jp�� 7�w\������?�W�j������#c�J����N�-�8��.���h���sH���"��y�9�'�3��p�q���<�F6#���X����{a)9ms�t�l�{9-�9GZ��+w�G���t�n����q{0_��3��)�1�A��?��=���Vr7��v���m�
�7�&�Z����m��	���0����������R3���v�-�����7�'�8[�<�����������r-��?������EE^��������*����R�h��y6c���lc���b�X3��=�/O�0�'O����L����S`�i��g�j���*��9�'��B��d�	����7�X��s�� S7���gFx#��3�]���?�(���X���y�S�?��}g�!
G��n�*t$,��Oi��3�Xld��
����1/���w�Jn��Jd_��u������;�(P�i��������u�@�A��QF�{q+e|�ya9E����uj���u%�����W6���;���&��i����%\��s��?
��h����nr����m��F�r/#��z�IY���S8�,6.Uk���XQ��	�����������oS�v�*�<���Q�`�LH����k��5zwY���Q�Fx�V������}�����h��*Q��,������@�2�S�}0�;��%�q���40�Z97���?|x�����/��
G�wG�ag��p$�����Q4{W��m��4��D�Q���X=����g{��1�9�N�p�w�6������nS7��<�+������Vu-����C0"C��P����3��Q{���z9�er�U6��f9h�y���k���m�����@.��Q0�wE����a^�7���������iY�2���s��{���*_��k��vg������/���
2�%�4��K_4/��h��5�;�0]�:7�6���9]������4'�~ag7
:��Cg;{��m�m�}[��7���m������Y^)��IC0/g�H�.e�`x���;�~�r���=�2>�&C<;8<���}�|������O����{�����kK�&1��RE�6�����1�p�AI%���p����-+�����YN6"�^�Vf������{��S�p1��'����x�J�"�eZ���r��+��)�
�������z��K����W��#>{R[q+���A4&�9aO�FqX	�K=��/�u�O�mJN�&��X��5���;�3v[��^����l��.O���mE��O5��v��*������9\b�V���=�%���/f����g��Zc�����.��|H��?/Z�v���e�<]��3��ygf���U�����������U�����U������������
T:���m;��9
���4Tr��,�D�-�N��W������Fs�!��#���E�"qh?@���G���M�iP,?3�Y~����_*����2���_����9����]m�S,������V��g��h��w��yei�q���l��?S��/[�hlIv��D$L��b~��(ND���+�]�
s
0V>c�3�9cv3�T���5�^Z�����"�6+K�m��+��p�Je��P��
�9�V���z��r����nZ��2�(�?����m1��c+���U��S�c���6�a��*7�� ��n76���CJ���x���ao
O���Q�JKYj�����[E�|�����Dsq�}���xM��O/���>N��Xf�<���	���v���eMN�����������f������,��k�j�\�s.�T��Xw=ud���y��P�^�S���r�_5�ke�;���M��E��;�����N/oq%w�,��9�<����a,�)N���~���9_�C���n�f��q4��9����q/�i��u\�dOu^;�:��M����&�Z+h�v������v����m��� �Z
�Z[I��M��e,���iCp��o�w��~<��m�imfSbn�d��i���6v:�M�6��W��4v�t1�����IP���=��A��4����n�,lk>\rM-6�ps-�><���:X��| �;���d.(js��v�������-;��y�����-����\������JjVI�����p����h���������U2���UR[�JfKVIQK">�����&��������e�H��K��/���%�	�������q������t�Gs����T���*����X�!&]����}����x%�:�:*F
��9�=��fd�b�:#�rH~6����?���������W����O������������.����$,�i�83s>�d���Z�J]�#�(a��7qZ��b����E"�+��!q?��x���Y*&>�y��~��LR�?�D���KR�� ��Y���=�d�d���?��}2�Q��f�M����ZH��`B�a�K���w�Q,=� t�1,�?_0��[�__�P�d_�:S��Z/��;��>`�+Km�n�E����7?�n�.�h����g��L����5�5��8F1!y��f,���dGmq�r�������X��K��Sn�6���������|J*��W
��[�������d�:�i���=s�����)|	
�V\.G�~Z
�[�{�3��0���>�C���+�]B��o	U~�%d?+l��e<_w�nE����unp�!����;Kw?���|��3�3$�z�_�Wp+�?o�j_m��A��}�j���oz�dLe2B,�n_��!����>_�����8�L��yR�l��0�D��/���i���Rs4������dP�����F�c�{��io���?���L���b��:�TNo��q�S5�v�����LS�jJ&+1���j<������l8�D�:[���
��'To�7����-;�o}�,���M��-��y���w���������M�������h�6I��/��o��']���<�7�>�^gn��
>�}H��x����F�H����O�z�hN'F�-�{K��:to������p�F���O
�n8��G�����Ecs���������c�Q��+ u��M6=�]��1�^�d�46���0������x�����|�-u�u�2=�����gO��_]D�&��9����@�����<M�S���N$�pT]��'��G�-�-F�+����2?8�����0���`�X���[��6`k^q�������HZ������f^��J�H$�v?����D1��Ra{�������E�q9s���`;EZ�
Ahe{�g"�s�r�a���O���/�Vl��W
 z�p�'y��/z����v�0r�T&|�m{P��NL��o(��mNf[������=��P�s��v]S����np����n�����r�v��������Q~`0��%��2aB�)����h����%,�+���5�H�v�k�d��n�F��}%�����H��	�x��d�j)���_m�_��/@������[�����a���w�����L'jw�������Q���~k��pX�YC�����..|�������1���S/�Q`�28��o">�����>��t����L�f�Y���L�������FM.U+3|lEK�����~��Ix�/
�^�q��t17f%M�	���H+����\�dD:���Q?��O�����uQ����R��|��p(F����cld�$<r���px9�\��uQ��k&���|�77�V�R�7�0_�9M�����Q�*i�-��2������������,�Y8A0�Nt-^�	W!XQ0�NF���nX��:V�~�?S%�>����������3��O'�R�v��P�:�VU������������7H�A	�Ga�B���"�c�d�sQf2i��J�|8���e��g��g�����T?Xb�)U\]E+����0�~����Ax�����[�P���[��A��n?N_��:��H����-����m�<��ivQ�^3c�1�s@�=���|�;a���[j��^���^��[��,�������?��LP&�!9	N����)!2o��5%�kkk��S��K���T�Cu
�Z�=��?�RKn�x:��N�v>2�aN�������{�_�2��r�z��f9��
�,��(�^t�����w++�����j�b1c�^G�F:���������HVh��N�%�l���Y�v
g3�	z�6!�J+�_^�L������os���(K�#�sW���od��b�-k����8;�p�,7P�e���Vdb�fd���[f=;�����v7�$q�l���"�9q�Qcn�Z*��+Ht7�m\F�P��D�D��\��D�>j���y�*��{'�%I�k����/1�i��w�vh����)����W����l8��nm����!g���/�M��lh����|�.sO��]��a;�_������t�#��lf�������xK�i�2�I9�zs�=�DS��V<|�����53�����1yQ&��KD���F�o� �a0��!1����]��N'�#��:C������a'�����\BP���z<��>��6�R�lY��}#Z�c3v20�J����I�����fp�l�lk�7�&��W{�[�S�<g^��],��'7��[sF���v���mo{;�'{'��i7����-�U1�#}C
��5��^�#T����_�O9�X��f&E�����/-���Z3�#����J7�G<�p~R�E;}K��������/�D���}�j�viix/�H�'za:��O�xY<�|#Y)�-'�\Ge��B��$G����h�24�E�7����q��<�c��J�bf���%��m�H����
/�ed�r`������cu%�;���i�{��MF��y��t��d��#:��w��=#�*%;�n��D3�r��������9�Z�rp��N�`��d�!Q�/��W���d���w�P��I�?�v�w�K~o�Hg<�:�A��w98����=��dX�������R����AO���U��1a� ���J���ZO���xE6���;ge|���������$j���
	�h�P�\o���&����-
��h�m=�~�����:T����g�m�}�9,�����P��b��FS9�pu�S7�p��c�X�7��iA������w��&���\�#�u!F����������i��
�p~6�!�27)b:M>�}���*��c5I����9�ra��f@�U���_d����3���a��\�k^����QGRn�m��Q�{9�\m�@7���:[��.�TW�������t������;U��:����$�������uru�;���nTNo{ 5�%��4[_�k���,)P���?��7��/f�C����C�?��=�����J8F]g������f)�D
��_��!��3���l�S_��k�t>Yn7$���,�$��� ��N���g>#��������<�"����x�d��O����A�X��M�$H��+�j���L�o\_:+�V���
�S�	%�g���Z��I��m�1��[��r2E�s����z~���aZ ���-b���\��;����r�?�n--?��?��R�_+�w;�g������R_��R_a��ss����t_����G�����s������[�����i��'@�w3������"�}8�;��I���?��
���lu�������d������=q�����������K�}���w������N�8r$�R75��j,��\���c�u<O�N�����M�w��y�����������
�H��������������ko�D"�[L���&X��V`��V��Ds���.@�DOrX��H|��~w��bn��vu�D�Y��.)��~��JRk)��{�����-����p�~�����b���.�,���~,�d>�Ka�y�	78'��+AG�������-����Im��{/������ �Z�
��&y���axZ��5���/�n>��l����f4�C5����f�F�YE�uW�_�df��E�����~��}��9>9<�z��Q������[�#���P�S�6Ur�������>����V��~�l��qks�������Q��V�����8���:a{���$����N�������T��'��e����2���f/����	wP�|�!w��K�������Ze!?/�������j��-����Y?,�'�v�,�;��H����������z��>�B�����x�������:��C���L)��.Z��8�����>��v����Z��[j����z#���D�e2-4*W�����*<�"�a������J�E�0m�5&-mG�����$(uV���U����a<��8����mx
^�����#1o�CZ	M#����l��,7c��{��g�������$^������l?���p2�<6���YP*>��?��h?��8�?g*8t�������}��g(�L[�I�?;����i�=��}��v.�������Q�p��������a��������w�;�w�����m�P!2�}���6jPk(�'�����j�C��^�l�zX=�tN��n���2��3�$%�E����6P�rNG�E������G�f�n�,�~N���A�`���wr��\N��O� ������H@A#$��]�#c�G�Ai9���'l��t&���;�Cs,��pD����@�����\qF�|�b:a�E����$hO>/|�v�(����������'xq~��{.�xP�z9�	�E������aX�����}���`��)���g����U���O��@��	�d�nx����p|���8��H�7���
�;�����,�g�'o���W[1cq�B�j���g'Xl�o��+f:�f�V�����+����)������Rt��Ip�����W��I��|��l=�<f:f��0�.���B���#R��L|n�?|z��=��B����~:�=���iV��k)�shdp;�����/�Z#U9�����_9�&���b�)��I��.I�Y��)KNS�Q������6������A����������,S���O�����\��������9�,����OT�^�DI5�(<<�p���I�����{�H����zW_�zgT��������s��v���~tI5�I�?^}9O`1��,����
������:�^��>(�bY�oB��!�s92��nuw����=Za�vL{F��w�Aw�r�o4~��m�����T��(��&����B���z�=����B}!@<�7�����$�7G�C�O�����l;+��N/�%�V��c.n��>��6������~�u����Q[�
+�����K�:r�N��}2c��G����H���)���`
�����.���?��o�_���@\~�����H�_7��,��K�D�,���!��
n
�3����Of@�����������R��@1�J���zR�91D�L�K���	U��A}r��
���R�<xT�!d��������qrE��1c��)^(�,�\��R,�`�������!:0xS�7��.E��"F6�
�H��RF�Yy�N����B��Q/�+_:������%��|����P���p4�]��{��a�~�H����#4�y����*��
������H^r�Z�G;������/�1�Q���+���p1s�%��&9��������N�o���0�iF��a�{�M����D��
�K���'Au�a?�:�h�q�_�yl���	c��'q�I�����>�����<?���/~���?���Q`�o�f�������x��YgH���Z�w����HT*R�/�"��$/P����~;���G���5c���;G�6�.� bh��n ����1T?;'��nb����&c����7aqy9� $b���I�po��{���������o��r����[���m�{$���?F�xV�9w�Sn�a��� <"pZ���,��A:*��?>q@>�z�$�����[����=�&~�h�����q/y�M\�n�Pq)<ZI��_�QA� )����x����������c�.E���
]Bl�_$���O��(�iDN��������8������Q{������R��lB�����������5~[v�vz\HV��c�r�����Xio��pv�JmC�z���d��	k�Dq����r�}���~��6��co$�>b���tzN��}Hc���Q�H�N'�����<V}����
��vC�aS��A����6��S%io��D�W$��Ix�����.�����������o�~K��|�7��>����hSl���g }ggp��z[�Qz���M��	7��P�	����{�8����+���&��Rs��y/��.�b�Ukl�uMk���?��>(� "���%`9��cF���0����d[_�d���D��	��{�a��Y��<�w�3���,�^���������(��)���?95A �X����nZ��K}�����u�C/6_�U����.�8]��1
�i���W=��e�<���E}��~f�1r����0!�w��:#x�)L*+b����J
�����
�����
�	*���Y���O�/���o���M��~��Esf�Q��UU{2���g("��5�Y/�����������sCG~��#��B���t������_;���(;ga8��PyT�JV�P|�������������	��
c~�x�]Q0R5q������Ol<n�?�q�NN�{�m�'�><��;�k������IB��
QZ�����Kfn����b����c��m��3�I�o�&C<�pr"!�pk$��FE������C���&K���wvO��O�;['����7��;�����h4T���d�l��}t������m�1j��mL7v�.�"����lW=�����W6�������y���3�T��i��j��I\�~��l5ve���2��l�!�����u0�%V����%q;��(kt4���� 3�c��N��f��m�x�v���ta�T;]�����GB�ui���jt�#��Ga'�����9�3�Sr�B�L�{e��a,kIa��
uK���n�V�U�����Uw�v%-S���7o����[oi���h��4���T�:����d�6��T&�Z��h�4���-"��X�k�
X�"��o��"�8������h���t�	3��L�N�_�	������W?F�I�_6M�7������&\����7g����[��c���m��'�sR�
��U�Ii��=�j�@F��g�Q���"���IG���&��s�m������$�����������<_N��Z���G��72�B���M4�%y��RN���fe}���N��[��+q�������F�fqZ^�A����B�gEQ?|j�|m�l�f�k<����f&����;����A�*x.s�;��@�;��1������5��4�}f��^o�����Z�in�U+��- ��)�6*�&&�l`�g���8W�f�e&�����Wzba:���1����!t�8�s���2T�W�>V�7�"d�N���li����������w��|���9��Z8��5�B��n���V���]�V���/Nmq�WW_�|G�It���L�G��qt�O��>I����;I�*���gzSN
'#�Rv�c8������;s,0����f�%��v�����TbI��W$�� q��c8vU������2�{-���C��u&1��H|:��9���B�<i���'������(�#*�B,������V1Q=q�&�4�Zv����>Eq����$��_h���^F���/EG������uO�0�P�m&�O��q��z�rom{�C����;S9��c����-��w�&6���������)�|�j�T�@�'���H�z�3D���Or�&
x��x&��pb�D�<�q=�o��������Y{�������O�8A%���h!�<�{l*zNv�*I�~
����t�`<u�{���g��N��f�k����8$Oj[���2����l��xn�*��������5����/��c��;6U�4��$S��n���vt,����[���������i;Z�d��XB����-��$�5%JQ?�`}�����;c�z����=�O$8,�q�r��oA���3���=����T�e���bN9G/#���W���{
�'�m��.\*�r?���%���H��]����HN`F�)2	U	�[���4&�:��
%/#��MB='>F��c�f�N�3;����w�UV 3}~��0����Z��O�<0,�Viu�����N��=k��r��W���yH~�hnR��?���$����l�����/�/M��6'�)W�Q�g����U��7qE���C�M��jkd��6��� =��������r��~�P���:���
����������}��/�����2nN�������k�����p�j��2�Yt�:)4�QHB�\���_v��8�;� ��{+hkv5Hb�A��9�w�#�Ox)�Fo�bVH7j�B9Z[��F��Fev�,l$]+�q��X.O���!|�=q-qw�tQ��c�Q^c>?L/Oy�'��=�h�@�������Gao��_Z��n�2B7^.�0bv��5i���U���F�����?p��to0���?]�4��>`��l�=bx��������q���{�*��N���o�n���Gs�������>@�d���v��
UN��7�A��*���r���F�U��,���T�jkc�=�^�L��S��� v���Lj�F��pg� K�;�?��pN�h����������v�f��P�Ol#t��`�����	���	��>	}�L��>��k4w��(��V����pb�����������ti&�6��m#�����g=h���n����p,C���b�Q���0E�����7����3!�@���_������1�$�_�fP����hR��ta�V����\�p{M�V2�W��
��b�
���L�elN����h��(:�&���2�"���q�g�y�!O����d����g�K���?(�lg�)&��II>SvP3mR����M���(���xno��i8V�`�^b%��U�uM��!0VT��,��D8�������,�d��V7k�
����f�eWj
��;,9���8=�9��c�W?L�ku07.9k�O��o���n����v<��6h!���3�\$Q�J�Y����4p\�1��K�������t��,��Q YS�	�f%��o��;���k!�sjY�p����kk�N�UO�czn;���[S(�f�Z��?2!�9���R&�G�g+hd����<7����S������=�����w�������Ib�����|\|&+�<����?���<y���^h?���,;�BG�lS<=5�V�
��Q���2���6��:'>pO<k������5��H�Z|2��&w��K5 G���'�k��n�%F�- yag����:,�
�E���6�,�a�'B���wip��<x��<���g	����C��{�@-|�I��yaNg����B���	�Yo $�>sb�e�T���L��'�kc���(C��QUz/��2V��~�#�\zq<�1J����A3�B�X|��W�����y~�������Bd\������xo��f����)����b��r4G`^�gL
D�q�������%�6�aP�Z3l�}<�>d2w�����*�R�g�^��d��Er�������ti�C����z��ld��-�7i�5����`H���p�d�J;}���6c������`����	hLo��Hr������E���"��W�>����ZR��������b�8�dEy�T���t�IW�"E�Y�9�?""��`�W�&��@��[��H�d,O�U��X���J������=����\���X��F���W�A�����)����J�O��46�VWp�D����q����,c�Q��a�'����Kf6}��������%p|��0U�g�iJ8�n�$�s���!����o�������w�|��g$�N��� a����F7\N����X���)�R+W7��o]�,�����Gz�.���"�+�6�X<��MW��HMO�Jssd��$=w`��G�����s�7/�#$f��{��z��/����n*�A�23g�J���;G��;�����.�hA72;��k��(�x��a;=��,��B�9��K�	�Q����D�Z&WT�U��*p��Q�m�8�o�i�a�.9
��	�{0���~�����g��-�
���Ik��C�F�VW�u�UhUSK�iD�,g�%���W�s0�w�)�X��������'9���E�� '����P`�c�����l_Y�g�M\	Z�$���z$}'�������/Z��;t�KX�#�gY�N?�!)�i'��J�sz-n�4�]+�(��q��p���S�5r��A���O�!I>LN���	�@�f(0�7yD����L�v^t,��7
?}0�2�\v�������?���������%�r,��E��?)�����e\�������a|������i��	�e���<:k�IF�V���c3_x�'8���'.
���JH�?�zM��'�����?E�6�kO���p�����l�f^���������p���������x����?��m����S�u�&*�]<i\E��uj�����o������B�-k[�r��53J~J!����w�����n�m{�`o����Z${�"��&����A
S9$.��yzT��T�>��1Q�?�������\]Q'x0;�����(?r����Og��39����8=��=���Z�Y�����A���	������P}��@�s`M �jP�>�RRh�{�`�z�d��zL�6������~z��������wyO�;1.�6�p}���i~�(�
xB�p���=�]���F	����-����^
�D�] ���K�����R%��=�&W<��= ����0Gd�������bv~�.��Z�nm&C=���nL�s{&LW�k@�Wm�4������Y���Y�i�����F>@�%NJ]���=��||�w��e�
���4��b�O$���4�ez����92Wn����<0��6��gi���-35��nY%O����|�������FH�MQD	�#�	V"����f�������m�����%i�4bt�l}�}�������w������ccB���g�a�#���(��F�L��5��y�Z��fJ����,���>]������T�"���g��(g�,WK����F�^����������
�/>-K��N�G��=�8
}�G��p��1/Q�Q��V��v�1~����9yn"<���>7���D�h���|��������t�	7g��������G���Hd*
Ne�RQ��/�����T��kfeMu�1�)��oxW\:*U��zK���Ckjs��p'�Yif�W��(�1KA��f>���VV����b�����`�b��7������Z��i�`9�"��24�e+�i2��w�Y��`g3M&�+����5)A��9BD/V���Q�Z��r#��e��h�� *����+F�3/�a�N|B��Q���T������676����F�R^W������_�O�3w�w�#SC!��N�0@������Mxz<��$	��#g�;$���`�U���TD�{��;X��:��g	��F;�G�u��M�s_��@��A��<F���5\}m��a��&��0�i�������l&	�h��D�3"��-�F!�����/_%��p0+�[_���=�~"6�d���(v���[�1����Y�q�!0.�o�
D�r�-�|h�3'�Q7T�S2vZ2����f�j��5�\�=�	e%L�X������X���!]~�.D,�
�*�.�(7\�)o��r������������m%2���D��
�����:�h���Lh����e����#2p�����$c����O����G9�!���!�ph��E������'��fG��y�L83�Uu���n�����������l{����Y4�~��Z=��}��0��4fTh��x9���L���;�����6����SN�1S�������h?*]���T�{��Q���x=B��ye-�kp �-�:a���e��/�:f��g9���C�:����!��d=���V���6��H8���{�b�4���a�	�&
�b��a������Z����,�t�� k��kT��Q��e�m���{�b��'�����)N��� �{�#�Q��t:�9q�ST.Ot
=I���;��@?�)3�2c��g�������TK�F"�v�����'����+\FeX+��vR���F�5R�_�=U�Y�DG
��1fP�(��H!��g������I��m~8��!r��	��K���*J�S�h���������
s��+�rC�17,���M��"O%��)�Iw��3��`��m��n[�=�9\���yK�.��P	�(�������I�C��B����{��'���fK����g����D�^1��*����Y�)��a���.�[����@[�B��Q	�H�)�A
�x�d��uJ�xJ_�:%�P?��avr"�,���p�h��7�L�A>��P��U����O�p��/9
�N��-�:IM�.��p��L�
v�pi�.O�%�46����G��J�����	U���99����O� ����������
�IX���9wE��~kV���z:��������b�)��l�X���B���O��~_�+�a�T�Sg���Dnc}���	#o�u,6��ngQT���[��o��C���;���\f�,�'���wD�)��G�d��r����B����v>Z1?�C�FFH�3�{##�`M#����w��*Uvs�e�ry����Y�/s�0�Lg|���Us�{{�Ob�h���ag�{�Q'S�^L%M�����,t�l���A���N2���Y�u*��1m�~L�4�N����0%�'RN$T�'��GZ��v���@���R?^;Q���v�h��L��,�r������1��~,�����������2�eZZ�V/�H���}������]��R������H��������M����L]n��j��e_��H���([���%V�y���3��X9���&�y��"��I��jm�,[{���7�C�&���\x� �6s�������.�5���|8�f�;�{����X�����w��`�I��^"	S��#��������&�B2E��s�x�?��'['�� ��9�&SIg6��I<�xk�kv9Z���������T+��6�;�D.�����h��`n���|v'TC$/^6T�K,������o�{l��o���;�v�bR���f��B�W���m:��`>R��Q�������AC
m^�����6�1�yAS?�B��~��-��L����o�����T�l����5AjhT��S
1� �)�GB������i(�$�����h�_�?f_g�����s�E�l���7f����K�7Tq&�d�����9#�gc��L�e��t�EZ��"��2��PD���Y�"��lz�y�eZ� ��(��=:>�����(3RE��/k&�bIC���o��iR�OFQ�d����:_g�4���%�S��	�����6�yz�G��D�.�:�3����m�����,�4
�<�������
�xbMs�W�X����t�21��$&�����-�p�(��_m�^"��$'�L���$��W����&V�&�H����Ks�%��J��h������k`x��u��:�v�W�L���1S�?}9[�	�a�!56���l��'�0t��Fs+����6<+�J�n�&A��p��c���.&�����v���P!�^���I�����4D��HbI0g
E���'9�/�hN93����6f���a<�)2Ym�e@V�a�d,���� ��� �{RW�&���,,�rD���
mU�J�i��TO��8T�����J��7b����<��7���
�x��i�
�Y�G�'\�
1��%C��	����I
�5��%�o�t������I�g=���Y�YoL�G��A���r���r _0c��Hp�/K����$>@cv7a�������*y2�J��3�.o��[���������oe��\_�`���^$������=Wf�p����3��*��*jo5iR�T�k�������#�U�o2�����<M��������:�����M&f3���Vj`N�9Yy��bx ��7
hQt���|A���5e�������NY��g'��?�'���"g!������R�HVex�5�W!U���
�#[����d�E,�l
j4+���-}�r�c�z�uO������|��H��Z�&�����#I�����h?�2�t�}���kv�U���Xx�>���:��Q4f�6	��k:������+I5���p��Y�wV������'�I�l��Gg��Wv��=
������-[k�9<z�ub���I��2AI�wX������f�T�u"@�m�Q���R��B�OCF3�x*����JV@�7� ��7���J�B��WA���w�p
�6KY��oKT����������������������&����q{�������W*&_�����"�,u~�f������Q�������!_h�L��6n�*0�3_m\I�g#rn����!���d3�>��,u\RcUJ����z,���8��a%�����BFz}���������<�Z	2�WsL����:�&�}�9��qrRB�����[�3���8+�\	x28��K|���R����[�9�\���_^��?b����O~�"�����g��w�"��-�d�$�4��>]|dYK������f���d-3�V�{B��>�]�'
ae��$��
����>0�2������:4�����A�M=YS'/!��)�U�<��������2K�_2����n���q���Yd0y�-�}$����0��������g5���7$g�@���e@O�@�%I���A#��P�O�Qyn���)�������&s��v�K���0���W�����AI�T9���3~���m<E�s�P,�Kaf���I:=��o*|�9�W6q�$Ii�p\p
�O��r\��(�E��VZ��59���W.!rPsd+����e>3����Vrd�I�(^j��r�2�;I�D9�%�-�~��!h��x��R#W��5zm���|�p?m+q��y����C��~����h ��<�"����i��N���Q7q3��-2]��d��<��|/��<��<�V�dd��q,|�����y8�#��x��L�kDl����z����@)��p�*};T���C/���/8���:��/iC�ZI��^���o�X���`�]���H7EJ�a�J+�5�h�I��E�/z�A8���@F��<��!�.t���R�t�g��.�8X����Jbd��
cG��W`v�^�F>R�h~�����l��y���/�	%��_�$������H+��8���HU��6�b;�Y�����X���Z��mV�d_�����`j���������nZ/_������W_a&L�p�E�
��y����u5�
&j+�DhG�,R,o�+��VZQ�D�_u�Q���+�P��,�=M+j=9�k����$,����(
���\�k�JV;3N�Q�{2>���XE�kz���	�����4Y�)����tke���xR��=�1�==W�������������wg^�ww��>�=�)�~�>����q���wJ�����:<���'��8��������{�po����������3��3����3sw��k&������`�Q�R�|h<^�t�)�e��koM����(��d�(	�a��F������?��H���F��iO����`����R\�=��'��T�h���^=�3{�5��6.2((Y������I%���
P�����Z����4���P�\UW �~}fO���<L7������
%U��1K?�^���hL�_�n������N�is��{`�7���&
75���2��oI�E����Vt�Dc���TA�N���%���1�����������M�h����#���S����jA����LY�<n�24O�z���PP`FL/R��^��}
i���a�K��J�E��M�"m�����n��,4�����rC�80��~�����>{�������?96��M���Z�I��r�Z�r.����r4�D	��1���M���+Q8��)L(G�y�d	�0_�K������e��YC�A�=x�h�����y��7.�H��2��)2�x�.�q�+����
�l
�Q_�����`���Nv�\<V?��h[F��~n��*�%�h�+C���k�;�#g������
�[{�"�&6���um�B�������M���~#�Y�sMK��)5�fA��h�m�<Y��.w�%}?�Y�Ps�����u�6�;��@���|��%�8�6�x3/�5�y���^�- �s
r'A�J@:�4{Pt�U��L���V�9
��CdI��&�{�[	���4�~��]��#����E�x�e=�����V�;)��^������	�t30��+��[b�H��O,����K�.j�"]z����^��]9)2N���E�O�wt5^$O���l�:��Q�3'�l#&��0~�5gf<&�������m#=�?�rpa���{�7�"���/d�P�b�8s�������+A�D�L���[��`�����&J��cf+!�Mf�����m�b��m(�c�B��9�D�V�dv6�y�t}��{��������$x�GQ��d����	_�(��[�DnmtZg���Z+��U���"gZp8SUB�4� �O%t�>�
�[t�n����1��esUGq��,925TF�z�fk%�O��p��XO�Q�3jZ,-�Y(�Z4 �{J�+�j����*#��O�
)6������=�����*�O/�����Q�K��4J�[G�����E~��e������U"����1Rs��~G�YCobj��b94.��E\��XF�,76����e����U��k|����������I�I����������������m#����p�A)ws�S����]P��Lg����
���������I����x`�zu�9�������j� ��UH;�(4�"}�#�
����#n?QK��za�l�!����P3�d2A|���UD��'T���t�t<�H��"��PO/��~�k:�:���#{L�v��i�i�-��!�#��w�������#9�+�_��Xm*��.7����I���]��`+�����?������R��JP��_�k���|�e�.� ������n�%'c��!����wL��['�F�/�l�l��Q.�����	�Q��f�<���� gR	���.Q2��]}�K��Wm���)������ �r��������c���O���d�I5<
kg����q�~V���M����%����a
��j�r����}j7F�/�����������[�Z25P���y������z����m!��U���LJ�`L��iV�$XP�&���xE�jec�M��&����1`(Oi
��q�C���d����$�F����*�0���5�4�Fpx��J�f� ������M��
~��J��z����SP�,���iXi�kk���Ym6o\<EM�]@E�5�}K���t��i�Q:�P\��
9M��:�&c��E���>�O�����������27%z}9_�D�U�����?~�dv+912qKr�M;������n���`a����[����r������'~��{�n	g���|"��'��P��A�Jcs�4�����*�����|�������9C6$D�oU���N�cz3q_�Jd�&�8�����|R��{��JH�oI�w�nwN��4��U������8y���k6#	^�o�����Q�)'��	�`�,���k [��9^���s��J�S��k�(�a��I�<����v�d��}v9$�i"�2��{g������I!��M=�*��`�~����8I{m3bw��qH�M+���!>1sO\�xhN�s�k����� []f�r�U��a9�����*t���v.��AOc1������=�F+����MY.�m�LOB����Pi�d_
d������hjM�&������Vn��)�����Y�a���N!U���Z������Vn^�ZOB��%8���"UgV�1O?�b���=��j������X7�rb�E��Q�$�7�aLp������K'���SC,U���|=�4�OpCF�9��H�e/h���Z'bl���b|�N"y��q/J��F������j�\S����Q�7�������N�}fo'��{+�8H��$r����xON�Q�����h���Y��j*9�!-�po����3`�M�G���s��G�t���^w�w5j����I��d����h��6�|s��X���I2�3��M=�A�4u+d����R�/�w���I_��quv&}�(�����>	J�r`��G���[��1�������H���(�O�e�/1N�����4+����6�k ������?,U���K�O�C�e��Eg����m��s,���oI�����<�����\�������X��[�������-u���5���)e������A�S������i�����"go�,��6E`����2S4���N�&��}I��[�b�K�=�D��+WC ~�=m�'1	4���!���Q0g�eqD����+�T�*��L��Y�����7A�z�����8��hG�ML��M����jK�a
���L�4Pl�(�Lx}r�up�	���l5�R`4^�f��������J�i��]��zv�����ZK^0z�Qd��q���:�w=���1)8k�u����=+\���r$�-��nI?d�f77$���F�����Y|;�;�)���BmK�$���gpqH5n�yK%�w�h�Qn�������_�-�8���������.���������
���:�C�8���5~��A����{%��X��k�&1U���������Z�$���Vk�Eg�AR���p���v��c|?�k��?b�
���E����./�������i'l���mnlt7��e����Rw��fYoJr����'hND�-/5�f�]�Ai'��?��/T��C���l���[�>���1FM�d�����h�Y�r`f����$�XMw<]O������6��p�}Qc����A7B;���~����������9@�WK�*��S�^��J%\dU���|D��*�	�Y�
������E~7�ao��`t.11���l?��q��m��X�w�w�O�o[��XG�n �f����sI�R�N�<���_N��o�K��qbF�y5|������i��&n�>4^t<��������G���)��W��Fv����p����;��AP�����
�����Z�	86k�r}���Qp��~k{7�Q".|����h8����d��D��t"\�Rm(�u��������g;��h�Gj�'zg�����C������G`��'�o�F���������9)�O�^��G�?s���s��X�����|��=�E�����%�2&�O_�w�G GU�>���{�2�+;y{[;{�v�+�,��K2������A��'ir8�*o����C���w�);��><�y�4�/�5=`���N��)����'�������p�E�G?��i������O?����_��q7��3�`:/�U������g!���?�Yqu���X�����:$�������M�*��Dn����f��7$T�}���^�3X�������{����5F���C�(Z�lV)��_�@1T�Z;/G}���U�$D��Ae-��&J��!>p��g2��4�������K�v�&1�O�������&��p�v��^�v��K�����Mb��
���v��d<��@f����+��.����X�m���H���Jg?��9�t�*g��.�En���.�iu3j�kk���F%Z���6�`y���:Um^����pt����7�CP�������{IIh~����m���$?E�����b�c�F`8���������!�C����
��^_����%�:�,������4C
m�h@�/bYbw����0K	&��7c(�0��[HF�4�x
���W�}#98"7�	���,�M�� 0f.c1l}������9a���Xn�oG�.���������8QrW��l����i��yJ����E�'#���4�{~��,������=��_�n������J�����nn�.��3�,X��z��.�a�3\��w�.�g7�9���6���`�n�����w��.,� �X����U]��p�=-1&��8�tOU(��@iwk?�������4��F�@L�f:c��&����1��a��]�����	��h���I5�<��
@���fB�O�U���7��*��+b�����������c%l�����"#s���{����
��9�\)���Y\�	�R��O1�T���6f��O����*�2R�s��fBI�2W��� =di6"�YNf�L�<����������������d�����m9ze�m�+7s������������}��;h8��9���� ��IF�p6-(���W��Mv#����$If�MW^*�+eQZp�(���kb��@�z;9i�{_v��l�9D_���t��B2c^����M~�+�k�y���=q�[K�ee��I�}n�qml4�kk��[�l,pN�ma)N��7���D����v�~{������!@]�GT�~��F3�5���d,kK��5�j�T"�-����M���O��f<�
bAQ��3��2�4�Sm/jc������'�Me�#�G�~����a���U�o�s�s�`Z�L�}n]����Y6���X~�M�<��U�\ur�����b#�jR��<�<�v.�w�Mw��IK��KgQ�<�0O�������Nf�5-���������vNC+�������t���KF��l<�G4�D&�z���A�4t�a'q<I�H0d��<%lu��-&�hd�5�mX�h9%kN�����������9��^4������n�$���m�d.�U�?��Z�����#C�q!�������@ztL]���e�$7�n"�Z�����f��X�wO[�e��L+7LS���k�1�9����B��%�7����4��@�S�0#��*
��?�U��;g�mh��}F
&�����	���h�#.,�x����0���j�4`�����
��<O6L���4��|7YXw��Hp�������r	��c�k3����P������5��,?��3�Fx��
6��"����va��p�f����mt7��Ym��]���"^\_$�z����G��io�GbJ�K 9�SN^�3	��%����b��C*�<Y%u��\7�K]%6�����~����bF�]�K3�y���y�q{�-�#9���4��o������TZp4(8d�a�s}zH� �����j��������X���F�Q��n��5������hU��,6VC������x��m��������z{<���;����y��%�xE�X���a�x 3�B���_TO���?��`���cp��(V��6]�Pem�==��zg��8M���x�
�{i2�MGg�!d�����.��D�����E��Pt�2���^-a��e �������8,���D��Z�Z	����n���`�/r"Y�!��RC��������-�?����oK&D6������{p��fo{K���)m���>��������E_���=���4�����������5~�V��R�F��D;O���i�n�J����cC�s��t��az�����.�2�����h�ie$rV�fM"P�(w��E�PB�A�~{ !0�i?2Ob9
a�f��5&7z��%�����8�z��%��F�1��de7�b������P���P�j8�&2�a�U2������0�XI���Ft�
pI~3Z�D�@���(��6�m3�w�����n��]��+������������;-j�]t��I�{���fK�'h�s+MI�.���9]6����D�x Q4���Gh���0m,E��Y�c�,Qn����S�H�r�A�@l#L�<^�6v!'[M$#9�,�"���%����K��O��
z6�sxR�^��o�P�+�����
A����G�c��Q��z��po����N4B������
�!��1�?�����cu����u���JPm������2j������T:v��H�������
-5(]��p&?zrH��Q��m�����&���*	��4����+�y���#��X�����</��>k'1n*a��?��m��W��.���SC��g��sn�z�sysjd����2�{n�:���t�e�#�����z.!�Sb�&�lO����d�h]}6L������T����^���G���mT�7?
�����lP���b�'O:������'{��9j���\������3G*���@�I ��-������\,����y_���z����������Xt�#6�n�\j��M�(N$�2����������b��}���D�Y��n�z�����6���c1��9�i<��	*�t��d�����!��ov\	����f���*JX��J�,���*?������3�RO������~f�������Yb+2�9>f%e3�Sd&}��7��t7�����HB��i�^6�uY�rd���d������<�txI��,#J:Ei
��'!k�O�B�/��+3M��;����|��A���������9���I@���)Zn���U����D�f��7&�Z�Q�5��U���J�#<��B�I�����_��NV%�H�������0�hk�Ns>����i�D��t�mw����-!h�v����pc���l��)&�������E�������y��d�`���r
��l�6l�i����}�����A�7���O��T_�-�5���{<�-:�`8���q������|M#s�|!�����v o����:���<y��~;�����=�������tN���'G�3-K�����{���g��4��[���	��
�?��������@�Wb��z2��s�O�����$3s���+�f�%*,�D�MI�������l�_*.+�M�7�����Z�I���I�6��A�8x�Y;z��m���i�HbW��m���2t�U2Y�h@��<4h����=�i�i�(��Gs�=�..�Dn���W��>���������5r�)��aGc��	EO<���ux��$��s����������~$
qG��
�<�<]R�����+;���'�#m#t����%@�x�e�����}nN��������?��l���zk���ss�om��=�=���������j\���7�,~�������
B��q�f�U@��,V������Z�w��r�R�f,�,3](���T��Y-^�f�o�e<��5������O5�ow��cMn�k�D�*
`}j��]sF ��LFn�YKBZ�"H��`���{�;�7����y����L��B��"��{����=�M�Q���D�K����O�h�	Si��#��S�~1������K^�mE�q>]��j%��&Z�����g��A�~1����/�f[�SI3��/	E|��]�%�a��-	��=�Ku�$��:�}�1S
4�k��*�:��W)	�$��o�?�!��Y�m�Q<��pL�+��g��I?k�������e��f�fp����A"�����4j����=� ����"��,[H;��h��3fr�����T���V)�cR�L�������	i1�i���g���6�[i�n����Z��t'��;��$�F����f�S8�bw�)~&�=�I}}�����U����0G��~cad�z����������
`��~��|��������E�����t���z��_FJE����);���s���e�RO��=�|�i���OM^3���%=��`�.#�&��y2�s-��I��	��*}���q��������#[�� ����@"XmiH�M�P���
�I�95��F�TNb���\����$u�f����8Nw��A(�������m+��Z|��k3����v�l*,4z���t�I�m
��P6�_�qbxesL����$Mf�3������~{�������n�9���{R�h�NF��]���T��%$O�����m�-����!��e������G�<.�����]�f���vkfzmm`J&b�:���M�
e�vX�}'��q���6�k�����1��.�f����V�����U������*�x�m	,��b:��i7d+ux�j#z�f�r
�������	Yh�������x��LC	����r���7�~elz��#�����X�p��!3T�!����\�����B���5�$ �@����B��]�������j�n������{";_���Dg�p���}��������M����eLS���I�&&����V������ma�)��,#���B���`E��~�lOvlo��(r�a]�;�nVH��8��Z�DW����qimE:��#/zm�'������d�H��+��Y�5y��J�������X��xB�1D�;2v��5f2e�q�R�m��\�M��:���\d�Ovw����<"��R	i�p:���M(hn0J��B�\2���)tf��������o����|%���L&�~�;�{�_�,�k��������m�e�l�H����/�������MZS��9al�=����Z=�F�zCs��1��$*�#�����<+o��uI�!�O���$� (��yN��~xM�s	��y:�������W�4�'�1���o��������{��7���L3!��d�*�����~�.����4��������#�V#��Z�����G�uq|��F�������
��=E�V&�,���L$��p����@l#r
T2	0�cO]�gt&.z�{-H��eGo��/�M����gR6+��5h��I�����!�2�JO����vVO#���j��R�v��H6������O��������������P
0M1�i�������W$������+�LT��Iv�j%�N���(�)���ea��%����<_��]'2�c���M����A��h���=�>Iz�9����6�_��t�H<�M��*sif��:�H�S���������Rx���W�"���=�P���������N���6�U1���`��:��'���8���N#;��Ld��6R�
B�#|��%�/�P�.���
���De�&W��U�X�?j^5��
v'�/���Ez	����������[tl$��/2���zz^pu^�5F������dv�;���dIg"��4V�'z�	csj�a�#�P�.�T�s��<i�����t3�p��qm�AvJe�^�|���S�TRqU0����T(�h��^���rw�3Rb=R5��DO���F}{�����=�X�Z�mPG��%s1%��Rk
:`��qdu%��(��W�BW�����xL���Yz���l�g������H���/'\"�>�o�4�����*9������A�������H�M�n�\��Pr�$��@e5s-��r�1�������M�Bz�T�Hc�	���]���<d3=�����?��D�� f-����ew�v�j���������6yc�jh�g�9v�LR#]�?�F#��Og03L�#�I#Yv��D�o��X�D[��t��7�3����b��Z��~�{,��nM�C�Lj���6�RE�ete���Z:2����f��MT[��(�y�����e�������t���tU�i'K�\�&.�h3yDQ�0C��\Y���i��tk�)
��y����<��d>���k">�����$�I|��![�6��s���c`�2$u�$�,	�f��1%��� ��m����W��������w����9+��x�X�s��@���>����0��6�Q��ax�#c������4���S��,,����M���S1�����zA�gO��f����c::S��JFG�6�N�8�M�����3�%U�W_A�o1��%cp@v��|�"#��zd'��&�b�e�����&	HOm9��M|�LL�������H�2�%�������,����2����� f�^S�@����vcC�_�����������������`b��q}@
P*���$X"�/���~5��x��n���;�^Pv������z�3;E��y�A�F� +�
�)�K��q����k���{���9A��>�������T�um.&
�������G;�G����I�B������3�.}k_����~ 9�����D�3�dBi��F�u�-	�2������-|V6�N>��O���hi����<�
�_9<�����iz�{99i?���:R�x�3f�������5�eWt�/�q�OB~�^���T���9+�?��4*�n��5���������x����MB�)���D�fyi����h�-�6S�ar����!3	��x[Z
�f@��7�.��u�1�^@Y�~��v�������>�<���Ew������r�%%+3t�~�x�Z��Vw�����d�W�l�=S�gzfZ'��[���W:�_�����4o?|M�'�,�2��H�f�r#q#zQ�N5o��5�hu*�iX�����������n�S"���w����g��]�����E�/���~�F���g��ag���4r%�6t;�s�0-�c;]��	��������~�Y��'y���F��=QYL����u�Bln)�jn�us��Q���i��s_�Z���:!��9u�"�Vv[�-^������)
?���f|a,����>�������b�E��d|�]O�n��]�����:���#��+�1�n�`�@(��yxv���qPR-)4;�fl�iX�2"����F���6R0��\5a��`u5+�\f7,���Yqy��Yn�V�!;S����\�����8����(�~���F(�6�	2��2T�\��v����M� �p��3�As�t[)�w�L+mT�{$O�yC���h�DE��	&H7�3�k�1��`���{�QK]�G����/����t�=u����f���u�(��'�s��>�F��Rd�5�A�y`�*h+�������G	��5�g�T�&��[����������:hQL��v������B�Y	��?<:���{{ �����������JB��tb��.� ���0�;�;�Jk�z�D$��#|5��e���c�o��Y���<H"�Cq�M��^�4���(��:83*�-�����am&9�T<���v��<IO�c�3;|�[�F�,��FV��I.R)��vt�>���]��@]�x�?����#�����b����o��^��s�$�Nu����3�}��J�3�o�x���b,=��)&!�a�Htz8�r�Z�hWt�!i�Dj'��Ew�����V8LeCzIy������d9RJ<&�g-����idB^��`(�_��a�����C^�^47���[d�~d���Y#HXx��3�DN���1u�V~C�������]�9�����B[���]\�<�������w�-Ig0���,�\�Rj�����*l���A$��F��
'7}Y{3C��*)M
�Y4Q��LU��[�R��y��,EMgw.�\�R���Z�l."�k	���v9#ll�e�F$u����OO[�;e�H����h��&m��s��ily7�}a�����7�.[�m���p��J�v���_�>3�$K�q�+0�m�d���I���Z��l�84����-M����	��x�� �S
[=�7&���zl�6E/J��b���
����J^�h�	G��O��#���o[�Q�����L, ���������rT@�$r�7�cRo����A�r�0M!��-��z�������q�t�P���(��g[3���p�#�)�p�.|L�9`E	!)E�z�:2�T�X^D�1���Q��Lst�6S��ud���@vmN
���@2y���iZ������#�<L����(r}��4}K��4':W�xFO{���I.�p@s�$�Y6����M�x�]�x�����g���U��L����I����@�N��Q8��3/O'�~�L]�0��pB,���j�L����e~0�ew<��M=9|�r�{��2����+m��~��M�@3k�y���Bn<��/�P���q�0� �\�����_�zm����~���d���p<d�x�;�m�����C��{��������$�a1�q/n�1�=�b��_?�88��l��'�o�WE~:��y�o���ScN����&4������K|���57�u��j�	U�Q�#���������N��a<���Z�0�L�F�Zs�Mm��C���
>��C
��s�H2s$���$��6�
�/<&�/G����M�eY�R��?�d*8�cW!w�xj�;r��������[�Y�b!�t�#b
����n����;�����ww��
���w��WG���a�x�d�MNv�����y�Q�ir�A��WI��G+����������U���Nk61����c��I{�9�sr�s�������d�3�����B�fN�<�d1IN��_3��2���9�8s�&5���g�7��31��1��G�1#y���]F��%�Xz��0[X,.��X��	0�N����!j���
(��h�iL���D~�Hb�F���
<�8��*��Z����Jz�t<�(K��<Gz�4�f��s�D�X�iC��S���qA�I,��;���8����l8��'���	�{�Bi��:���:=!�="qd��7aK+�#�����G������?<:��Y��l�s���YL�Ng�dD}z�$	S(�l����9�s���G��(J����������e�?��;�>|z��=��>��<�
Ce��9=�����N������<�X_���6�C��1u�����4��bz�2����M|_�au��*5K���u���a	G�r c�pMPh{�U5��3g$�21�����B�o@�1�t$q���	^��s=0*����hV�G4���E��d:��|����n����#���������I{g��������������]X���7Vz����)��6����*9��su��|F�	v�R2F�����D��7R )J�hu�G���sr��M@�A�NQ��4������+���[�~*!@�?��K�o����$���t�MR�/��	.�XS�Q���
M�C:�����)��J�����d����(vC*�AS$����o��D���kW�^����5���K\7��3=�a7�S���������%��������`����O����b�����p����3�^��=�__���)�)
�J�w��E�	���(�O�Xc�b�.�45R���?d1r��d+0:����+��O�g
�	9pw��{�I�is��A�K.8[��<}��'r\����������Q>�i�v�^v����v�eb������19��LM��_����i�
sV���F���(/%F�)P|�u�>�_H���I-����l���U��{���!�z�Wd��	3a��r�!�	��@�|f)�${O����Z�A6i����<�7��4`o�,_d�4���,_O&���V���D�����D�$.vr��H�J�5X����;����Y,��aT�s"����'AocPD7H]$�%��O��p����s�H���t,F�l�i05/w�����9;D�y���"%Xew�s�Q�1f�c���T�0X�T9_�L���D�[�������_$$.z�PH��\��n�f��X$Y�`J���Yy��%^��;���o���y�\�k�>��}�W�(_�
M��J�.�hHv��#��]k,?���
>r�����}�x0�3�������R�$���{���Jy�V�1'�$��������?����(�:%S	���,����7���Gm��K��BdK�N����7�?��'�g�L���b�.3x�PM	(����V�A�P���fff/vV�Fk\	������p�
�u�5�.�8�2���C�������m'.��%cf��6�,��"�5v��	9�3v�1��t(�#��'�<<�H�G��+���|9]��9�W�|�����`�����������?������jP�4��W�p�e�|�%����.#�f/�$����sh��;�gI�Ym���}c1�Q4���I3R�����0n�$�-�x��Qb4V�%��m��2�������4*� �` ��!��Z{������1�����:U�T�*M��(q�&�?�����|0��8�G�m+�����+�D=3Z�($�d��jZI�
qF���a�\
a������^/�q&��\���
;����4�������~4L��s4�~�8�:l�*Qi���������;��e��l|���b g�����'�'t��Z�i���~B���������Lo7�&{����l�+�Q��<�n�Q��F��r)uw_�������<�u�^�����T�E&����Qd=����H�����#b8��E5Rc��}�R�C$��c�M�Fh���g�d�u��=��NB=�lJc����X,+E��j�)���3���p82-]EXb���^'�i�����It2�*.�_��VD�Z"������cV(1��V,q�)l����i���z��������h+�B�g9�]�XBx�S�k��v���vlrM�a|e�-m/K"���u���4����{K������p|�+�Pr-��VK��	%KQ�/���������0$���R�"K���-��w�>� ��
K�C�%�+E&���0�1�&���j��I�����%�) 1��4v�1[������%0�Sy$IJ�&���-���*
�$6��%t��P�����G)�+�}�V��"q�5}�+�g����C������21/������x�����H�����N[f��R��"iF�h��Exa�U/�G?���w�~��
XI���U[�'�H��m(���D���! �S$H���y��RL���P0�Or����*��w���No<��9�==�b)��W�=g#�`o?�)�
���4�d�l9K%vJx9i=�B���xH-�k�l���I��{!k�K�D�/�4��j>����~'��ku4�4$�J�hN$~K��\�h3fT�+j?�X3����<to_���b7����K����
�E������`]n����4��-�`�MN�b�7`z&f&U�_�2��L�L�R��D.f�FtyWx���_��$`:1�.|��5�+Va��%��KM�j��-��5M3E��e�dj�]N�g*L�dQn�q���by8�b�({4
�����	8~1���������7A���������4_�P��M����D�`�/d��$�o�p|e�mK��r��h3PPV7Ak��t.��������J�vv_x[M)�9#���O����Pz�S���;�U�CH����;�k+��z�F9y����+s�i������ba~�6'>�H����^����-��?|�3����h3o�C�7qBO�QS�h�A���m���-��Z�~�
�sH�%���(��n������s�\��2�;��1W��R3!J�{m����������U����yx��8O������DT�4},N�V�c�B>�fY�><8�;>�=8�d�M�Y������;���+$4����-"���=������+�E����s�H>�lC<cf�dPc��T�5Y��lZf9a�c����dw4���u��p9&�UFXN�59�%E�=qq9yaA��f��&��;y*2}s���x���J"b%q���V��R��
M������=:A�,��t4�7��1_V`�,17��z<,�zL���CP�$��$e�F�������&qRt%LY����~�:x�~�G�-���c���?��d�!R����S�N�7\�SM����������l�6�W"��V�O�N��%#��-)�G\�E;�(�'�fyY���A7�Ks��\K��B�:k����O������v1��k"�Q8���!~j������H(H��e���s���a.H�2~�w]`g(zz����fcJde�4�aF��DMNV��l��6/<��6��:�N�kq
*��q��#�r���W��"{��g�������A�������*���+����m�G�;�$�+,u�M��fnj����y��n�qK�!?��`r�~�����������1�����f���L�Y}<7�<�0k�,sc��t�A���}��:�Hk��&n<�(�nOIFQ��/=���4��R&2����:��
�E������J�@	*��c/��z�~�����*�LxY)b��|y��0{�%Q����1	������f�rV��=8���a�N��d��a$���?��m��x����F�h���\��|'G��?d|����B�C��f?|���r����O��Eu5����4���n�x�#����H4�96d�B���p�x:f������S;h9�����g�M�����KF����(�������ek[7�����F{p"�9���i�����]X]���N}����ST���t"j��u�0��9bi�'���P������TPl���'�m�k��55�=-s��<|d��QZ%�8�����I�3g���#�V?)�R����dr�JV�@M���-�5���B�h2i0H�*=&�a�D_��>��2�&�s5zf��s��*:	�8QI�����,`�$��-�������G����)�8������q&h�F�1����>������n�&D��o�n-kVP*���(���Dg6�=��_k��-\o���W��`�����<���v*>k����h��d�Z�U�c�N�>��>�Y�
f��ce���YZT��-:%07q	�(��1�[����`�E�n2����qmd0�F�L����d�$�����;-�/�w�Pp�K�v�"�y<sL�u���2>T2O�c���"qB����1�F<9q�S{�tT�JM��_12������I��&��Jr@O�15��_V4�����t�����e�����w�0
�f3�;����6'��tSNO
�h�%������@1��bO��k��1�u�2~%Jc��cs���������(����	~v������4�V��et\����nd�k��x��2R�;�h��#7��n��,=!�xCIl�������Ib�V?>��$�5����l��h�w@�n����?2^������~���g:��/o�c��N��Gf�_&{��J�Et���1���~x�7��J�Jv�U��t(��]���f��5G�i�^���5��%J6_����-�}��W����'�_f��b�(>���=.�3�ytV�o�o���E�������T������q�z��P��p�������t���}�=cX0������9W&(Z����<�ca���l=9S�.��G��)�4��24;ID���!�e.��j�5��{g&���~r�=$��O=���m�Q���T)
f�}��D2��eTs�������u�l���E���>�2WK�#p b�Wz��n�G����zh�eN����M6dn�|��a].�NH����9Sr��\�-��'*I����$��a��F���u4���)�����_��pK���V�5�Z�2�s~��G
g�1�Y�����wc�(��\���w���i(f}5���e��v��{N]�����,/*bC�cY>�����,9�N�������O��&�)������Fv�pC79��	�a���Hh����4q�]�X=��`v�J>f(����e3��w�����a[?�����@q��'z�C,���J
B}�&g�hl|.+�������e������ ���^{�C7���.��	
��3/�x=�������������Y�3m<r��\u���W?��o�h������,��G������^x�%X����+��}yg��?���J��;�Z�,y?��a7�'n}�^�#'_�c�R��7PI=2f�1��'�A�y���9"I*�������04`<���0�-��l�8Q�f��B�������r�6�E�y^KBe4O�<M=��R���/g�L�O
��M��	��������t�;��
���R�2B��+�e����������{Xb]"LO���w@v9��x��U�
��a��kU����@e�Z'<��tdj�I�X��&^�
�
����P&�N*o(C�2��-�q+&�����d��M3`���H46�[`�����vv��w(	D���M������Q��*N����m7������d�j=�9�L�/HC:D���t�-�M�Nd����v��$
�"���T|07x�_^���L��?������su�y�`��w�s-+&���}{�0y���}sfI9��<�b�_�mA�/vt��$)�ym�z'S�[��.� �HW���*Cjl�t���
Y�q����2�
������hqd���Il�y�|B:�<�fj���� p{T����,���f:p&��"<����eJL8����8�d�BlM+a�S��&y��b��&��#z��~86����K���@>f��$������R�����N`>���,I4����&������1.���b~�Q�`9]*���.��3/���>��}5�e)������w���s�m������{������d���s���W��F�\7e����-)�MF*{PF}
� W��`
=:�%��6b��f�������O����v�N)w�����!��[���<���=
G����F
�y6:o3�����9~�(E:����|��g����L�}��Hx��=���>�$	�?Dg�=���3�M�a?���C�k�Y�`���g�4�q�������v��8u� 
������C�-y�%��q-��"?_��;Q��.�w^�����7����B�m6L�Q
�+�Q(������z@?{�E��9g�S{�)���K�����^�%�s4tL�d���`fN���b���
9�7�G��N8�^�������/��#�;EH�d��Hm�!�/��4����"g?�O.��m��r���+<^����	���,V�����9:����x���4g�Y�����!��Nr�vD�����nJ��q�,0}�0/�4��
d{MZ&7$b���
C�CLzMdJ��m�K��d���P�3C���w���@b����v�U�x�F���yV$��
���V_e�L�QA/?E���u�����}��������2�Q)���r��g���������~t�������a[\�h�m�������$
%���;�1���Lo���^�m�����/-���f�R��)�V	h�d9�$�e�U;��9T�������6�uw��!R;��F�N/G�D��(L'��Z�������&I7V�@&F�3(��hc*q5�^|���yjdC,��?��3P��e����~�<�BRB��
��{b/��B������x6���m�g���8�7��_����$�@���������y|%@������($v����c��c��G��JbA����&�3i����^tn�do����3yK���/���qV^8V!;�������������p��������~z�������X��4\�rI�<�]	5p���n�z���������Duc��v0�5<�k���;YV����`�k�>E�6o��v�����~�w�u�7P����$f��&��`�����C�fp�a$��$��Tm�V��#��?��ftP���N�7q�w�5g�zr|�K�c�.�O�4��$C��	�����������-�I����3
,d&�>Z�Q6����y�/fb!8x�}�����P�=YI�������}�{�2��x��3�7�rP0�v6�Y������QY�f���@��L������
���p_J����F�t��IB�J�L���|�����z/Tv�9B��.�O��@���#�4!��Si��,�Y��-�BP���
 =Nb�ea]N!]6�q�M?��
^z������pp��N��J��:i�}(DI?�h_�0Ou�3l��Q��e��j��h��o�a������;��"9C����x�x��j+�"d���-S��
Lyp���{������)o�?��ao�mA8�K���2���H ������k,
�����tW���	m��~����h>�$����O&>����t�Gg��*?���6m�	���
.���Pr%KL�D�,����:0��S��X��������$���j���&iIr\c�)�a�r�4��&!e��H�+F��)�\&C���Y(�Q��
���8��pv���I2g�0��:%<��Q4�]/�����IR�oG��++��-` ��rK�/B����!;v��d�bP��h���������G��z6=�J��M�XG�~�;'�{��!m~&�������4�b,�s���W��t�E*�Vg�3+:��y>4��45��92�$ �s��b�������F�d��x-�k�B;����
����}��;<eoo�>��m^������G�F�i��u�t�����f���cE\�;���#��������l*����I��v����J/f�H��N
a��N*/�>I���������V����y����J�>��^���r����n�����T�����c�m(�SYJ�j�R�w�'?sK�6�$)
?�P^�l^�~�~�?����������� �I���F�mW,������-�t7�o����^���mbs2U�xnv�m��f���f�J'K����#�(s�y��8��
0��|��~�Xki�#��n��W��n�e����.���Oi^7��<�����q�L���4�s���g�5}�����F)C��2����v�d��m�iK'�����h2�F�[��&�$��8�HG��e���A)�`�t��Fh��l9L���64��u�(�o0�w3Y+������
V��cyxxS�O<��;�!w1�������LD�L~N��O�GQ�c������/�#M���`o�&�/W���`���'���a��q�����sue�j�,����S9��[��6���/��J���h�&�>�������~J�,��Q1���[�v9�`�-��7�['�v%O������NvwfR�by��9��R����4��m6����7�B�b&#�r0���Wr�6���`�mp���]��`����}�i���n]���v�X�B���k�jP�(h����-�8�����1���m.oA�Q~'_���/Z��= �X(3�S����K1F�'z����[��HT�M���o��o�w�|8�no�{�d%�;%�q����2���JB��(h��6�����"��%"v��������������N�1������w�0�
���4��(���I;����l4����,���"�y�2�="�7�i�[a���h`5%����_���\���d��Y��;hSc6K3�jE6��6X[�dv����+%p��8�0�a8�'/���2����Zt��|������5����j���q������2/l�d�����+S�v���d���U�L��v}�{�l�� Y��SW��;�7A����W-44-�p�����k�L�^�#=����Fao��VP��&	���o�������A-o�#��dw����>�+���^J����/������K����Kb�K%�������$�d���v�����J�4��4�������]@*��F���������L��f�-i�8��d�h$�Q��1��3^��sU�]���)�
4���9���X��Bu���*���:GMB��*�(�N����K�;�����O4���tr�7}O�N9Jq������:H����������2���N����r��rR��L#m%�9�>��w�}*%�4m���)�K��8������f<(D�u;�p���I�����{mR�[�m��r�4/�g3�1N�W}��b�>���������`�C���U�v���G�yTidh �[��TTr\�l�(E�����~��U�����X� b�I�`/�w|O��m:�%"������9c�������}�������/���'���1'K&�J'�]��\Vc�/��oaF��t'���%�y%��������T-��d����������r0���<G��b����u�"�]� {D��������UR�X��b��"��pJ��7/E��Z�p�i=Q�)Ge�L}'<0�z3���d���:���a`?
�r���k	��v�|t�c)�qqs�`'�P3.F<� � sXo�d1�p�>��?����{i���f�qS���l-(}��Vr���5�Yx���qN��
\X[[y����Y������-s@v6$b�s�$�p����k_I�/���O����%#d��r�=��i�e�������@��R��tW=���k�2R�����{vYH��qY�b]��p;7���q+�x\[3h�f��h�
�?����q�����X�ML��)_�-���6ty��u��Mb��c�:��N��N|;^Z�l�j`p�UQy����N��Q�Q��$���)b�?d�"���I�����-wRI����?r����?p���u�]*�G�Qu	Zs��������g���=�U�O�>'�����X�O�^��q�m���F�����Cz���Y>�'2�8<:�;�g).�p
[	��Az��hD����>*�+�������07z�t�p��1��
~���j����k�	z"����%�u�]���� 5�H��+-��=���|����k@����A�+�z�/�c�V~>��U7�r$��ZU�z��|"}]	F#���D�^���:k4�{C:sY��$@Ux��hj!-)���?P�88�k��X��R4�	u�-ww�`K�]wg� 	
z1LHs�hc��.��{9��_92K1]�Tt
�8�.s�����m3fR��hAi��?����7�S4Y��ut0��t�(Nz�������)W�2K��J�4������'#���hJ�+�f�Rgggy/���+���xKDkG�YB����
^"U�����1o	Ew��}���l��sR��w1��<��B��CA��uI=f��
�<
"+Z����H��.�8.��a:��*�)�x�d�CRY��_�+����'���#�0`��������P1"��RV� S�-?�z�n\�i��+N����+^u?8H���*T���,�}!O��&�;��]c��>7`5��^�D���I�!��������"����QP0�iC�r\Q���X*Z�]�&���E�����
�
G��A%w��o���3����y�����������p����W&8�I�+���������C�0���9�\�tX�fM,�Z��pC�������@�Ru�������~ix�����3�:��
��9��S{���~��7ol�CE���&��/��`&����[���� ����N��n*
x.k~D�I�E����S�,,�V����0W~�������o�G�Ks���w��FV���e

��)5�v��qv�1_a�����H���ABo����9/� 
��-zy�����g����	��y6:�#j9�~Y!;n2A`g�����S���
�X�%�A>!��$����C����e�Dk��%Fxj�O,�:�����}#x��_�����n��-g�z��d���������{w��N�VEM�!�:� K�J�m� �����
���F���$�s�6�K�S��l����,�&?7M�7�b�z!E�F����.���K�����&\�-B?]��!)
�2�:v'���`5r������w=�nXj��m�Z�n��bJ�L�7d\�#�Q��!Z	P�?�;:��;�����-���~���G�ntx�Z��V.��7{��'��O�-�����w;��4>���`og3�k�_��d����F��/AhB��U������E,���W54�#h��������*��7�Lrv�FJ���L��������s�~��!���������'�P�2�FO�������`F��H+`��!��
�d��d��*�K��4�p��3�"/6�V��2�Y2l�'�>�7�u�������0Wq�s]���;��u�?��c@j���S�X����y++�����YID����jfQ����5H���0{lXTw�������'x�FI����1��(����	�u�1��S3w$�/�����/�o�8&��a�������N��y��C��!���O�R�;JF�m��H[GPJ�Rf��M�g���F,g�f��[�P�I�����^r�%���b����W�}�;|M]/�	�#��8����>���y%>)�sR���[:����Y��2YA�+�SM����z�h�`f(�LG�C+��[���h)�@�!]���������5G���r���l���m�/A�Cz�_N/��e��W�� [A�_�m���(�\���3dBp�+i��6ql���>5<IE�B�n�M>�XiH6B%��`d�bH�N?R$����70AV�����Q)u�j�yN�\8Hp��>�9l�(��I��bV�����B��!����OI7�-����b�c��N9LB-�x�
�1��)��BE�����!f
{���xg����&���/��������sI����K6�0��aRB��(m�������)����P)�^nHW������B{d�p�;!�L���z�-@#�07�b��d�F1���G�Cmw2-�I�5��Qg��"hI1�O��$c-�=���(�u�	�	�d�v9O
)Q_5g�QK�[��E���^�y��F��z����x3���1�U�ds����F��D����~7�-�P�e�5�zU
��w��������^"��
�pD��+]�r����%�G�����$VQ��� /;�)��B�(��NZv&��C�i��c:(�G8��J-��e7�%R����o�M"�_+�����t��V�BK�*�%V�5]��Lr�e�vh�G��e��7��te��$���a>�n�SI��"� ����d�<0��m>���z����������7EH���|�e���U��y������:K��=�h�[��j�`�Luw����8t��]���.��U��bGbO�����M= mt�
��v��"���3�Hp��hIj�������Om��bwW_�����=�������*�B�
��?o��Gs������#�(�t����Q�w��D]c��o4H{���%���6����2~Fq��8�������=({�)�B;p�m�'X�E������������vz���a���
�J�d!:���nN�����v�U@f���n�n���{�������?����{7@T�������@d�����p�{�L��}ZdQ����W�7�&ZC�K��v����Q����}pp�s�w
sy������6s�?�f��?�?�����l#!:�+|"<�M?�����9�T�����{z\�U����4����m�����5��v�iJDS�-�V��5��9�� ��y?���hp�p�9to����)��I���RX�B�yY��&��g
���w�1�{y����n��J���<n�p�m������h+k��i�'6�w�q��v����CZVM����2����1��qO{� ���B���E�c^[YjV��R��OL0����R\i�����*2_D�������Aw:wJnR�F�Y�ilxlY��Xd����3iiw���"�l��j7����,����������;���(3�����gL
����sZ���>�ah
��vpE���E��o��N�O|�+�X9�&P��=�������"n?*F�h����{D�������(r�84�c�q�.{����1�����#��T9��#GPEj~Fc��08��8�sP�����T��i0j��vc�<�ckF�1��,[�0��7&/�P�(��"%9��jK�_��gxX����A���Ro��:	�s�u*H�cJ�"|� 6�CQ��^%���$��S���Wi�]|����@�a:u���/�av��	�n"&
�n�>F*7��M=�a?����r�f^�N�H���}l�=?��H(�|(I
K2�_�<
�3�T7�g
�����ED���u������.H��C�|��!���{��*fr�����}����:������wq����)����[u����U��X�S��h�U�,�Y	/	�7]���1F�l�A����"�����]a�s
��S�k��$�?��Y��}��c���[�:+��4bK�F�5em�_3�hl�!hB]�D�����^�ps6qPsN��OFmP��&���c�:6�/����_���������(���y�:�)����*j8hu5��~������<Z�������o������0�`5Dx���`�_Z�e����}��u_�u��o4=y��q�[�����Gs���������l1��D'�vz��f�H|��j�r���j�,����2CY5�����K5&�N�:�'��;���{T��;���X�YvV#7����l���b���.��wi����0�6*�7WF�>��H	��\s`��
�{�c��%}5�������m�*~^X�a��O.3u�F��8������;�x��0/�d�/N��y�-S�g����rNn��3.E�&N������� �%&�h�1h��/�0�D����C�slF~j����Q�,	h-���$�-�(-��:sY�����y�b��o���	�m��� ���AF��Ri����|shg��<�r�R�����~K�)Ws�����a���5����{��pG��D,IZ��������1/������E�b��\+ �����q�s���O@�d7�qRX��l�N��/�\��--	P��B:�(�c -��.�����C��J?($����
� ?�tGb���0}���GEHc��3��`h��wos�9�7�*��|�cX	>p�gL{���.�u-��.MKr�+�*L�G21���,�.\���)@���r�����q���!R|� *�8��O��CY=�Y����=":(�����;�F��u���?d$�=iZ���E����	R����f��r:q������}Xu�p�mF������E���J:�������C������@���N��~��Wq��W���:�����cl^���'�?�+0��-"�a�����BI��-+�t���P�T�����Q[f������4��<���"�/�^��0X��A��!�Q��6���\x�Z\��4���xsW�@��,�0�4��Y����G���U��;���D9d���b�1������}�y�u8�j8*�L�Zl��rZ����8�&�x���urA5��qy�L?�#����`e"��p��VcM{�_�����������J7.�!�0��GM����^���A?�;�e�����/I�����!�8��aq5D\N��D�KT��j��R��M4����h�>�[:�q��*�Nv9��D���[p����]���d������%��k}V=s����a��|B8�x�R
v�);|��2�C��9�;\:������s����Z��T�'�U��` d�����FK�����Y���E��t_IG4Sh\~��1�����jAG�b�e�J���@7�'����S��3�@*Pgn~�8;C��^�k�����G����`&e�#e�F�i'�c����B?�Q�I7<p��k�P B_�JE�+��9b
�r6'�V{���������'Wp�?�_�^��;�H�4��h��l�{��A�[Q�5U�)+Ki�R��4��m����7�>jUf+��Im��ZF9<�p���M�"���5cRd	|:�%���wcf-X���s�y�
����6(�l'�/3�D���F���c2Q���>���P��3�e�b�CX�`�;���������18��%Q[�CB~� ����vA�:ZXT@n����H�y���~�idW<���\GX���3qW������1&yt����0F���E�
12����G8�9N��Z4.L��c�L�����������;+�0��U�5�Yl�d����`�K�������s)6�&����w.K)���m�!+�6�<^�rfQh�9���_����Z�l@��X�)gx���$������o�=��w���3�T����+�_]7u��u��~wN.
��t������NUj^)�������������D�V��VA2�g��_���6��eH�j��������w���>�n�+��`�v�0����p�jR��A���!��=���������� j@��?
T���SdV���r���>p��e���#crA�a�4�H����7�.�=���tJ�>%�o�]2�l�C�e\� I[\�5�[�����<vYG��+fp�M��V�������	�yFQ��_�P�H�ms��{�k��/�%��]�|�����^U�m8�/��=M��Z��*��D�����O��M��Ea�3\^] ��K���B����<�H��'�~'��NNnF�*���]:�M�T2S�'<���{]�"��c���M���-�c�x�!$w����	&�d��J�v>_e\�Y��&z�����,����T<��&q�b���7Q��R���qJ�J�RV,��)xs\u\F~�������k��-��� m��d���&�m��qg*�k�C�'&������$t:�w"qe!���F��G6.�(�^�v��p{m&k6'|�&��WD�C��=��:NI�v�N�'HF8s\�?���}��kkV��-��������z�w�MP&�{eK����}�5v����m��ssY#"r�������]! ��H��
�q���J!�����������gQA�z<*)Z��I6J��`��_r4�#��J]�S���1f�H<��8�[��m���
����F�G��#�6���Y@���p��(�;�mc8���h�yv�x&��u�i��w[�����%z30o5�m���K��~�P\�9 ���rH�i�1m�G�_�g!����Rx��?���G��j	y)J�K�2&���d������{��Y����$��h|��������Er��9��G�F���������O�T��&<qH���b �,]y��l5D��d�WU��d��%���y}/��"�`3�qd����M����7t%���������g�kM��C�/�@��N~Mo���8.�U�b2��!�HG��=���.��g���-K���H����7�W�3�L�s����V�h�[�m/+��K��I,^���������r#_�&:��"J(��iM��9��1x"��1��o�oB��J����V`-��p]�B�Ixo�Ppz����oZ���]������+�C�%�m5�%z�]b��E����A"����)m]�=�������'�"�����G5r��i��N�c����o��V�1����+��W	���:�����\����5�]d�����W����6a�b��B��hP0Q��l�>�f[0^'T��R��H�h�ng�:W��bO���
�H6O<�kg���2�]N�0��t@.)KT�������U���N����������������4}���:dEvJS���4�PC3
�'�����~����_��OT�/
_[����.Z��	�B�:"%x�a4���D��R��U���h�C0RYLe���<��Zz������AQf
��,�Q����..FQ��������\9���+cs�W`D�:}8�V2-�j��%U$}����
��t�s��{���@������_N)7����	�Z��gh�����3�!������h���7`�F��&H��6N�����
��m��hc3��%�nU#��BaEW<���8��"\�\l�+�Z�.�rB������t\fl���J����cU/���|��kc������M,��O	~$�c`�.Ha��q*��0+��0�A7V��"�p���%�R&����"��v�R��C�/�S�C����j���y�jC��Ho�(,��'?�&D��+Ny�	�
��M�a���a$�#"����Yq:�������y�����ai
�IQ$ 1P��������^��8��\)�v����aU�XW*U��dzcW�2�vf�M�H*��@	�{�~U�V'�Oh�|�����.KHl�:�P�5<��	������mDazO
n\�.��,��E�3����q�5u�������.I��_&�A��C�3��������_wv�)40����7�*���$�
��hx6l T~�-	���gV�K�A�����bp�;���vm�:�� vkaG%	��`�!o+���T�b����]eo@<��&��N�e�-� ���#�����<�Ep}����&�-rgF*�������O�n~�E,7L�c�7ObMI
�#zD`i��B����}[�M��KF�{��2����D���E�4�8Q�8��I��C����V��0U�5������:i��U���[�Y��4gSej#S����4���x3�����f����T��I���X#���fX^�v����l�	�&���0:c�b�
�{��|�y1ge.!���
l��G_{����R���i2wks�<��O�peN\��-�?\b�������a<�q�-�d#t���Q�,�s����DK�T0��
��LVD�9���/v���C�2���OO��-a����m���?�|�QJ7+��5^x��E�5z�+����v�en%�,���i:r3{�<f6n�Z�Z���gC��Z ,��H��lx�����98���F��c���k����
�,�2�����M��u�����������)=��V-�c�,�]� ������
�"�J3$b�f��K�e���y%�f�XU����C<��@z�����=�\D7�l�6r4�I���A�J�"�9}4�K�����B2��@��]N�@��(����C����D��]�q"[d;9�Q�����a*f/&��'����Q�L���hS1gX(3B�M�ghh���=����n
[p�S}����K�[����L0�ZT��a����V��Ys(c�c0�b�CK��K���O:;?��t�Q:�8#���1��W����Ks���b��,i�<�$1�K�,#��s��;������rD:"���,��8Nb���:

����Xg�kr�)E��j�H����v����\(`B�����{�4B0X�����A���yJ�����,�6����'P����)2
w7o�0�Gw%v6��J"��] f�"�#?���W �J����o��I�82���i���!glL�J6U�Z
y��F&9�xnj�RY����H��>p�_"��������8/��;Aq�4�_��s��o�
Q������y��`��K�	O�#�)�}�i�:4��a�����;$�p�6)��g��@��2�mB���3�y�R�k9�R��\�Y�������C
�Q��^!
;d����d#��8�K��D����6�18sxsL��xV��Uh��#�8]��I�8kl�D�\
|���td�����~O�=��vrXL�U�2e��l�5
��������`��[p������%�o}-[4�H.��0�A!����=u�Y��c�HF���8w��y�mG�~4�0o ��j��
�w�R\���0^�[��6P'������4�Y�i�R1���sz��
ZZ�Z�b]�����S�����oJ��������/"�0aS�x���n�2
���k)wV���?s���!�<2�N�(�KW�k�#)�nC�E�����aQw8�y�����������)��,|HI��0���i� �*���9&k����rI�R���Y����>��q���7��A�
�;������-�`�m�a�XP/���1gC���� ���0{|���d���5~4v�x���p���d��P����4n��;����*W�I����N�������U��vt������������b���h�um�<>f�o�k�5HW������)\mP����c�M��K��X����u'l�����1TW�VX���c��sE�]�]�z�����HC����S����&v��=��j��-1=(��JK����'m�R7��u�&�u���P���\�-B���Y�meK\8��M'�IYY������<h�=5*�����J�)~�y��l|��V�a{���������>4�}���f��A������_�
f{�p1��~V������8�YF^�X�#'�9 (3�����FC�HH�d�r	�h
)	��g55-��N>��<K�`�@7��@>�Y�)�*s�����������lXf|7��.�eW��]2j[�����m���q��v�c�}vF8�����w��g��,��v��:���
+k����Y,4�����%"���-�m�Sm%i7"��.�t��8�z(�Jt5z�P8{��/,����Qs�9�2�z�W�,g)^	�5��J��"�����ua0>�~f��|�>�1�T-(k:V�P4K!��l��}��	�+<�>j���[��0�;��x����z82���������8��C�+��r�#���\�
�'1���|a�cn�E
m��������q
��w�����\P��=���t��HD���p���Pv!NA��W��2���j6Uq�3���7�R�g mp{_�/����J6����X3�y��fI��p� &��e� '$A��~1�f�F�l���n7��d�Afd(V�U����a��>�S&����@�3U�RX�T���+,EW�vo��k�jE�(*�p�p�D�VU��D|�\�,��Us��-~���^���`y��1��/I����z��j{�����8��c�_6�g�����149i��=��(o'B~	UGP�\	faP�i�gp+�I7Q!r���Dt<gE1��)�-�+L���<���Z����\�]g�)d������
��>���*��]����_�.�t1&fJ)�L���wc���qaFz�o��e��$���E�/
GA�;�����f�J��N1�3)�a>�R��c��$��v:�bT���<�	)����y�����/es�=�i4�;li!�u�_E���~�����W5���X����[��GN�Q1L���hH�^2����
c���������&F
��1�d����)��X����+����2�!F�����dF���/~�SO�����~H��\��.�j�������5C��Vz!�*h�%������IZ}s���L����1�O�7���2�A�Z�*e4����bqOh@4�Q����Y�8w�����A���-||���>�y���*�����a�:�C����^�}$]&	�	��Tg���%w��.�5��������p�07���
�+�p�>�����ym,���^N�{�!+&�os�H��w�At������:����>7\Z�AR�Cl%q����h�"�3�&F�>$w�4���<P�*&�h.�!
��EP���:u�c�T�Y���;�B1�D����Aib�'t���s1�5���%�M��+����oyZ
~�e;������l����7��E@���Dg��������r�o�1����]*
�U�W���	��`�|�����D�=o��QB��Ue�T3�;����0/��������o��NZ��`@fow�8��;����*��M8_{<R>��U6��Oh���+�88�Y�Q��V}/G9H�)5L�w�cPi���-olq���^\Er���2g��"�
*�s����dG�������
���
��� ��P{�6��pOt�Y�W���g<�vr���&�<N��&^�J�����	J���%���8/&��8
�Ai^�bV�v��e�x#�P,(��(�p:�_���`n��J�Uj���J�8RR��j8������s9`��������|��8x�0	�UZr�a�&hSD	�� }�J;#K2���q����1��xQ�t��F���+a=���#����"�r�22FF��"A5*?��4��������ba�aH�������o'���7o \&�X�R�Sp)L���o���1�����4��^����>u$��	$��eAP�i
.�p$�t3r���~*x�Tb����D�iFo�,=	���q���`��7�J�N��Q��E��_"[����Cdf���hU��A�+�Tb -�\�m��I��7Q���o�D�b�atE0��|D�o�d����zX��T�� 3�Y2$���wL`Dt��M���8r"��P�d�7�V�Ro�w��b��G�)�.�r�1������D4F�Wg�j�.�����6��L�Wa�w�
��(gM�<d��R8a�]%�	,7\�;��q#�"���Pe�#��g�����w]7d�e�'dE��?��7G��v����pN7�8{��p�i�/�j�R\��Zs0��L~�J��},ugF�@���sB���-���������������vl���fc��?11�~�P��0���U���ljn^2��]Mp6���$��HVM�����(} v�`N�L���Ihr�J��*n=6��R��U������+���vy�ta8]�+s/�W��'?
u�y<r�iE��~��(���Z�!�m<F%��I�?(�z:U2!��
.��(�_Z���������M0��u�9��fW������|��{|w=���������a?������3�g�M[�i��n�q6@K_��]���:[������k���U|���S��{&���P&��'Dl��<�
�E���bI��)Q��������5<�����/������S	�p~(�:~�z��D�����6��s�QX��k��/������y||
d��S��0oxY��n���l�7}`�4y�M��<��m������"~�^g��Sp�A��m����r��I�t��P!��1�����R5�����l%�����>�Fp.��j%f3�����1^���yS���v�QM�W�_M�Q:���O�E�y�M��S������U��x���]f��$O~��+�F]^9�w���0 ����
W�C:����3�z���38\��$_FQ��c�O8���y&��].`�z���Y��i�&9�B�N\Z�7Wc�pa��T��Vt��w��_(q��_g~��s���H��`�����2������G�4o%�V�����>-*[&7���d�sR�[� �>�M��b�s2�H�����&�t�G"�
\7-������O��b�
�C�P�d��.�DM�%c}��1h?� L@�Br5�e�r+���l��#���t������f	��eQ�����;�3wP(�xam��~E�
P��.��^_����5�rR���N���l��W��������L���ir�E ��-E�h>��2��0����S%G����! K��/>�	������q*���Yx@X�<)���a=qyvE`�w_`��}9������<H����7

;
f�\|s�g_H=�ZD�,���g�#G�uM�c�d����;eC�#@��e����`��_>l������{�%�W�a�uj��D����[��/��� sa��p�\��.N�D�=����J��,��l�A�[O��$�=��"��[��
��������.H�%�L0��������`�(N��&9��KOh>�@Wm|Fi���!����
*@�
��Bu-
���,N�uhG��F�H�Ni�Xm�3���>-f���y+�}tv��i�Ch�M	�������?Fa���O����Q�r�\�����0�z@AX-�3c��@��AD����|�>��	K�A����8��s�yT������pp����
������2�IV?�#|�p���9C�0o{�7-���h��$�_'�g�����q���OK!�s�Z�QQ�D�w��e���&G�������7�������������{�������������;��:Ab��>5r�E����&��&&�������B&�Aks���Mk*�&��y��=�%������S�����t��Co������1�S��Y������:�vq_�z\pG�����w|9Q<ye��}�
�6u����~� ��;��oyj��n!��,*8Jt���`�1]UmUq��(���{�P3�P��t��]��K*��8�����=~T7T�'q.������>����Ja5����v���}/.�
�,�kz�|�o'��b�dC������~�?�����f���
�����oP�!����$���+����-�m��|��cXU�q[E0�����o?\���������������2�l����������&������yl"\�\����E�4PSb��Rl��<W���$�"4�<���"d���5Y�4�p��^�%��B4?F�D4�����y7�XK��2pCu�$x�����?a���@5L���z��zt�*��E�_�1��������?��E�������ke��.r@�'�Q����Z
�T�r��y-�-7-�,������������ �y�p3	������p���#LR��_i����wG��5r��M�f�r�f�>@0�*h�*qEq��Qix��0�}17����h�rn�V�a|��)qT'R�����T�R[bX���)�J
[��b(����T�^^�B����$m������2($*�:�"C[�+�;w��:�-��wl�W��M~B
4�)iX�z�9u�Wmc�Z Z�&�sf'�b�E��[%��/g���W����A�y�k�L�j	�?`��,�������Vb	C��!�_�^La
L~y������t8����������X��u��Te����UW�q��IO�w��_i�^����o��3��+[!�aDTmuA�To�����E�Xd���&G��]��Z�b�J�v��0�������S�h8�.�
[WBXY�a���K��<[��B���?���h��(�T��0�+��!j�����9�^1�L�n&r��� �;t��*���^*@�
��D�b�d=���V�B��������B!j����f����Y��OD�z�W@[!iy�eR��u����5��"�E�LY�c^��`W���������3f�<�����O��YN�#���r�4��a>��cH�v����iO�J2o0�ky�����k���oL�L��h�=j�3�}���L�{��������\|m)�&hd�\�W*.�	�a�1�s�����Vm��U�'O's@��	�%�6��_P�����a��!��o�����<���l�C�^�W���$I}���lH�n���������0��������F�,�d�iv��-����������eW�����V��I������-'�ZJ��_�������l�X�?���7R�jF<e���"C����Ys�VV|j�+l�u<,s}$��Y~��l�4��������[��v�`�s��!�c�!�������e��Q����o�����a�����E�g�=��.��������]3�.]0f8�0D���Nv�2����o]I��V �������f��>�x����:�������#�k]�s��J�����
c
{������ja���dD�]�62�{RoH<�Td���S��ZI9=f���
pZ�@�7G)Uu������d36�.�mM�d�������j���X�gO�c�e��g��r�[��6A �2�W�HX*�
)��!�L���X���=
j��?8m���#r}��������;,��3�.c'e	�_i�M6b������4R~g�@�8�A��.�s�)�s�Av��@q>$�����\-�v��V-�9�j��2�Mp�����8
T|o:�Ni�#��L7�����s:��G1��z�WQ��c4����7y�yP���^����Ki������kIZJ��������������������$^r�C���'����r�^���$�h��oD53�jc�J��&)��K�Hj���S���k� �TZ�xlJN���,��1���sP�5�p��y_�@��o�"0(w)CSvg9�t�!�C�b�j�������c���i�dU��X��TNn :�]$� ��D�G�Ke&Xq����>@r����}�r���T��_����9����M��M)Z��C��a�(.������0� Wf4��1����bQ@tG����O���X�Jx���e������U��������'|�"U�#T��+������c���Z�Z0��)����
B�{o��������^�z���v�#�]���1je#��$5V_�������/`R!4���'/)_��>y�sz�������dPit���[��
+���GI�G������_�_#=��B���A��l�$��<��K&�9
���w����$���Z�����[}'�.��'����-�&	�dg�`�C�~��p�t��P��9���i���_�N����*�P�A���wXl�����<������J>Ltw�+����@��	{r�s�$A��-RKL�S�:��i&J���������O��Qp���@[�I^������V�
��v������N1�w���U��1=����o��o/}����Z
}���W�Q�/���u��6��O�����3x�<���#ncs�f� *	��*�w����m0Y�u�����kk�w��(*�NK��td�,�.�e7�
6Zs��Z�/|��2���#�j����_��,����YBW�U���y�?�����)1�=�Z����&����9�d�1�%<	Ky���1vU6
�K�U��<�S	��K]��?1��i�z��
S�����/����� 9z�-�Z�Y���(��0c�l���9V��X��-N�\;����,�w�����H���S�r�p������S�;p%����2�pn8$�Z����������w�O����w����G��ng��cl�!���;��x����_P4�b�'�.VG��������t�]���6��QFqA�.�ZV"�kMN�^�C�r��<�+�b�tNa�T��$��
:���?�3�p<=�2��Z������FM��/�"�C|Wv����	_����������=���u{���N1�����c�
"=�������0cd��rQ�&��_�IZ����[	�T �t7�#�C ��������6�W"�_W�
�5��yX+|g�(}����ax>t�X��y����F7��L�K\,~�w��9!������L��0
��R$�#]����l�;vI����O�B����N��>��HP^uvz����.}���v�2qB��M�#@��l@g�O<U"���6�e��
_<�16!�U�$�X{
�_�5jT�������o6����%	M��x���
�G�~q_��9������y{��Tx>!�=D/�>�F����Z6��ct1$����}K;��������Z��Y�g ��i}�w�T�A��Vg�#��Y��&�K/�
1�mr���CM[<���Ha#OLt�CTyr^v#��t���F��
E�p0���Uu��A�	��m�^`*��e\����3��5�����������XW�TpJK]2��=��]��4�+������Z�!�"���������l����Dc�,�3G�g�;CM�i�������m��^w���v>�+��iKgR	����Y��WL��	0��pB.��-��9J�7�6�d�o��n��f�p�|c@�iiH����s����f+k������U���k�l�	�:����U:��21aQ�_T��	��{EYo���w�D52�,o���E%�\�r���C�J��M��D3��I���c���o��8��Lm��[V%�����QG{��2r�D�k�)L��[�V �l7������U�Nm�=y��8���ks�=��kF�� ^%���������t���b�8"�^���V�80T��G�4�	Vk�������PX��
g;��z���[�V�L9X
S���h���9���W�kkj��u[��9�2���w��Kj%��r~�OU���X=0:G����6�Uc�c��0���C?�	�����ZCT�QJ�Q�A�p_�?Q8��
��3�GBt�7�"{[����1�&� �8�t %��M���_Y{e��&�J	0�E��	�����<�"��s�XJt��^��D�~$4����XV������[��r9w~���^ztC0�b:�e%����M�t{����b��;h����~�|�XJ)!����X��d._�[aO
2+YK�8d
52�5�v��h����~rF��q������n���,�.V
��+oq@��V�q�xa�yN�����uNN�O?�$��������v�&Z�������+�����G1��H�v ���ob���iI<�f/lg�<��E�>#�;3����J�n���K����B	gX�n-��4&pa�@�t���������&$[�y�C����~�������7�3��CT7LJ�;�AQ|���KXS���T(�T��=����|�q�n�E�)\�7X�t�%�4���^�h	�*��
�8/����$�ra�_Fm�w���J�zX�}r1��+TuN-k��ZA��>���1��UM�.�o*���Q�M�`�n���	�tq�zCGD�hu"��t���;�l���lA�@v���9���KO�-��0"Z���u������N��T�J�P
�{��Z�\�S���,bK��=C���t��vZqgd����N�����r��?�n.K�N���tV�3�d��!�����f7X��&(���
X�n����9R?^q,�X�8��w�@�&R2�.�,#����
u������l��������8�4r����t{��N�b���,��V ����D9p�\�s��\Ob�jc��n��K�*a�����AJIl�0����
���3�'��������m�@)�@�S���*N�.H�3
���u,�N%������I���D�`?;���y*�L�����m�b�WV�0(��k�=�	�<�����i�h�������Az#O4��n�!cW�u�-a�~�/��H�[��n�K���Q+�+[�3]�?'?M��a�3��	~�����:fG;��6�w|�����r�_�Qo������O��{�>���b�)`;u����]�.��QQ�����������t���%�D��R�I�!�������5�J����� ��9���T`�6�,��VlOz���|)8ETZ������U��#���O�JHj�c:WB���ZR�~���d�i�Z��T<�T�cAA9��9<�L_g�s���	���0�BkI<�9�T�i5ZW@N����+#��*����3�
��������j�����@n�Q���@
5|�P\[W��]�}R�'��������*0�Bq�6��%�6�Dmh����p�g��m�p&������SlEa%����U.������A��'X���q;Zws��C�S ����8>�{��-����q����8�vm=Qx$��z�����Q�#��\w k��/S���?U]<���[�����+�[���+&T��*X����@�#XJ�B�I�
��4_�	3��U{:\)	���L�7�*J�f��v�Ko������j��|�%ipk���B8�E�����c�y��T�$e�Z����x
d����d$�9q�#���H�$��J���2xo�+;����T��|�Em��]K�_����v���`�����}T�E��uT5P���l0��A\0�K�nc� G���i��+e_��"	�LW�lz�B���&�S�<�9r��fX�MVB(R��%���-nTU�)g	��G�v���`.o�<>�ig���������9���F��M��e�c��u;#k�M���/I�>�u�h�\���u�%5��/�[�7����n��*+Go����OL���$*��F��?�����r�0�x�f���kR��t���9|�&����d ��Ou���u����~qF���4��t��K.�����O��p�?'nPF@�}�\��DRf=�����u���"ZE,y���r�������9�W���_�����������g��?�ce*�.��E�NgP�P��3�j��G;��i�����v�����c��KV,d�i�M����\�����	2+�^:<�vqp�ng��s���x�t�����������d�Z�I��=^�{��^K�o���'��Hj���;'"�4!��:Z1��:�
J�
��5�_~Im��*{��������A�/��-w�������m�u���^w�X�����P�"���!{>�.�2r�]�(����O�Z�
 ;������n������T1�gE�jd�R��p��t��8�L�W����������W�=�x"A��_����T�
�PR���7��J"���ls�6XR��,-s�0
�&��N��s�lx>���a�q�A1���}��Nq���qF+o�4_[�����P[/��G����^}2������'���T���9�|E&���!�)��/N|@����Y����@m���ih��*�3p�/`C/�����_�h�,���!lR;�g%!��!�K�?!�`
#ge)��p�5R8�G<���E�&�tM.�x��e�:������1O$U������$�A+����tZM����/@��e�V
}s�|o������r9���t�3M�>qZv�����`������Z;��=������
^���+��2q���8���x=��:��
�R�\�7�c��K��;iU�����:�X*.=oh��c	^��f�A��2>���n�[��T���Z������=��a{���?~��Fh�+H�&��Sq!!P%���W���62���G�rTk13�\+N��S�r9F.�����s��X�z�Xr�k^���L&�pG���p)����Qm_��\Lp8��v���3+�|�-��7�"�@Q��%���@2���*�N(9!������JpW�eZ�#W$aFK����"����BC��Y��<5��,� ���BQ�T>0�s'/���?r����b� nA��ZT�AZ�����j?��r}��{���b &2����\q�Hdi���2�W�>����5�������W�^��d���n?{��Qo������<�g�bl���������M�7Z��fk���g���+��?��N���N������8em��H'����r�{&"A)�$�@L���W��Q������E���GG
�k��K��rr3�4�(*,t}XO������
3���,jG$�!p� ��k*a����I��)��\�]�P����tB�$;��P �'<��h��5���� V�`l��Db@�yGi+��mBQy��g
$�|�ug�>v%Y��xh�D@k5~��7q��lH�R}/,��C��$8g�u�o;�g-�=�5%'X��
O��{��[��eF�"�{����`1�MY�m��
��������7L ���R�]�d8FG�"r��x��������
��o�[���N��!�
1��c������x,9�V����DIS�9�����B�i����v���C1��%�#p#!D8�19C'�.�s6�t�Km��y�4x��j\�*1<�����Q��-v�nh���pd�z������}I�����2����x����B�c&/���I����a ����N�QcN��1%
����	��Dv��&B�]B��
4[��yuy�����
NE7h�����P��E��p4����/��	�-��0�1//��.�|����pI����Y�S����9b��4�R���O3%��g����#�������l��F��� ��-�w�Q���������\SP����^%�t�����00� ��WN����-����D�x��b��
��[M�"���		d��4S�"�u��%0/�b��nW���M�0����������#Gc�Y����BRi�q�L���y\�qq��On�"��d��{~�'=�v�h��)a���=���2Kiqr"�)YzV��T�"+M$��F�����3��m�_��tl��h�q�av��x�L�|�h���E%�+���kD��=x��� ������?1|�:)����������
>��A2�p�;78ac��"��H%Z��H	�����x���r01S%�f����%]�'
_���A����r.M����x%��}��1��f;9�����w$���J���E��_��+0���B�sN���dIvt/�
�e�����o6��t uv�2u*��{�)"�/F*(�5g�m8��
JU��,��kS����T�����������J��q.b����#��������h�����
�����N
�"�to0g�x-�
X������y]��Q,�U����(�p�;I-��F�N��q���(\HT@�����v	{]�!��%h�E_O
Ll��G�cA��(�|����hp����Q�lE��X�<A���CO;l72��,�a�"?�M��)���(J���6���[������NGx:(	��8���c���`
�r����a���������)'��o�V[�v��7D��i�`C��OM�o��~��{���7�)���7?�):�@&��*�W��#t��m��]�o�S�.��t`K<���v������e�w�I��p����w{��c:��"���r�#����e���%�@���G�����������=�����9:<�?9�;�S��/���y�ak�)�>,���j��8Y;���`ir=�x������9��1u�+�$��r�l�8��A��/����cT�RB��+���5�*�[���Tj��|(�<�<��#��k^�y���]gV�p-v\��8�cR�IR��cI�����7�S;#��k�Q���"��,����0�P�3�"�m�	�K����
�5�a1M�x�bZR�����|���{��-�,q��v�r�r��d�f\���2p10j�3�
��)���������]V��Q��%��"xT�2,��:�G�D��l�ZiTL�f�������{qX�uaB����pG���R�D@R�����-��[9�,���D�F4��D
$c���-yx��.S1;R��� ��=T4?�=J�o��5�����u���V��('�����A�nPt��]������w E�,g��=�����@�b��3�G����o�����a��,�;�y�������7�C$�����kL*+���p'M�����e^��>�����,�?d�w�dbjRi���2�#r�J�C����W����}	����|H&�|X]���f������S���y80�m���L��
U���G~����;=?g��@����������'��{3~�����K1���zB��_}�Eaf)��9����>���N�dhr"'C1�}	��A*�
��GxN�<�����r/��8�v�Z���H�>�Po��U���fF�.�;rQ\�j>&}�p��jB5�K�SaP3K�Q��Nh%h=�k~4��9�1
M����-�R��E��o��3C���
��F����PnF�6g�gM��_9��"M�����FR���[pD��2����)�7���{��b��Tz�Ba�0�a���x��y�+���1$��,����
�w���l�>q'b��z����\X�2��'LAT���n(��
*�����,��	�v�N4�I�?|f;;�F����/7u��#�?�����4@�h�tM�|�K�*��&���P�L�?=��(t��'D�d��	�M���Sj�iXt���6��pZ����f.�*OK�T7���'b���?���W�W�Q�b�+=���
t%B��=���%*��tC���?�J����GA�V��,�H��������Z��(�*}��a� ���
�rYb����K%�Fu�F���h:�A�����=3n
I1��%!D���	k"�������|�3~�k�+��V�A��E�4��Fdw��%���e����#���K���88't3`]E��h��#���L�O��b����Qa���WkI �v4����3����)���R���
��8��,WH�b���#\���w���7\]4�l=��t�.���}4��h�BX]	��?��@�>�HJ�k9�?���c��������`���7��b����Y�jdh(�T!O1D-0�,$�-��t� �%0�P���	J�\����S-r����1�\�+Y�&���L��M��/=x�,Ic���?�<����-��h8�=��::�l��������>^� 
2�!-�H'�8��"`R�Sr|��I;�C��n?������s���!!�'�Dv��#�-C��G:�E��Y���tK�O�2�3.��`TL�	U�4�uE��*a���
���B�@Wc%��1��cL�����K~	w) R
��m�,>-���4zA^>����R^�~��	�2���y/��D=+����
��u�C��\�����%��A�?�,<�k#���DWC�o����w[��c�;���	����������XR�4�?�("�5����c��Fg�9G=Uan�U������a���<���Y�,�z����c���C����V�Rx�~y��D_=�U�'�����G��}(>Y�}E�}����=�u�k�q�V'�}��l�����3�20�!��?�ggp�nW��fW;��g��'���$%�������;����@��\�����%F��8#@��?�������9Qee���ND�7/��6-X�
)�K|���Wq�"���~e����Q���Y 7p���
e	J���~E�)��}��rCg��k:	��7<�
<'�i�\�2�N�4q��Ur_�,0�
�X�Pb6�5�x���0����0J�����T�B���eNhIN��c�������[��n���v��������:�����tp������3�����m�a��"�/R�����C�T
1���[�����U�4�t��A8�h~�"���q3�H��"l(�&��.��,t^s�Q�C�h"��c�{�UYI3����h������t�����-��%�x.�����_� ����\����p��3��(��m_��a�O�/�'�	"��W!��l��v/oeuad�����m�����|jVK�t1��N�XK�*�y�$�a��=a�Q8�I���**�r�P�G[>���j���{F�'�<i��}L�aU�:�uwYLu�����3
��9�)�����O�K�Z���(T�"���O��=����-��-��;'$����4u�^����V��0��&������h�n"A�m=�.0�]'&,��%(s�x#�S"
�<(������F����!��wn��t���k��8(_�"s���L)�)u]Z*�I�\���	���G�[���:~��.�2����	7�����*������7W�Q����P�"����u=����\����
������XO����&��N@���s��8������s�5����K��:�f����"�C��<�_����i�����q	�����Y�a�zz��a>h����`��HB9�����x]��I�"�%�=k	,��T�2�8��$9�.����Q�3����[Y��H�&S���;Q�\��O�����d0�)�/��;��r��9�b<�k���Exv��#8vu����|�������ff�+�-'yU���P�&���b��p]����&��?��%��6�SV�>�-9Y:����S���!,�!�oR>X:���������
)��C��QLt����9��6�1>�1O�T,�����@o|�*�^����v�P|�.�i����U���+��*���6��g"��8��ab�V�fO�%3��m���,�0�>���9��w
~���R�yMF���%x���B�}��E$�
��'2D�Ga���5�(�2<��u��ED`��lfu>)��N��A*���!�KWR#�2�(����SS$��LC�������xx��q?SD�1A0�4�*=�+s�J�Y�]#]r��
F`-�����U��}��P��F
x�c��T�����������!�+��P
��u�D���C^����y��|'�Y��f�tnA~)��e����T���k�-5R��'����u1J^6��H���S�q|7"�
>���@RCm��&V����nl��j �!]QhwE]p�R�u��7�0!=�=C�U(���';�4���MI��a��}8����-K�������>�nV8�5��x��Z���_������q��o����o���0��>h&���7��k�k�����5���k�(�lZ�x7�W|����B�����|��'�g�Z�6�� ��^A�����6p2���F�w�OT�&k|��h��3�+[�.��R S��a�38b(���',���"B����	G�g��N��u;M"b~��0��o�vZ������p��d�B��X'�}e�1fv"J��%�u��������a1�h8��n�����Q�>�;MN��O�w4� 1YF[�
�Sv�a~~���?kh�$$H�/gg\j�p��K%�������j<�@�C�I��J��a�i
���O�Mvqqhc��S���O���f���o)��q2-�(�V�LB�XL�Q�x���>�P
bz����@t@���ET���n�%A�o{+�q�$����
��P�A[�@&69QA���xg�����(�����e����\w]�n�%�O62�`�Z������+�*7>�|<G�����/�p��&�6�Hhw��K�}��AXx�e����'�}��h���D!��!:�����/���%���	<Wd��S<��4���"]z�N2��sJ"���e�]rD�0���q�c�'b��@px�~Y�>�*��s��qo�t���|��})�*�r�1��;8nW0�e,F6Bp��i���d"���\k�$�P���y�A�f����Iv�\v��	10/��I�l	��Ul��BI�Y�"C@����VC|]��4Z:���8�j���:�,���Z���ehh
W�f���2vG3��������(����Qm�$��.:�a�J!1��E�F�h�������7$�3F�����I����lD�f���5*�{M"��_	k2��~%9��0�����4�X�v�]7�J��1�A�
o�u:k�R�Szq�<��n�&�����T�y�W�V��5��B��K�G�9��7��W�d�/���#��K$(C]��������m!��0Du����D�I;q./�:�Y�:������+/MF�����gD�2����+&_��J'��A����@�R�64��MG�x�L}1ME������,��X��iJ��Cp�C�T9r��m�\Ou�q-�g�NVl�w}��(���1��lc�\��j�wX%�B
J���U��=�K�'��6�Qe�1������j�aw*'�er��(J/�g��I*��Jmij�I?��	<88�����\��������G���f����� �5)��B$g�*o�d��g�>/��4
eF��K��=��[��{������mO�G��5#�9�L>�<[$��������\��)��K���Q$�������$�V
R/�l��2�Rk^v���uE~b�tA[����>S�Nl�|�7��d�P�%AS,��1���R���G�G���#�A6��5�{����R�],�N��DLp�=$3�+����6Jw�O�d7gm���{�#c���7�a�^�/��F	����8e��=�2������`5��mE�6L~��� �(�!eK*�,��'��qlq�%��w�i����g�i;������
t�>-�#���;#�a��P�)��XN�[(o&>�F��H$��"����)G*��@�a��n%��j�Sj���j<����lx�5��t���R��������a��nxt5���
C�q'��x�^��()#d�3�����wN���r-'��E�����>��c	 �"��M!��
h�7��v1q�5b��'����O�������z3����
W�s��b��-?{�.��/oN�N�D����U���d��.Kiz��O@KJ�gB�����_�e
��"-^��>,��I�>����zR�:�3?S��6����s�o�a���^�������s���!;��>%y��BN�h/������yq��6�<����3�3S8`�>����c����E�_�� |�#�K�A����|`��'���1���`z��p�m�v��Y�/Z�(/�G�F����?�37W�}���o��1�/L����(� %��0��d'��>\�,1w�l���g��q1���rw6���>�a����@J*
g��X��a
i���>��h��-r���C�����q:a�����tD�j�v�Y���`����������MO[`�d���}CU��YE��*��5`��T�4�3�W��K	���b*�o+M�+���������C�&���)q"7d�e���"���I�y�D�����aid�q�;e
�E`FP����-c��q������������L}�n�!����NS�s%l�� �	��=�����LQ`��9;f�{si�9��zHi�������Y�������f���I3%���-?���������r�3�)k-�����#c`�e�p�V=&k�J���kM99@	@
�S��k��Z�+���h��Vp��xD��zx�0��U��h�� ��}(8Q�m8z��L������&�Qn��at�Y����rm$���"
��#?Pa�����<�F���#*%*����*�LN�(�;g���f��������7�T��&�JM)����A��s��hR���K `EZ��6�0���2��z;�����4.�����4��HGV��q_]m����,iw
w�:�[XGQ3D<�L��)Z�~����/bO7�����m&
*2�:����V��T��������y8Q�����D��w�M��jVt�Z���%��V)�e����S6Y������a�s�&�JQ���O��k�Y�1�p^��t�-T*$��@����8��[������K�r�z���3W�-��|����Uq�.�= �����(��'��H�"7���;J�P�^�N��EsG�'4�c��fD!��F�
A$����B6���8�K���^S����U\�����.{�}���D�)������wE7����knf�Z�@3�,��	��I1\�� ���'�����@=����`!>�y&�M�nWA,���t�-�F�&_o"��5B�h�t�uM��5�����C$�1���(��7A����g�����6Cg=���R�bQ��=����D+#����Gu|2�P�-5��!A������t2.�,�� aEe���������Ca1�"�����
>�3^��3^2���a�#'&�T����&k��@��\g���Q��BXe��;�6��.iQ ���)����/s�G`����{������3$������mV�bj�>��Pt��Ds�#t�lT��F��c�#J]U<�t]j�o�t6K�.�0auU����>;�k�(�j.#������5���	��@E�UB=
^�;�G�V4���r��2I�4y�\�*k���N	�=�~n�!g���|��@�'��;MS�T�.���/�������
��
��ug}=���~��������8�.�
��%����]�e=�8���qBk�3k�����D>9�O���3DEt��9� P��a+Q�u3��r���]�����-O��C��l�<��X�s=f����*v�0��E���$���hL�~���hR�.T�����$����d�g�h�e��X�3���������nz�?�����O#1rn����B�!S4s"��:J����6w�*��g�$WnD�A�&
M����q����!~�����Q�An�(p�~�M��Mzf+t��hU�%��:t+���"�(�A<O���E���z�*�TV%���p��I��������K�2�iYN���J�~������P�dE��L7fg���+��6��q�m�i�C����aW���7X��?�%
��"�/����p8��
��J��T0m��y-���@��"�u�EF�V���}�HR��$��p'z�F�+Xh��^�`(b%J}.j�_�������w�.c�x�|��d7X�a������S�SV-������
+��2_:���������%1��k�=6-�Rz��66�on��"�K�f��9��{C r�K���]v��.I��&�F�_W��P�*/Y&|1�op�������B�@Vk�4�u��ZUW��V*K��Z�)��9O��+������q���fS��dq{Y�u1����HYgk�)��T=n�ae�?M�����(�W1��5|�[j�6&����]X��&4�0jG��ak�Z�z�\�J���I����f���`����w����+R�V�%�*��D��d=�.�,�"$���)1z���{g�5B��o�[3���r�J#��
%!;�����<}�A�6i.	S��p���B`t_$����i���]��oIt���9�6����t4k�
Z����|D�+���*�&���E��<r`��*a������'�g��i�x5J��NRq�Fa��
�0����{X��l`��b��Vu@k�����j<s4��K�O|����aa�h�Zu�� ��H#%���4�@������T��gh��1X�1�r}�j���3<_}�\�U��R�R���b75�P�&l-	?�����vk���`�z�s�kW��+�^��U&~A���:�M)'�7S9WT/�c���6$�e=�?"��o�I�d*�~��A�&�@^�V��9Z	-X6.jb^;3��;�K���$��I�P�����,������fat�Z����bUMm,!����Lq���epb��L�T1vIN,�_������71���Up��\��[�:�����
I9�@I1�H��bjI�y��cJ~��5)�T�H`���H=�xL�d���V�g���*��o��N��%�Jn�AQ�u3�LQ[��������>���Z�&y|OI��I���^-��O��P���D���6t�F�	��;?���um<��p��yUF|eBw*�3���0)S)$d
�V~���c�,�>jr�����t���;����y�l��9�f����:v�ATPh<�
��M�e6�:Ix���{�0e��x��zL������r.���@����?�!�F�u��Y:�����p���B����bV����3�g�:,�RGJ"4A��7��{�)y�B�H���8!E��Cz����tr�A�T����4���� �)w�vn��	�o�p��t��C3"\4�%�����[	R��x�g���E�<+�p�������A��F��oio:�$RA�<��0����h�C
8`�8��Reqe7��aa4��L�m1>/qY���o��p�I��rPh�x�����9@l��b&wqb�f����`c IT��bx�Yy3��`5��&G���4tJ��JL�B����C�K
t�F��y�\p�L6��h!�wq�LP���E5�-�y�}K	��D������X��0�J�R���i����W������,5���S\n������*�9$�C�O|����������a����*��W�W��9r��'���&G�c �T����ek��y!�A���_�.3���1��������a�i��W��$r�AG���%'�w���eO:z�������M����]y�����.��qL����&�}F�h`U3hiY��cK5F7�I3w6�U�-D}�,�*���*@��E�4�d�;�>�w�9�~��������G'����^�{�^����K4%��9����Y��I��.�

Da3	�;��C�o=��
DTE_1�zF���g�qHo\1���Y��
���<�����mm��8d��`�(�K�@?C����W�_>���<�������Zm.c0��D;���I�//�>��n������,'�V16]a�Fv����$����lr95�����)cj������5��@�kQ��A��:������o`[(w�"|��o�0���a���Y�b��*�C<���U5i��{^���JMW�&0���Z�g��;�,S�x���j-���<0���-��Q7]�����3����p=���[]a�s��x"�l%�����,{�V�J�:��{CT��;'�r]�J	��{M�oi���v�������k�������P,��������V0d5���
2[�zy�w�r���D�&��������P
��c��I���E��s�[�KQ�(����@��k>yLZ�%���3Q�Z>�1!�W6r�t8u�;�21�o8I?M�oe�&g���"�:��=	�2�}w:�'�E��g��Vz3���������P%6��A��L��s����f3���M{�a�i J�u�\�
/ybfVL�����Z��R���hi&�tr����b>El�l��[�I�d!���K�x�W�w�b�G~�e���FS��\��#sb�]d#�P ��q�.S���)Q���4��:hd\z�������1:������ggv���
p�o��������cC��dCr�� ��MG�O��`��jF�uGqE��$�RTe�+l-�1��{hPE�8u�A���A��V�F�B��_��c���8�lG��;q��p0�f�EBE9x��K^����`c*��Z|��~�9(���L*\��
�N/�h�g]����$PJ?6��F���$6�U7�-+}�+��5`��`��e��Z�]�
f#xK^Zo�?����U���a�n��"����R��5#��]��v�H5����}��U��Lq���� DX����b3�E��#[������/�yF�����d��=��XzT�C�0t��������qFQ�5 Q1�i�=�)��uU��N�+ya~�����tk)����H��w
D�_"�;D�dyQO��}���"Il���4��\�z�h6q���S�����,d�B6��}PC�^f��=8U�*$ L$]AJAm���.N��D$U���^���!�0�i�d}�.��k���h�d�9�D7�����-xv7���P�����{r%�c�����B��������D��&�6��s�jQ�������A�v;3�b�v������14�|z'�J��tnS&}���e���W=$����Kt|��H���XW��
,����8���|���D��-��GU���k�%�2]x*��z�0*�H�	������6^������)!F��X��Q D|<�Y\.���� �O
w���\
�O�K��H�]������}
k���av��Q2o�@��U��xc��?��F~C�����FpPq��E���9x����H!��%�;�|j����D>:���=�J���:�����h����CR���0�n::c��7y������T�-��3���(Zpeb<��n����$K(���� �O.^�L���G�v�Uo��B`d-2��Bt,`�����!e'��	`�������f�@�":
�8����������	_�GY��7>#�|�~���l\?����������u��d��0�t��	���E�a����O���gc}]��fy��=A*�MNj����.�����D�R�y6P:a�����*4J^&��Xu��\W��eQl[�p�x��V���KE������+�u[4����}����o��||3J��l�9��W7�\b�9��^L.��Q�s�W�O�>N[Z���;�����i�2�a��_>l����������"?pp����q���NwJXH����3���6���jI�6�`�ay�`���W�xN7�T"�����@��B�:r9FK�
d�b�o��#�������v_*�+�J����	��	1�M�5�D�P/����2�+I�����%��"Ri��Oq_�!��\�&3C���*�P�9�K��9��d]L�]?�S��D��(F�.����mSg�V��{r�@�E����\���������6�-���������"j?3S1TdhL�A��I6�R��� 
���J �F!��o�6����&D/����$�;<�����4�3�/��|1`+8��`�s1��e���e��avR0��h1�
�����xM�4�JOh ��n2�t(��~N~�]���`Rb����N'����S�Yj��m�{�M�t��VX�RzB\C���9&B�cz����@����mnFbJ5�hEC�8<e�v
���3�.G�F�:��)��W�_��/�:P��)����dd�0����p��7�������eQqVl����,��:g4�R1Y�u����-R�*��z�/n����18���&kc��I�����`��&�+�Z�����t�C��Dc�6p�g���=V'�0�o�|��F���q��2���N>�M,��$W
�c����Uu�N��g-�k��*�����2���N�����+�.�d��b���(�3\����^��m�g��R��O9VP��tB-`B�Q�o�+i�u)����2��������|��5iAj�X���4���+�����7�C=T��lY%�M3HW=��+�iy��8�M���G1q��+4�yeke�r*`���<4�����!Y	�L�����a%WGN����7ou����Ko��l������wV/����Da�������K]=�Yn��L%44���I�y����:po:�:�,�Z���+�����d��L����M�R��������V�������������6V�	
z�������������:���J�yz��a}~?������
������\��f>��7%��B��Q@���uN�@vN�+���5~m����s�5��Y-\�bm��Y�-������k�j�L}33��������}i7O7���H������>��GA��a}�KO��MfL"�o�����*��z��P\R��p���Ay�AtMi��(����{�F��H��O������������������w�7������>r��?�tr?������A8}P�7��Eh:st��A���
����E�+�Xv0=�_�3q������Q�����A�1#���B�,��{�`�����i�'��qP
2
�by�����<�;���e������<Z>���e1���.���p��rF�s������~MN"R�.�������,��B��<�Ml�)�7�wi����%�0��t��X}�����ERi�����I
8$�x����R�B�}Z5CZ,Q��sXNGx>�R%A`*k�F#��i%��{w@�;g���������%�*S�n��3���l�d��z�O���AQHbdb0�8^jQ� /���;A�0FR��*��k�����V�,�\0�/��j��!sS�l!rr��n�l���#6�-*��g�6������L����J.W9%�v(;���*/��YX�Y�9(�	P��Gl��[���������IV�v��V�A��N]�?VQe�n(����&���t�9��(O�
"VK~�i�a�1v. �,��p$(b5t}ei�;b�fKy>�q(0����&&z���bU��}��C�9�N�EWQ�JU"?�&��z��I����v=�&�[U���L���
��+���2�C?�#�����:Y����s����d�U�I�$v�S�s��ka���W3�'�1�%����(��������i�0�l��9���5��j�I�N�&2_K0w'A�������4u���L#��;�Ve(��!-�Ls'b����O���`����`b���i8�:������"��sT�[w�yl�1UNc����3X����Dvx����ga���)��M)���q�P]#2v-o���(q��n������Q���m��u��=��}��W-i�
��m�����q��+1�`�Q�h>7a�0B����-�q�Bi{�V7
s	��:z��T�ly��@�=X��$�,	xy�z��k��������%i�ba��w`!�,?'G�t� ��v�Z-A��l���}�7r\(����<&����|W-�jQ����j�_V1us�R����]�KS���Di�}�e%��k�"���*��At�pt?�wI�@=$��<
5���"�|�}O���[�b�-����^�00����`�������L(��_}����Z��@S�(�_R�	���F���oF�S�f�\�L�m0�S����L�Rxh�=My����r�9?��3@���1���)BS�-F�.�T�V��cH0���I�k��=@|Q��b2�.H}��Y\]��9w��#�eR���T�H���������.�4Vv��^}���\h���VpqC���?F�1�9h[���B<������g�N�cf�2��^<��P����#]/<��(��a���X0m��Z#�m����t!�A>��Zg�9~��������Ff�y���XeT�4Rx�
�U�,����h�P��8,8;
�����;���y��"��~�v�^0{�	&�+����(Vqr���l�[���1
��NK��!P.�3�T�{��i����i���yN%�0F��C�B�������5%-H ���2��13g����K��Vz���8v��5/����c��<�
��s�/��������l��;
h�o� U�KVF"�g�x;�-����.�����$������.n�N4i'SJU���Dq�j��e�����w���/E��,(�s����*�h2���0��{�+L�f���Xb��t�	t�����C��,Y�[��${�����)L���_J���_v�P����f7�,�t�
�������}|B;��h�r��w�i��E���s@��R�;I(+��A�_�
�d�����_�;:}�}�I���IT�P[rj�&��;����2DwI� xC�� ���|��{�����������"p��V�z��Kr�8;���Dk��~��?�j�?��-��ij��IG��Q�y)��QQN��kv���?���������r�RD��H#�A��(���v5J���rU��0���#C�d
i������c�?K�=���B���y)����R��4������>F�����Yw��A� �����4�+��%L�,B���3�w����-�\f�5V#��K'�MG���|���������fr�7�_~�(�-���9/����	����E���sa�%e\u���CA����b�Q�+�_wq������y��
�K��K�}9��-�9v�=X*����vb]���#h�k����rx��Ef���c�ya�p�#�n�@��9ZF���J1b�o[*�[YY�H��RJ�H��['�k�<�9����9�?,�=
����m������k~�<�z�{v��n?��z���O676�>~����>��kkk�������?~�z����%������(��{��I�������~_���M�w�������_������
������o��?j=�!�I���M�����A����4	��\��g�y�D��hA��E�u�[)�Ri�Q����v�5b���x`�D\a�U�"���K���-�<�6(?a�\��3;�������QY2�<�����1l����g����KLe�]��E��3B"k�&�j�Y�DP������7bE����IX^�������~���i���<��������?:�������JtA-������[��"�n=��3�i�i&�:�4������3�P����
�K�/0n����+wn���n&�������^g^��x�a�HG'��8/"n%<���{����{�B��?om>N�=y�z�Y�c.�$�bb��6���V%Y]�3��>R�|������*Zr)yC�\e�WC�6�]0JL���q����~������*��x�}��
N����#1�}��v���i�=����l���H��t��V�x����(�Rlo��'`F�8B�,���'KL���i����@������or��$���Q>�<BX�o�%h��t0V���ok�9�*������`D��o���v���e-Aq_�K1I3�kF��|v'�i��xC�����3e)|:��u�����GB�_��h���2��*�?�t�; K��ltv�v�v���4��������s?z���dN��'�GO��F�����z�!k]��Z�-k]_A���[��`#�!�x�_ui�w���A�(.�!���aP	 ��*B�U�.4�P�Rh���� V</S
�E�<�� hHK�,^�L���m�,6��YR3z�w7gn�o���,+i`f��2����`��Io:��$�S1����f��i�@�w�A�i2��S�gV��Q
�}��������y�O���Jm()saI��~��,3a�b|.�t�N������{���!`7W�������s_f
�3�U�F�)��^��#��y��Q)w�	c{�
�)e���#��������T#����>{�3.f'����v�.�76r�<�A���#���� ?��<x�^���}RAG����c'$���H�E�R����������X�>��E�c�B]1��w-�o�M�&�W{S��:����@P_��������������i<�*��CbK.�������8@<���`���J���Aq?��m���y���pw�����n����wo��)
���r�HT-��.	��]������!x����Q~�t���(�pm��GN�Q��	�#/��+�_5�_C�d��$H��48�3��>�6�����I��xk��x3"��	2x� �����P�	V�����X�bx��	;�|���?�I�uHWp�r�0D=��5
�������/2�~P��Qc�
��R$^�_eG�%��,�?#�Sf����kL��+�8��*F��P�^�g�����
Bqm��� ��(��o4p:��E���^Ww&�C�>�LO�@��t=&L���6�E��)��y�l�����8|�p��-���W��.�t���uL$��`p����Nn�3���(���89�����m����W��!��[����<�����:J�9A���'N��7��C,D����>h���C�J��2E,�^\E��t���O;'�������#���I/U�ew�F{����=�v	����z���)�3�^%�YXV�#U�$���HTw�J>o�����H�d�>�
�u�5�����Cus�Q�v���?kt��~�Q3�[�j���I�g�{�{��1O9�9g���[������k}���=\,a��v�,cKl��s�(�@��j%	:K�_���{��3������MNw�����uJx7���
R�}��<��|�v���Eg����Po���
�5����Y�x��F�����&�Z1��Y��IY����3xZ�&O�8ZC��j�k�&��X���0s�Ej:b�6��X9��8O6_��6��'�6Z�_D�����xr�F%5H��d���U%|���
`���G;G�b`�m��~�41.("
���Gk���~��^����O�����#��LK�R��B����Mj.�;��9�����o1�ug�Ck��8��t{���4a��b�x�~�<�\BdAT�8���C���EYr,��(Qw�E�i�X@g����@�y��$!�~����/�%c�L�R���lG�Z��
8�Cc�&U��Cw����N�������1������$(?��������;!b����4I����C��y���A����������s�q D|*�g�����$+$��t�l�67`�/���Gz��Q2�� �sCON���]�n�g�2'DQz�9���b�X��z�����0�tZ|s����<8wz�S�
�hJ������%ml�J��@{�1��Y���c�w�-�����Bv8��� O����[��1WuL��4�����.��r�Hl�{�lW�yW����v�V�MJ�^�E�%'+�x��@5�������(�2�X�]~>,0}mtqS��*�7���O<LH����'�_���T�<�
�"��;6a�2&�.�!����U��\+
T#����R((OHGB%�k��7���������k^�"^[�"�+��a`����[au�[��f��'5\<S�^H����s�rOG�	��~<?U�o�-+r3���A6p�(����a���p�nR|��Z*I��25����o������FM@������D�+��(����9�M��	?x���.������JzOx@��������'�.��E�y%���K�)$��eRI[
�����K���R�n�������%=��CnAF.�Aa$��v�b�G8P�k��Z����������@1;��l�25���3��@����&�m��	��#���K�3�����g`�}��m��B&XY}�����SK[�:e�H�n||���'0�|��;�9L�!��\[{���
5�?��L�F��%��T	��O�Z�=�uhm^����7���F�
^�2�R�:7�,Q�ML(�>��h������FYgLv�u���a��BZ�-y���X����2���L*����	v� �W%U	��x��z��mnml�6�&�@ 6��"t[�X+����o���O>]x<�����s�i�Mc��t��D1{C�������rk����/���a�u:���OV�B�����J�@�t����5�4��>��-f��<G(,�D����p��3���?e�OBt4��|_q�-�r������i%�'O�^����i7{���d���g~����������(n~6LGy�5�%�����/��0����A2J,���g������c���P>��.���?bRfIsX�=���u`	���?�p����Y���]���Cr�u�������>��=�x�%�|t�y��#�^)j+[*�Z�����$��W�V�����J����/����$i@h�^�`pt��Lh�?��=S�Q����
z �
ys����;�M&��/�8Uh�.��5�U�Anx�K���� s�����8|w�w������}����mz:u���"�*��8�s����~�RA�\]�c�S���I���ZY���W|�n�~�`I��o��h0=�[!h�)R�bv�&xk�������?���nV�V����_|��,����D:9dF��/d��(��C����@�q�<�t0����w��g=�j�X@���S�������� ��������-w�������h�C�H"7a�c�Ns�*� ���C��:��G
�*�b'�s��tl�\u`n�(A��,��i�{��Vq5p����@ax���cOB�GK3�i�t3J1������1��ii�6���H������;��T5h���k�?��`�`Q���)��LnEgQz���@�6���IRp�8B�l0-��]n����E~>��kog",0���V�a�@���s
�F�h�v���7
9�-6c�-z��:�\�`�K��� ��� T��l-����Q��0�������?���h��h�n�DwV��Q._lQ:�#,(k�&|%�#�+6��#��I�%��'�����a��w�������	����������A]���2"�<�&��|���������L�?�UW?���z_�������������qk�	f�>mm>��[x1���?#�;Z��s�9�������X��_)������?�^�=�y�����l�T<�I����^����8�����k��Q��[md�2W��H(5����75�!#������"Y��|���\��4*��fE�n��`c��iS���F���*��6��dCc��,��������o'���M^qs�a��}�mFk[�6[�/����lOM�kkU���u��r$1�K_j�4E�g��,�����(�����r��?��yT�����&2��7ZZ[���8�fMlv��(�N��[���W��!�6N7�;^�/��o��^�O�A$��g���
�N���q]aTF/����ry����=�|��Y�n?~��nn<_����4����%���	I�/|�7��tp��v��?y�-��1�T�]������)
D�B�i�$��1b��~��s&}R��0cX�#�/!s9�GN��h+�?�i]�tNx��;Y�w��Q[�.n<~������~�"��m=^xM?s���� 5
�{R�qB6��MG�!�x?��G�������f���-��3����;�%+���H�O�<k�����@`lD����'z�D���i~��x�_��Q,���&��m��"/����s�V����&��d��+&sb��#��y�pWf���Vuj�~��1� ��|��v��WL'���#hn��G*d!O�)�(j0����N�/�*/����+�z��S��jZr��nIO��lu�e���z^T�.jZ)�O{�7�?n�=z�4}4��Q�O�]��$v��2���(`�����\�O~���_&W��#C|� ��C�w����k!��������Yg��Ch��<C�=&(���U��K��������z���@?���q�����PZ7a��K/�wF�aT~��j`��F}&��`)�q��E����Eh���oLN�Nr�"p/�=^g�u4fq"RK�����g��������b��I�
x�5���_��(�������$F)���q=��u�L.�)|��@�c����W��]B=:=���v�!���t:B��c��K�4���>8����A��3Oje�h�$�������������T��@�E�/�����9h�_�`��n(�6	�f%��L�LC1�~�������������/g�Olj*�4� �~�`0b� �����q2�@����>�E1��2�"���G��O*ULf�`9K.��OPW��Tbzv�����}���s|�����������J���@���8�����=(M���~<���A�w]4�H)c�����l�!S�*�T��]y�5~�����.
��M��Q�S��2�Bq1h#)-<\qo��,����9��9��uhk9��nwS9���e75q7�	C��*�\�v�oS�S	2S��K{:A�������{�q�)�]���D�����ch�{�Gi�.s�S���-G�V�T�:�Z��sPx%�`��CX����[�B�D���qoU���Tw���H�,�D���K�W����
1��4�)e����E��h`H�7�v�)��3'7��Glx������c\��t�f7;9��$A����TU�r�i��:e����L���S�)�.����������y�<�)�Lg��zg<}��G�:��4���
<�p�-�<*��h���p%��*5p^|��\��U7��$r��oi��ZNvu��%��I�q_������9#u��R���W���� ����8s�:��	}*U
?�z:d������(��_��cm!�'[��-�SP��Wp��!�iC�-�O`��61k��q�.�%R����I�������.I�H*����������Xn��h{��
����>U���j�I�E���~���j"��@f�7.��b��NX��a6�����e�4��AZ�ufdc��466K��[���'�K���'�`����7�s������A^��L�����K�U���}���#8!	h��0x����;���������Imn>�@�us��8&����=������=t��cH��_TA�,e�����ShN�X� �P��U����Ra�z���/�a��&DKe6J�kp��n8���S	�p������, �OD�wo^�,�5�Dk��mmn�6m=�����Du�M`e�����o�Xp<xU7�#Y�;���T}��*1�����j~����3Yy�����z�%��K��!�g�g*G'��1�@0b�EI��3�[1��t x
�*�`�UG��;X;�0�t/�su��SBewdb�t��M�,�3�P��p7���Z�m����!'�sZa�(~��.tC<�n���+����i���TJ�U��B�@�d�W~l�|�N�^�x�����?���&�G3�g�>�a���@�fH�S���6��&�/l"�����ZK��L� �P2��r����h��8��n �����Y~�J�h�2�+��@<�e#������>�����	z��i���Se�b���2|�H�M���������T�WRc}�{X��pU%��:�B��$
^��L1�i�k|>��:%h&���%G�S!5[���,��X���"�>�b����Ss�N����Q��F��S�$x��<�����;����B��t4����h�?rd���t�d�y��EPq���FT�g��"�xujn#���
!��a	�X����R-�N9���C�l>�`2~�a�����*�%�b�����������p�����6x��EksqqQ'd�<���y����+d�*`gnm1��p�4�����*'�����qF5
+�16�r�Y���;���(J�_����REd/������Oy��Tk��J��=�{T����Dk���?��n0�����M�������!��������3���E��N�v�\�6�6D�������Q�|T����F�����2s��X�]2E���w����]Q��	w�Rz�Kd�L��}mk/�L�C.��e�Hv5)���x>p_�k�`��<�a�k�*��f�����s��zsg�����==DN���:������h�����"�g����v�?^V��Y���.kC��\;'&�����d	b"uu	R��
U�!�t��	���pUJA�a�W��\�N�g������'r/���>���w�wq-m��r���0���[��q<���U�2`�/�{2��=����^������jD������s������v��#�'R��fA���W��m�F��$�^>�z���,t��|BG����c�7F�AQ]7����}S�)�����+����rEK����
�a��v������,��'*���k
�������*
��U!^*�=�������q~!�����Z�*X;�����~i�n|V.9�.�"��9���S���d���c�r`t2x�a<M����O�k6�Z\R������3�R���;"cp������bk��b�3�����Y���?I�L.�/�����	c���FJ���Rj@�vEf&�#(�_���5�9�v�J�v��i\\��\G�a��Q#-�WtY�	'����vIk;�p��&
�e�r��X ��pM�c_NQa���e���Q��F|Y���JWY���#��Zty��R�����������o�|� ��R��J��d5;���f����pMp�����|�8������f9�AB>d��JX9�H��*Uqi���H�1F��$1��<��Af
q5�\��������Z�����H�g&�"el��.[I����k������2C,L������Ju{u�a�8�I�x�Dp���a_��|YtMN�+��EUDDuB�������'��?�dC�������{����8����y���^d���a����~����Aq���"�{F�J������Njaw0���
���-u��b��������y;�xrq�]���s<�;i�"3�`�l�x����H�\�.Y�9>��������S�9�3G`W���u��R6�@�H&L	�n���0C-���*�4!�����)��0f�E{�����a!����_�n�|h��5W��k�U��@\�^��K�pO�zn''�1�����yG�)1k�>�>��bs.V�o�0//�3)�~�@����Kj���x����ZP���S�{���Z�r�N�3����"�|'s�%�)K�F�] h���F3\����t���{�p�u`S���t�W�$bW�����aq5��
��#l��D�r_�p������!?�@�z�R����T�a�����#�U�0+�I����Yayp��7��Fh��
Fi������#���%�A�/�(���bS�<���zz����vT��k��H��Mi�
� r+*� ���fW���u���/>���y[4�ke \�*�3<�Q;#L���x+���a���]

�P�����i�uj7�Xr���h������_�v���+�]���}y�9\<U�s)���^o��a(qB��d��D5��l="������q^��GxLw���I�O%Rh���j4��=��)k��p�h�V��O^5��n-�Ph��N+uE*�*�
+:���M-"'.V9b�@����2V���M�T�^�>�Z�u���w�
�a7:��2���U��L��!Z&�
b-�4AH=��h� ����Ad� ���WO�b�f��z�n
>���7=X�)]�	���[;%�����P���s��x4m$�����l�y�n?9�G\0���2;�����
JL��kj�9p��E������b�?��b:B>	?&���C��d��}�fcZ���4d�g���k��*@���X�����$�%� �E
(��=��D��g������5&���zv*�vr�}����;'��O�!Z����'�=q�����u6..)�v:�c2L�J��+bNa$8I8�z��O8���S��X~'a8�����0Nx1�HB��Vr�
/�H�r�\�G&��2�n��yGG�����f{X#�����i�Z��D�/y�XK��a�� �����Wq�����T�P��%Q��LpC��IL�����4F��e��qA���4����s	Q��S.��>7��U��v-���r�����9��B�f^��D=�^ �����[[5?��{��%H$"�A��3��R=qdY+`�0�� ��r&��E��M}5��f4�:kp�\	������4����sMu���X;���������K�=���[�G���5���fB�[��	������������O�D[��m�Ju�rW�@B��Su=`�2��J�����w��R����BB����;�D��W�!��s*hzK��d���f~Z�#�� �d-�A��AG���g�]r2^�`��+.L�[����X60���9����6J<W�Q�U���a!'A��Uz_z"Ve�%������Ag�}���8;{���N��Fp�_��8�2A�����5O��b$��d����_��� .xJ]�RpDq|�!f���`���1#$�	`N���O7zi�}����t��|����^�r[��s.���>� �?�l����z[���A�\�<�`
NK����J!���t�J^����������I�i|��GJ=>�oB�MI�
����x#��:"G�!����������}������w�����+�o��o����-.�5o�"4�
��������M�
��azZ��*m��g����r����y�b��z��3H'�$nsA)z$?�)@�2�JEa[@��K��R���(Mz��!m��T�Q���t��Fa��������G(|�z|�3����,��%�C��a:��r�oc?~�S
H�L����g5-���@������>����0R�����ZR�>��_����tp2�����X�������j<W&\=9e�%��4w8;r����\��z��n��^��p�
���k���U�����
���/�(��R�0`���2�j��m��.qx$�`�B��O�S�I��<(��"�m�#��� 9����B��>��_��2��t���H`��H�����������d�/\��_���D��De��_<�g���C����*,!�B����[����v{s�I���XU�k�%�	����b0�(Y�U��l
Z_����`�D�/���j�����k�6 �kPd��"c�"i�9�9C�QOX��HK
�������F�������8?p��.#�$.�s�H�������0��T}K�]����d��~�	Y�x�����
0f�2�X"^�-��a�����#�t!�����&�Q���g,�ivr�}Ir�x�Wj^�����L
������ont=i�m=�|4�����t�4$!��G������.�C���LG��������V��\���o7%�4���oS.���k[��._�z$���.���1"r{�4-��0���7�-i���DRY%�\2[/�:.�����a�;~h����t@����y`=��%�2<������\s.���}w�f���������������"&:�b�Q'=��m	��/���3��� i����Gi����t\��G#��=���I(\~��7h�2(���$�~��cB��z��2Mg�� ~�`��E��Zs��	���Z�Eux���B�7
^�c����/���k?f?�k��%�e)_��)���b��A�b'�G8������9�������_6�-���In����9����x�]��(������*=��d��%
�e%��O0E�����ir��/k=d����	[t�W����Mkf�G�C�y���I��Wq�4�~�s\���6~�gG�h��o���+��C�+�@����Ze'��[S	����as�K�f�w n�"�}�,0�n�o����������M�F#B,���2�C|�a��1W����
K�����������9�b�a(���mqTk�D��4��y��e(��=`p,�j�|j�B�mO ��J�
6���f��hV�qu�
t�2w���p��t	�=�B�W����;h4��4�#K'�@�Q��r}�]0��5����2����V��S�Kp`��P*:���}���v��Sph�Q��U5/[����p9�����k��x�]=��������8r1H�A84x����!*���������j�t�����t�g�����v[T=�dh�a2�U�Qa���F{�X*e�ZI5u`1.�I�����rJ�J.�%��D�q0}���W�K�0��i��d�3�5�a�TN�������A�e� {
	(!����U�]'.	�*�X�����S�w���R��l��.S;RG1��A�I�o��P�����G��`A�C�������^zD��
*�,����~��B�g�����\Y9�}�Q���� r ����1�� �4�N���OV�N�
'��'h��������U��(R��HdP.^�o���%�<iX�D��I�c3:������4'�y�a����n���w��I�8e�4X��[�f�n��������;"]�(3a��=\W�8��e����������/5#���8o�o�9�|7Wp6L�l�Lv@|A�
P��*����|��+Z={\��o�
)�G6���Ci�-�9:����N�4�t!@�b�w%��|W����u!j���f��g�1�A	F,�d�Q�c�A��9��2~5<�6����nw{��[3��N�,2A3�?F��Y����y��x3�l�t��P\�j�����K�S��8N)�a<1c�������R	;(/I������%�I��X��	��|����y�OND�;x,��� l����$���{a�civx������L0�)�D���C#�,
���D���o���Aq��^i
m�o��o�Z	i�*�!�$�#�KQ������_��q;�	7�J��Z��iq���A9�{���U�sFO���^������_�;9���~:�Y����X|Mmn'k��4�&T����mC���p#k���[iXY�����m���a(y�.m�F�*����m����P�����^l
X���������r�l`� ����~��`Sft W�R�Y)�BFf��S�eNoez�
�}���#����@�PCM�#�;uE�\�B�(
�*��$��+�$��
�a�G
�`F��|b��0�UBN����5I������&��<
����`z\�`�)�NOr�q���S�N���)F`{# Ko1\!��2|���Y�)��R��9��4�L���V_�����I�G	����I�en��x��w�.��n�����������`o w���q��>c�W='9��s���\�1���O..x�����5Wgb8���3%#�"�n�m�����'w<w$vP4���}�c�j���z�i��w&2���|��fD�;��n�0�]�!�@��4}�g��l,1�
C�kxn6aMGPa//%�����I�����1���~�vo���6)�}c�o��z4p@�����%`�KS=X���r:B�Z�j�M�h�)�����h�q��*D4S+�D{�-����&q��!T��n%��"PZ9���,5�4d9{/t���J�W��h��n��(>�����-^K��^�Hr�_�������x�H����I��E�8��U��t����U�'�:%�����v$��YV3a�R�@L��WzaF��b��q��T0Q��-���mTE{�M~t��+�h�T��p-Pcee:�L,;���whcM��:�|����F�4����u-u���:���Wp(ZR1���!�����_p9���I���
^����y=���0��=���/��=�p����H����kf��Y8��f�>�
���<��V�7@���`B���L�\r�Lu,H�IQF�B)L?��@h��x!� 	����� ;fQ$�a���
����_a0
��GB%�x"uc(�A��0�#6pd�QH��v�������5>�%����J��I1��b�&�Bl�G�[�	��B����a�q����Uf�����'h���JW�Q���9�g��9=���)��gI!�e�����Gh�>= �\p��3 �M6;��j��L�&M#$>���|:��HK�!B���h0{��q�w�x��rm%��V:��k�T�?]p���lF����V
�����	�*�f�i��iRGq5�,����m�r�������4L�ju��W8 @5w�n�v�[Y������|^e^��������C�fX_���S<�z����v�����-��El���L��6"��]����������y%4+�o3�dK���K�9�q���-��i�)��'��^�
k�3Z�>�pV�m�lit
���-q�pT�2ZI��S`�5ve����������a���'���<~��|J���{�d��w{@I���7	0���B�l�r/D4Vm�����Y�G���y���'���`t_���<��aH�O�%
��sWNdjH���-�-�.��9jm�y��&�Tq����
�<�x�Y!�0W�A�b�e6G-��nXf��&����T�8^7�q��(HzZ���j�>J%�Q���G*�j��^������p���n�������M)Qp��A3�?#�)���G^��v=�8-2`o���r2'���nI7�7p�a2vN)�@�5'�^���5���.�g�����%��P00@�t����V$�/8�P��'E!��I(���K�`�
5���U���U(U/9���Sql�3�������w��#1%z*�����^=HS�'XaN���
hi&O��-�(l������BD���{�uU�O�������/��}�^���/��B���tle68k���@gU�;n\����|�*T������Io
��Y����������EK�i2c�����K�	;���@�J&������h��\=t4X2�W���y2��ET'L�Q�Mo8��Q���|���'g�����|�F��!�Q�YE��M���$�rw��A��4�j���)�Z�	I�[h0�!��+)c1_��kD������h���/�*�3�]Q�uC�t��>���w����L��L����Y9�|������c��I����B�������i��V����vW;�	L�������W�������'���L�SK���g�*q��qr1&�����CG�"���������-�JGw������ ����k�:A,8B�Z��;�1�����!���s���MF��1|K�)�*0b��h���
Y����f��w�vD��#���,L������,�-����Ph��P�������nX�q��_�{���b|5`�>G��P���O�+�I�u�f�+������T{��V�U��N����Fe��[(^��-TbZQP�kq%K�d�g�V^Z�]B��N������U�:��#�2-�&�X8��a�Kg������]����-Hi"�Rz������t{�98��3�G��^C3��UE�%����TR)1`��2�N�PS*A�=�g�[�Pz�w��sJ�o����z������Z�8�`�V�.Y`�N:>����-�o>���K���f��O�!����?���AwU��z�2"��y<��^�x{�e���rq�,�T��a�s�th3�J�c�+�R��]V���>*�y�Ys��3�{E3�]�8E���%���>�������������{����x�U�{��w��_���7���TN�f��Q�~
.u�F������x������R�~�#r�G.T^F�M��Km��l�ZH�
Rs�W.������Vi�C��&�5�<fZv��Q���cm��_���ls���,k��g�'g���19��cE���a��)j�a`uv9��p�����W4��&+6��$D���f�b���������d�Ggr9������/����?����%�wW��������������C������~��=j�7��ol=�  �=oW��H{LYZO��!k��D�p1L�pJI_1Y��#Wm��G��b$%�]:z8O�~BC�f�4v�U�M�=�|�&	�6$����{����m��CLf�P~a
�D�e�x�en�	{���DB��;��F0��d'M����=�v�����>z�bA��N��6C*|LG��+����[����%H%d%���]c���$�rp���<��a���Rt�����+�����7�76xf�a`mZ�n�:o����c�����3��q=��|�����}�&�;{����f�w���q��4����'����#��
����&���h"�Bx1�*"�e��N��F����TEM��P�Hg�
����\s�k���`�/�J�K���0E�{������DDW�|�N7�80������O'\�w����+��r�qD�G��>��o�<=�z��h��z�8;� N	~(a�H"z� ����]��``/����S`������R��|�<�pz��4�_�9�hh��"���$�v���O�����H����t�������������ut�L�0��#i���F@-!�f��<u*1.W
t�mN�8V���b�~���E��y���8z3l���0L:C��Jp���z�|�2x&�X[����o��Vx;r<ugg�o]��m	Q���E����m>�('p���N�7�-. .]�5��D/����
��6���u#�=3;����f$1�	����������=�g%��� ���|cD�$D��_�,�:P ��C���[[���2P F��#�*���%S����zq�g>��+����2$��� ���I��D����R��[�����*��4�a��l>�P�5Ai��Y�*�6��;"#��i=N��^��^��JY/u����n\��By��o��O�G^"r���>0�����;_��w��+2`4n�H�p�����h�
��X��$��h>p[�:��CS:�n��������w�zh��U���1����qh�	�����E�o|������t��0I�w�.|Z���g�{�i*�$�9�Cs���&��V6����GM)�����%�7�)ea?�B��t �����c=��)���}�)�G�@~x?���tq01k�H�h�bu��������.<���5����O_��]�:�����"�kJ;p��38L����(�bpO�	�VU7?�u�������~���x��q6__��^U�	��Qt6��J��h���Bn��J�����S��[�f+�?��������'�c���v@8��vUpIl
�as���e��A�O�f��`zeb����d��I��Jp0��8���������U�n��!�G����n��I�h����3��������45M
����r��P�����l���z�����t>e�}����1{	������8L�����������dj�K�\gd���!1����m���[��E#M�/��G���S�dt������w�O��c�_�(;�G�!��t4��H�w��w������^��2-2��������[OSG�l:��)�=�u+a�0R_�.�*\l.�������)`OR�JsG���8#A[p��#D�r}�bM0�+|�z���q4������/i�MB��T3WH�LtA8��[6F�BK���%��e%x���
c���F)&�������]	�9��U���T��B�:0���u��k�p���l�Lw�>|<�;9��m����
�lK;���$�e9��j4��zd���gT����]�>�5����,,���CJ���0���������F����%)��)��yv�	���J�&
����hI*�K�R@	S������iYN/3���ff��z��&I�r�#�c�d>��ec)���9��ng����wq�T��p����=>c������o[+�7�v������k��l�?��CO����;(����S��Yi��$l��Q�F�\K*,Gz��k��h������;Z�7po�K�]���d��p�V�w8{-Y_���e��l���iw��3���=�z�5���g�v��[�)�q�R�`�V�U���8���zy>,m�1�P#`O�x[�16��{
X��?:���r�����&|7���ev�
�d�;%�?Q������&��}!?5�F�*����')\(�P�����e��������H����y�*w�TQ�]��������v������'�����Qm���
r�������T�)��={�"i$�Dq���� v�*x��w�'�����M �dc5��;�9n��g�
�����}��
y\�y)��3��}�o���=O�n���t�������=����)S��H���k=:�M��y6���\��k3��c����������l�hm=im=mm>mm�<����;~_������f!�Z��������S�E�{�������E\�@k���P��u
� �^�d�Z%�]�E�M�t���	��n��>�O������l�E�|���qV��n���U
��&g�d�Vm�@g����P��5�U�a|��d���D���W[Y���
�����"�%�����I�ac]6��E��7� �'f
����>i�P�ER�CY�`P�!�����P���vbsWkv1�d-����V��������������o�5�gn���cK=����;)�������h���>�]���t���+�(1�s�@����Q��&��'O�J��iO�FFd�,W*rm�w�M"���Hx���

�
��bx�R�)�]�c`�A�Y��_�?r,�On�M�9����>8��|���B� �]���GO6�����������G����Qi�����z��x"�����B1e�X5��kM�~��Z�
��
���u�u��<GI(����v@����WD�"ig��������X�w���������9��d�W$�4�du�gg�rz[�v����;�q�C*a`�	��'[���-�2�iJ�Z�v���}V��X�U���J�L���v����'�g�����o��E�9�����3H���X{�`�G�O*?��*I�p���P9aJ�d���oF�0��1�5���1��5z�dkcsk����v���.f�#��}7.�#����
M������{;G�{����i�q�Q{����f�Yg�Z�ejF;Y?j!���#���X�F��V�{��\;i.I�V:��������� F�f!r����G�����������?������k�+���O����]c�W�
r��
�;�/sR��d4���vy�;�����i<��G��G��39��������!8��$a���������^S�4�+�w(cu���e�$��8������:�9KE�K$�V�n�`�����z�;B���.T���9?��V��Y/�"u�8��G1�UE ��&�x�X�ku`r �G%���(G�
c��5��I!.SIp���e�D��%�����>a*�U�6&�� /'Ha<���v���[��j:
�@��z3�R
B�jP6�u!�@���I�������!#3Nn*n�~�����(��%��q���$r�Mwx�#+'A�t�H@�%Mc\�;���)�����N2r���D4D��z���;���U+�b����~8^��U\\A�c�d �$������2�b����G\�q�06$�J��p�A��������(�b�����1�&�~�8~���g��Cr
���R�3~B�	N���,����H?h���Y�y�&��?�q�i�?D�~�������R���"/��	:;f��$���J|�P��s��y'��,_".|�-���z�o'�#6Z��X/
���6�g�g����5����������K��S\q�'��o?��D�~��b:���i]g��(h�so��5*������N�B������q����&��������(8��S���������2v)�j�����]W�t����}���9���6���p}
�|z�!,�8%m��Z.�:z������b�{�����;�7V��po���o`����gi/��,�>�~�t��x������-*?,n������Q=�Si�!������S��Z�o������_�*?��}9��} ������k����`V����JIi�����DO�It(J��������3R'�shyw������R[��/�b��)B�(L�SCmbMB�1��� �p��5�fc_�6�y�/<N����+!F�3��U�L@f\-�`����r�
�DA������KZ��N�z�.���E��e�*�h��H��BR1L�3,�����w�0��v��d�b�>��y�]B>�;{]���0���������|C2>��<��6+��#����p�d�P��@����q���u�����=8���5���x6���Y�7�XYY��yQ�=3�������z�����(�y�<���������O�Y�:�' ���E6�����_z�����V�2H��5�_d4�	��W��B�[��m���9��1����vl�X�b�}����/�Fr.%�9�@I]NN����.w��]*����������k~i,�B����k^���zS�S6�lf��am���\H������Yw)�>|�#�?z�)��@��-�;_ w3��Z�R�R���h�,:5_�>�;:��;~�����cW���q�!�B��M�|PVu �=�yYu�)�BI����]�����%!�R�-Auxb?"�;0��������y�9q��6�w1~�+AV���i�>G�Fs���:��B�����W$���Tf�b$l��2�@P��|��B?^��+VVP������B����J�):M������"[��R
#��}����+�HI���V�j�����>|���?<�;&
*�;c�����w�w��r������������5����C���F1������������[��kS\Z(E�VI�&�%��d�(��)���c�)��G�q�%Tr�/s����x�F��l/��c@#C~���63n��B?s��&,0)�t� 0�A�~5g�ZZ����H 2���=u�1���]gzm):�C�-�F�{��&�$,�h?����T�B��=^k�p�������U��x�*y d�S�oL�2C��D�aw��t\������+P6P����� ����D`����3Nan��=��	����{2Y�R\)�>�����Bj~k	�Ld(�u���n���@��B���t��,�O����v�:"}�h���s7��F�{�JX���]z]�N�yI�'�I9�)���gLl�Eq��$
a	��+�!���I����,�*GUD[��&�
f�E�r��c�X�P�1ui��&�<���e���,�]�������F�'��,9�"P���k(	�������(��_���@�[�
���7����{+;���N�����(�
!��hL�,[�7�?���7P��3���
�����s�Mq�7���d������_����H��rK
�.��-��:�%�c �E�7�~N��EV������7w���
�����)�<-�84D����c��J�X/sWB��@6`�A~J^0��[P#�@~CN�	�������Q�/�=L
���2E����Y��������]V��K�M�� o��Z��7����,����c�O��k��gx�+�F�"/)����X(�.8����C�Fe�r�-`ka�����?\_P���T����F�����)�:9���es����_�v���
bP���m��dN��^��U���tg��V��b^b}�S����'��U�'�(%�!�M������Y�(]}`�)�xP.��c8�>F�!�*k�V�H�)�5j�hft\���s:�Q���~^~�C�
��4C����W��9#��,a+�"��7���"�Q{|c�j��K��
Y��o&�^�B
<�+��4��;��9560���I������v&�?g����]���� �dw�M���,�-��[�������G��~F�������e:��*��v� (������|@i��@a��Q11j6j
��)�+2�6�N���E�E��m���b:�[��#uD�����8�C�����!t��0�c��-�,��KrW�yF��e9�.|���l���w�n�"�H�l+y����I�p��g��\[',�
S+���?�4���<������LQ�
���_�����">�,��"l _�u�u�i��x ��Hw��f����
�i��U�C�q��f��'��BtiD�"z����Pm=�F/�����Q!%R��1������D���EM1f$�V)�wG�^������aj���q�2������.��)��@�-&Y�^����q)�s�1�9�*����~��+F]�*�@�pyV^��1A����7���N+|�'P\���dG|�D7�N�]���#�Qw��E�v��aU�<�Y�xK�����o �D;��gc6&nl<�J
��	� �7e��T
�*�����X���%�QeY�!F�E:v\�E�7��;wV�|����cT�@��*M__� 9�a/!���pRLa���e8g$=�
����2����1��l~L9H�L�p�93y7��V���l�|���EVb]J�*�@�?������������S���F�)��,��p������psD�):�(r��G�Q�=���_��u���������p�@�w����d��*U�c5��+%!>1���k��6�%�O���W.5�|���.Nd7�h������!�q�Jc��^������^��fu-�=��,�j�M�P��C�A'|e���������$��c*�T�P+�c��`�Q�!���������,P���f���+�B���)��M��H��9�0BT0�F +��c�I�L�x�Ie�������__h���m^��J�7�V�n��;.����:�;�x��o����M���l��6��,M�N�'>�u��V7�~��{W�
���2�K����V�kl��l]�[�+�����k6��6�������-������?�S/�����0=`;����_���Q���!���w��'B����Md�����\����-q
����F�"��	����A����cq��K�~$��{�I}]&���f�q
w{���q����=z���b�Q=tQ����p��"�.�LJ��j�yA�����,R���"E������
'[T2*���8-/lD�	�C^�cTN�2��w|�r�wxJV7j]�g�#"�M���	����G���+}�}|��a�x���t���A
������Oi�j�PK6�]���c��Z�[���Qb.'�f�#q7����w#U'��a��f���H]���?�Mk����XX���_�X�����z[���%x
~�zA����O��O�,K��%_ �����y�����U�x�(Zh�SKFo.��2�5]�D�c
o�q	���:��J�������lO�L�J�?D�:���!t��B������ry�G[XM������-��66��P��5�����S���L��}����apd��e4[.6]g�r�oqW���}&��S	��i��>gd�e�h�E���4�:U�'[� ��c�{P��u>��������mP��S�;��z��D��'����P����,��\���`�x��z:�^�V���J���Z��A�N���!(�^V�����hfZ�t�-�F�b���Y:�l�Ij*K�}]��)���-�7n!��H
�������=�|P����#/:,��De���_�V��k�]���}Q��h95|�Xc����<����$D 0����:��;�K���_�\R,�|f��%����&H�m�-�jb��/X	���V�����G��I�6�F<����p��gT���3��$A������e$�%
�m����5���.Nj�
5����qFn�n���,�~�#�B������C��u�y��A��.����q��Om�������v����H�s�W����H�0�Cvv��2��$�{����
��m6�������dI�����|�`Y/��h�������<�_PB�C��X��j�z�/�A�x�1m�����
+����4:"�U�=]E}��t�5J6*�=/��z��}����u�yo9�2��d����U
��Z��i�{2.sG���w�$���sp1� ���F�\��`��sN���
$3o�/{4Z�[��d^�
�DM�2��s3������ !����@�����q(��Q�������U��%��
�%UC��`�G8��!f��{��8�����������9�5*���i-�E�pn�@�F�����<gu�������/w�^[��33�.y�(���A�a���*X�����@~�Z�y7���f��z4�4�9K��'aA:
�<F�m�{x4,~��FX%�`��4��0�C�'�c*���\�:�0�d�K�v`�_�'R7�!��?
��@���0s+i��1Q�%oF��
K[���h�
B�p��({S�@X������^o
����5��h=(��<�K/\�r
F����E��u�hbEO�'���vX�o`(�#;/��+�ZX���X���e/�>�5�A�p�jMvG|~�@�F>5�h���g�&"�)NO����	�:�m�v7�K���9?����N=������vb�wZ���n��=OEx5���5E�����������1�g'^#���������K��6�9M���~ Q�8���B
d�3!�@co��u�K#�%3��h��������U1�:S�t~X��H�&l�Wb��t��
B��O�~�#M8eIq������MnU�����/���j�,��d�����u�W$�m�)�\&�a6��5���\��]�%��S����.��.���A��_�@�M�F�J����j����t����W�FgwbD[
L��]�8IpP��������~����o�F���p�i�
�����K%�*���ZI������_�f������FiQ���K��f��yP� �r���.��5��Z�g]A�O-�g����D�W=f-X���:�P���o����n������tU�z��Y!���������'3�����ZD���"��*�B��A��7����w6?-w���
�$0������|)��U��[�
�Z���U��������!,KC���F,��W���jNN��A��6�&��f������Z,	�5|('�.~��|��'?��>����T��e47TQ�$��~{�^�U4���/�`Uw��[�����fyjz=M5������f���m(<�)((�b����`G��?DF+���W^'��A���ry�qA��r�=�j������v������Igz�c9���Y��i�0��I=�;�h!S�s&��,����n�Y���{�� ��.b�&�I��{�����C�m�
9�2[��Z��
���Z*���u�_k2Em�
��1�����95�r�4y����,�2�6�%��5�f�D�:�Z�6yq(����@����d8��A�^V�u7C�����n�m���YL
�w�BG����H�V� ��qW�X�}���������G/m�pF���T��������B���K^�x�s�����o��i�H��+����
�1f�s����W�	���f���#8�<^(��������k2�ib�]��a�"-���S�*���S���%�Z���0���k���3-��Ki3.2�zL��f����]0����j�Q\�����k)k�{~���j�Y�V<��
��`����e�J���=-��K�=8�-��d�%��'�[�o
��� �T�$�� %�#�`!,X}�t^��.��8�AR!��n�&�%'�%nZ�!��j�j�(��Z�/��	i�NS�|�&#U� ��fPl*��hK0���p-tM�t���\<��-2JP�BL��0���$M+E�W����D����x*(��s��[I�z�ty	���r�~yu�I�,Z$9�d��<����'�5�"Ja�,�����3�8�A�M|8�e(�����;��4���h(�'���-wse��A��SI��$6����.�[g���0�V-�N���������
���|_Q���v�Rx����1��J6
?[P��������=]��r�E��3rb������v�Tb1A���~0WA(7
WK� E����m$����M����Cw1�zO���pBI-��K:���:J�L&��m�R��O7�K�lJg�UN|/k�T�/��l���[��J~�lI������!]o2�*z-��Z�\����\�k��Q���`�~(���k�^�����t��O�cf��z3�'x�\��Vg,��5���c)������:�f�0�S��M,JM�}�iE�M� "8HY�f�>!� ��@"�	)T��(�S���2����5��o�������b���HP*������n����.�h�p&*�3��	%{�"����	�h�b*�@Sg�2��R�ln��l�+y�
�K�F��r=�H�|��/)��zQ���=��uA2�
�!5Q%{@+�=�����p(��.B2�x�xd��z^�=�N��#�v�#���Q�}$��y�����2 _���t����l�dXTz�������&�|���,{~}����sQ�H>}V���`eL$���u��������������D���+2����a�$~jDv�^��?���X�3�v
����j+k�;���e���I�B��D�dN/>�>��d��/U��Y	�]Y=�}7khu��R��Z����j�{!a��to���{����fp���5���@��>�\�����3?~cb"����e�����'��^��X���������g���������w8��k��o���?`��_8{�W*,�� ��j���R��^~6���43C*�
�L����$,��@�����G��� ��:��H��S�:b��`�de�nB!�(k^��O9��d������K���M�Q8'PNI�GX�Si��6~�H|�g�������A����s��-����*0���<4���07�{�y���W��r�+�
o��^�e�,&J��+e8(�?��9��������hbrQ�uj��%����;K��Ne.���N��EY�i?9������tV��=���3�</��]T��v�z��FI�K�����9r0��`i!o�[�G��44���[��11�O������?�������Xe�-����b�('�Ij3�^�s�������I�+(��4�+P�(�|G/��zbV���/�W�Q����?�������']>�0�[�� ;�0��a7��n&�����v����;��Ouh���(��h�"��M���~0Y�Q��� )_$���:Z�>{�����MA���b�������Dr��/x���Fo61L��{�2$"o(�i��0-�#����[E0��`����|O��:t�I�V�)s@�*+Wz&��3& ��(d�K�n�6��9��Zr����2��p�����|�_�h��)�`*���\��]�����P�gu�|�>`����r�b�Ro�B��([�>LUp4����;�Nk����:�P5�����u��C1o�g������r�m!x��!���]d>gg�2�q�-d)P��"Q�S�gKyO�N�5���L������#f�{�J���f�xD������������&��������~�)���-�ez���u.�����N2��2��^�~��~��`;�R�h� �������'9e
<��ch�G�-,�����L�i�g���@H���W�].�%�PX^������jo%�j��
]<�("�?%`qA�����-��N���kp����6���8~�{pA9�p��R%�����
D4��(���J;m�����$��0�������e����{��{l�/N�?�O�m�k�%&k���8�������O�S�1�`��@_Zi�|H��Ou��c~���o���^����<���lu�7�f�3�j�C���b����#���*�_G] �`�G>,�#�;���aZ�6���Yi�S���'#BOW��3��e$���n�0<42�Wh�n�G��d ���[�EF����J�|y�b%�����{/����y���o}* 4�,��������DT@��5�T�^�eb�mO�����n�9�Oc����}����D�,1q�n�C���5����L��a��(=%Z�jY�a�������-;���NI-5����&/�w��b��0������tU��~�������TZgS������!1��b-�[>��@�v�\���t�j�Z	��F��@�O	�7�r��p�+q���	?2�>G=��iR2��B�a����[�~���R�Q��y��������BL���
0002-wal_decoding-logical-changeset-extraction-walsender-.patch.gzapplication/x-patch-gzipDownload
0003-wal_decoding-pg_recvlogical-Introduce-pg_receivexlog.patch.gzapplication/x-patch-gzipDownload
0004-wal_decoding-Documentation-for-replication-slots-and.patch.gzapplication/x-patch-gzipDownload
0005-wal_decoding-Temporarily-add-some-uncommittable-slot.patch.gzapplication/x-patch-gzipDownload
0006-wal_decoding-Temporarily-add-logical-decoding-regres.patch.gzapplication/x-patch-gzipDownload
���S0006-wal_decoding-Temporarily-add-logical-decoding-regres.patch�Xmo�H��_1�} `l0���M�&:��K����Z�c���v��$���o����Iq��E6;o������x�?v}?8�|8������82�;��2��#���18�$������9�����+L�\aqx���S1��Cis|n�f'�N�c��E��zdp�&�	��q��l�z�{9}�+�z������ �"ZL`��$VL	��d��PJ��yOEY�1�)���Z/i������
zf�W���6!��{�Ya��3
t}C{s5T��eR�`�������\�t������FJ��4X"�$�����ST�������[���$���P���T�*1�
I��,Z �����(PMH���
�|��9RR���5G�p�
���&��?����+n�dY\�!t�����o�ysY+���jx��8�R��/������5�z�{Q&�E�y���S�:��ng��V�� N�ptu����8��//�B��K}*c=[��mX����R��������)��D��c�V���ZN������U�J�����V�pL������D�S]���:&���jw�H�j����c�}�E9j����M��Cot�����UA��)�=�����Tpc�*��qD��!K��a�nk����i���7dJ���x����'��?b>�'5W���lxB�n��2!M.L�"�����lI:��9i�����x��i�:NZw��
8��-�'�c:#Z�[��{���}o����GA46��k�6U�E�l�������Y���_]���;����������p�A��q�6�%���	����6���yh��&4�jA��]�v��&T����3�����z�r�7���>�������o����"�lN3A�
{
B�(��XJ4W��P�F)�%cP�d4A`�o�H?5vn��!Q���'
�Kv��$�QQq��b�,-�%����"��F�%u�,]v��L�������n�Nu6�����h�����Ig@�u;C�B��H��)V���Lf�2
N�dV	�
+F�+C�0����0e�X���b�!�85�M53�X�����p��D��4�ea(����X�`��zM%����rk�4�<V��=���CwpeK�`��9�v�����fny���b9&��Q���:$3]�RJ�4���z�K0;[�$��d����v�h�6���X"��G*Pj�7���yyK\,������R�p���]�-T�����r�cTmr��Y4mw9����bR8���A�����M�M@@�x�A�y��k?����]�h.(��k���VA��B��e���*�*
#117Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#116)
Re: Changeset Extraction v7.9

On Mon, Mar 3, 2014 at 11:26 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-02-27 17:56:08 +0100, Andres Freund wrote:

* do we modify struct SnapshotData to be polymorphic based on some tag
or move comments there?

I tried that, and it got far to invasive. So I've updated the relevant
comment in snapshot.h, inl

* How/whether to change the exclusive lock on the ProcArrayLock in
CreateInitDecodingContext()

I looked at this, and I believe the current code is the best
solution. It's pretty far away from any hot codepath and it's a short
operation. I liked the idea about using snapmgr.c for this in principle,
but it doesn't have enough smarts by far...

So, attached is the newest version:
* Management of historic/timetravel snapshot is now done by snapmgr.c,
not tqual.c anymore. No ->satisfies pointers are redirected anymore
* removal of the "suspend" logic for historic snapshot, instead the one
place that needed it, now explicitly uses a snapshot
* removal of some pointless CREATE EXTENSIONs from the regression tests
* splitoff of the slot tests that aren't committable into a separate
commit.
* minor doc adjustments

I am not aware of any further things that need to be fixed now (in
contrast to features for later releases of which there are aplenty).

OK, I've committed the 0001 patch, which is the core of this feature,
with a bit of minor additional hacking.

I'm sure there are some problems here yet and some things that people
will want fixed, as is inevitable for any patch of this size. But I
don't have any confidence that further postponing commit is going to
be the best way to find those issues, so in it goes.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#118Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#117)
1 attachment(s)
Re: Changeset Extraction v7.9

Hi Robert, Everyone!

On 2014-03-03 16:48:15 -0500, Robert Haas wrote:

OK, I've committed the 0001 patch, which is the core of this feature,
with a bit of minor additional hacking.

Many, many, thanks!

I'm sure there are some problems here yet and some things that people
will want fixed, as is inevitable for any patch of this size. But I
don't have any confidence that further postponing commit is going to
be the best way to find those issues, so in it goes.

Unsurprisingly I do agree with this. It's a big feature, and there's
imperfection. But I think it's a good start.

A very first such imperfection is that the buildfarm doesn't actually
excercise make check in contribs, just make installcheck... Which this
patch doesn't use because the tests require wal_level=logical and
max_replication_slots >= 2. Andrew said on IRC that maybe it's a good
idea to add a make-contrib-check stage to the buildfarm.

A patch fixing a couple of absolutely trivial things is attached.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

trivial-fixups.patchtext/x-patch; charset=us-asciiDownload
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index 4fb0974..3c56238 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -9,7 +9,7 @@
  *
  * NOTES
  *    This file coordinates interaction between the various modules that
- *    together providethe logical decoding, primarily by providing so
+ *    together provide logical decoding, primarily by providing so
  *    called LogicalDecodingContexts. The goal is to encapsulate most of the
  *    internal complexity for consumers of logical decoding, so they can
  *    create and consume a changestream with a low amount of code.
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
index 3b8ae38..5fa1848 100644
--- a/src/backend/replication/logical/logicalfuncs.c
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -2,7 +2,7 @@
  *
  * logicalfuncs.c
  *
- *	   Support functions for using logical decoding and managemnt of
+ *	   Support functions for using logical decoding and management of
  *	   logical replication slots via SQL.
  *
  *
@@ -400,7 +400,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
 			ctx->options.output_type != OUTPUT_PLUGIN_TEXTUAL_OUTPUT)
 			ereport(ERROR,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("output plugin cannot produce text output")));
+					 errmsg("output plugin cannot produce binary output")));
 
 		ctx->output_writer_private = p;
 
diff --git a/src/include/utils/snapshot.h b/src/include/utils/snapshot.h
index 4b25607..8ee9285 100644
--- a/src/include/utils/snapshot.h
+++ b/src/include/utils/snapshot.h
@@ -36,7 +36,7 @@ typedef bool (*SnapshotSatisfiesFunc) (HeapTuple htup,
  * There are several different kinds of snapshots:
  * * Normal MVCC snapshots
  * * MVCC snapshots taken during recovery (in Hot-Standby mode)
- * * Historic MVCC snapshots used during logical decoding 
+ * * Historic MVCC snapshots used during logical decoding
  * * snapshots passed to HeapTupleSatisfiesDirty()
  * * snapshots used for SatisfiesAny, Toast, Self where no members are
  *   accessed.
#119Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#117)
4 attachment(s)
Re: Changeset Extraction v7.9.1

On 2014-03-03 16:48:15 -0500, Robert Haas wrote:

OK, I've committed the 0001 patch, which is the core of this feature,
with a bit of minor additional hacking.

Attached are the rebased patches that are remaining.

Changes:
* minor conflict due to 7558cc95d31edb
* removal of the last XXX in the walsender patch by setting the
timestamps in the 'd' messages correctly.
* Some documentation wordsmithing by Craig

The walsender patch currently contains the changes about feedback we
argued about elsewhere, I guess I either need to back them out, or we
need to argue out that minor bit.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-Minor-regression-test-fixup-for-7e8db2dc4.patchtext/x-patch; charset=us-asciiDownload
>From de3f317d3d162e1b3c546d8245f1cdd2af5a8027 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 00:18:19 +0100
Subject: [PATCH 1/4] Minor regression test fixup for 7e8db2dc4.

---
 contrib/test_decoding/expected/binary.out | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/test_decoding/expected/binary.out b/contrib/test_decoding/expected/binary.out
index 3409d9d..4164784 100644
--- a/contrib/test_decoding/expected/binary.out
+++ b/contrib/test_decoding/expected/binary.out
@@ -14,7 +14,7 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'for
 
 -- fails, binary plugin, textual consumer
 SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'force-binary', '1');
-ERROR:  output plugin cannot produce text output
+ERROR:  output plugin cannot produce binary output
 -- succeeds, textual plugin, binary consumer
 SELECT data FROM pg_logical_slot_get_binary_changes('regression_slot', NULL, NULL, 'force-binary', '0');
  data 
-- 
1.8.3.251.g1462b67

0002-logical-decoding-walsender-interface.patchtext/x-patch; charset=iso-8859-1Download
>From a58dcac943fcec01a722267f93661b93da898dee Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 00:15:38 +0100
Subject: [PATCH 2/4] logical decoding walsender interface.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This exposes the changeset extraction feature via walsenders which
allows the data to be received in a streaming fashion and supports
synchronous replication.

To do this walsenders need to be able to connect to a specific
database. For that it extend the existing 'replication' parameter to
not only allow a boolean value but also "database". If the latter is
specified we connect to the database specified in 'dbname'.

Andres Freund, with contributions from Álvaro Herrera.
---
 doc/src/sgml/protocol.sgml                         |  24 +-
 src/backend/postmaster/postmaster.c                |  23 +-
 .../libpqwalreceiver/libpqwalreceiver.c            |   4 +-
 src/backend/replication/repl_gram.y                |  78 +-
 src/backend/replication/repl_scanner.l             |   1 +
 src/backend/replication/walsender.c                | 790 ++++++++++++++++++---
 src/backend/utils/init/postinit.c                  |   5 +
 src/bin/pg_basebackup/pg_basebackup.c              |   6 +-
 src/bin/pg_basebackup/pg_receivexlog.c             |   6 +-
 src/bin/pg_basebackup/receivelog.c                 |   6 +-
 src/include/replication/walsender.h                |   1 +
 src/include/replication/walsender_private.h        |   3 +
 src/tools/pgindent/typedefs.list                   |   1 +
 13 files changed, 816 insertions(+), 132 deletions(-)

diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index d36f2f3..510bf9a 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1302,10 +1302,13 @@
 
 <para>
 To initiate streaming replication, the frontend sends the
-<literal>replication</> parameter in the startup message. This tells the
-backend to go into walsender mode, wherein a small set of replication commands
-can be issued instead of SQL statements. Only the simple query protocol can be
-used in walsender mode.
+<literal>replication</> parameter in the startup message. A boolean value
+of <literal>true</> tells the backend to go into walsender mode, wherein a
+small set of replication commands can be issued instead of SQL statements. Only
+the simple query protocol can be used in walsender mode.
+Passing a <literal>database</> as the value instructs walsender to connect to
+the database specified in the <literal>dbname</> paramter which will in future
+allow some additional commands to the ones specified below to be run.
 
 The commands accepted in walsender mode are:
 
@@ -1315,7 +1318,7 @@ The commands accepted in walsender mode are:
     <listitem>
      <para>
       Requests the server to identify itself. Server replies with a result
-      set of a single row, containing three fields:
+      set of a single row, containing four fields:
      </para>
 
      <para>
@@ -1357,6 +1360,17 @@ The commands accepted in walsender mode are:
       </listitem>
       </varlistentry>
 
+      <varlistentry>
+      <term>
+       dbname
+      </term>
+      <listitem>
+      <para>
+       Database connected to or NULL.
+      </para>
+      </listitem>
+      </varlistentry>
+
       </variablelist>
      </para>
     </listitem>
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index b7f99fc..c214053 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1884,10 +1884,21 @@ retry1:
 				port->cmdline_options = pstrdup(valptr);
 			else if (strcmp(nameptr, "replication") == 0)
 			{
-				if (!parse_bool(valptr, &am_walsender))
+				/*
+				 * Due to backward compatibility concerns replication is a
+				 * bybrid beast which allows the value to be either a boolean
+				 * or the string 'database'. The latter connects to a specific
+				 * database which is e.g. required for changeset extraction.
+				 */
+				if (strcmp(valptr, "database") == 0)
+				{
+					am_walsender = true;
+					am_db_walsender = true;
+				}
+				else if (!parse_bool(valptr, &am_walsender))
 					ereport(FATAL,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("invalid value for boolean option \"replication\"")));
+							 errmsg("invalid value for option \"replication\", legal values are false, 0, true, 1 or database")));
 			}
 			else
 			{
@@ -1968,8 +1979,12 @@ retry1:
 	if (strlen(port->user_name) >= NAMEDATALEN)
 		port->user_name[NAMEDATALEN - 1] = '\0';
 
-	/* Walsender is not related to a particular database */
-	if (am_walsender)
+	/*
+	 * Generic walsender, e.g. for streaming replication, is not connected to a
+	 * particular database. But walsenders used for logical replication need to
+	 * connect to a specific database.
+	 */
+	if (am_walsender && !am_db_walsender)
 		port->database_name[0] = '\0';
 
 	/*
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index c10374c..2fb731b 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -131,7 +131,7 @@ libpqrcv_identify_system(TimeLineID *primary_tli)
 						"the primary server: %s",
 						PQerrorMessage(streamConn))));
 	}
-	if (PQnfields(res) != 3 || PQntuples(res) != 1)
+	if (PQnfields(res) < 3 || PQntuples(res) != 1)
 	{
 		int			ntuples = PQntuples(res);
 		int			nfields = PQnfields(res);
@@ -139,7 +139,7 @@ libpqrcv_identify_system(TimeLineID *primary_tli)
 		PQclear(res);
 		ereport(ERROR,
 				(errmsg("invalid response from primary server"),
-				 errdetail("Expected 1 tuple with 3 fields, got %d tuples with %d fields.",
+				 errdetail("Expected 1 tuple with 3 or more fields, got %d tuples with %d fields.",
 						   ntuples, nfields)));
 	}
 	primary_sysid = PQgetvalue(res, 0, 0);
diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y
index 308889b..08587bc 100644
--- a/src/backend/replication/repl_gram.y
+++ b/src/backend/replication/repl_gram.y
@@ -73,13 +73,17 @@ Node *replication_parse_result;
 %token K_WAL
 %token K_TIMELINE
 %token K_PHYSICAL
+%token K_LOGICAL
 %token K_SLOT
 
 %type <node>	command
-%type <node>	base_backup start_replication create_replication_slot drop_replication_slot identify_system timeline_history
+%type <node>	base_backup start_replication start_logical_replication create_replication_slot drop_replication_slot identify_system timeline_history
 %type <list>	base_backup_opt_list
 %type <defelt>	base_backup_opt
 %type <uintval>	opt_timeline
+%type <list>	plugin_options plugin_opt_list
+%type <defelt>	plugin_opt_elem
+%type <node>	plugin_opt_arg
 %type <str>		opt_slot
 
 %%
@@ -98,6 +102,7 @@ command:
 			identify_system
 			| base_backup
 			| start_replication
+			| start_logical_replication
 			| create_replication_slot
 			| drop_replication_slot
 			| timeline_history
@@ -175,6 +180,17 @@ create_replication_slot:
 					cmd->slotname = $2;
 					$$ = (Node *) cmd;
 				}
+			|
+/* CREATE_REPLICATION_SLOT SLOT slot LOGICAL plugin */
+			K_CREATE_REPLICATION_SLOT IDENT K_LOGICAL IDENT
+				{
+					CreateReplicationSlotCmd *cmd;
+					cmd = makeNode(CreateReplicationSlotCmd);
+					cmd->kind = REPLICATION_KIND_LOGICAL;
+					cmd->slotname = $2;
+					cmd->plugin = $4;
+					$$ = (Node *) cmd;
+				}
 			;
 
 /* DROP_REPLICATION_SLOT SLOT slot */
@@ -205,19 +221,19 @@ start_replication:
 				}
 			;
 
-opt_timeline:
-			K_TIMELINE UCONST
+/* START_REPLICATION SLOT slot LOGICAL %X/%X options */
+start_logical_replication:
+			K_START_REPLICATION K_SLOT IDENT K_LOGICAL RECPTR plugin_options
 				{
-					if ($2 <= 0)
-						ereport(ERROR,
-								(errcode(ERRCODE_SYNTAX_ERROR),
-								 (errmsg("invalid timeline %u", $2))));
-					$$ = $2;
+					StartReplicationCmd *cmd;
+					cmd = makeNode(StartReplicationCmd);
+					cmd->kind = REPLICATION_KIND_LOGICAL;;
+					cmd->slotname = $3;
+					cmd->startpoint = $5;
+					cmd->options = $6;
+					$$ = (Node *) cmd;
 				}
-			| /* EMPTY */
-				{ $$ = 0; }
 			;
-
 /*
  * TIMELINE_HISTORY %d
  */
@@ -250,6 +266,46 @@ opt_slot:
 				{ $$ = NULL; }
 			;
 
+opt_timeline:
+			K_TIMELINE UCONST
+				{
+					if ($2 <= 0)
+						ereport(ERROR,
+								(errcode(ERRCODE_SYNTAX_ERROR),
+								 (errmsg("invalid timeline %u", $2))));
+					$$ = $2;
+				}
+				| /* EMPTY */			{ $$ = 0; }
+			;
+
+
+plugin_options:
+			'(' plugin_opt_list ')'			{ $$ = $2; }
+			| /* EMPTY */					{ $$ = NIL; }
+		;
+
+plugin_opt_list:
+			plugin_opt_elem
+				{
+					$$ = list_make1($1);
+				}
+			| plugin_opt_list ',' plugin_opt_elem
+				{
+					$$ = lappend($1, $3);
+				}
+		;
+
+plugin_opt_elem:
+			IDENT plugin_opt_arg
+				{
+					$$ = makeDefElem($1, $2);
+				}
+		;
+
+plugin_opt_arg:
+			SCONST							{ $$ = (Node *) makeString($1); }
+			| /* EMPTY */					{ $$ = NULL; }
+		;
 %%
 
 #include "repl_scanner.c"
diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l
index ca32aa6..a257124 100644
--- a/src/backend/replication/repl_scanner.l
+++ b/src/backend/replication/repl_scanner.l
@@ -94,6 +94,7 @@ CREATE_REPLICATION_SLOT		{ return K_CREATE_REPLICATION_SLOT; }
 DROP_REPLICATION_SLOT		{ return K_DROP_REPLICATION_SLOT; }
 TIMELINE_HISTORY	{ return K_TIMELINE_HISTORY; }
 PHYSICAL			{ return K_PHYSICAL; }
+LOGICAL				{ return K_LOGICAL; }
 SLOT				{ return K_SLOT; }
 
 ","				{ return ','; }
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 4fcf3d4..a8009c5 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -45,15 +45,22 @@
 
 #include "access/timeline.h"
 #include "access/transam.h"
+#include "access/xact.h"
 #include "access/xlog_internal.h"
+
 #include "catalog/pg_type.h"
+#include "commands/dbcommands.h"
 #include "funcapi.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "nodes/replnodes.h"
 #include "replication/basebackup.h"
+#include "replication/decode.h"
+#include "replication/logical.h"
+#include "replication/logicalfuncs.h"
 #include "replication/slot.h"
+#include "replication/snapbuild.h"
 #include "replication/syncrep.h"
 #include "replication/slot.h"
 #include "replication/walreceiver.h"
@@ -92,9 +99,10 @@ WalSndCtlData *WalSndCtl = NULL;
 WalSnd	   *MyWalSnd = NULL;
 
 /* Global state */
-bool		am_walsender = false;		/* Am I a walsender process ? */
+bool		am_walsender = false;		/* Am I a walsender process? */
 bool		am_cascading_walsender = false;		/* Am I cascading WAL to
-												 * another standby ? */
+												 * another standby? */
+bool		am_db_walsender = false;		/* connect to database? */
 
 /* User-settable parameters for walsender */
 int			max_wal_senders = 0;	/* the maximum number of concurrent walsenders */
@@ -145,7 +153,7 @@ static StringInfoData tmpbuf;
 static TimestampTz last_reply_timestamp;
 
 /* Have we sent a heartbeat message asking for reply, since last reply? */
-static bool ping_sent = false;
+static bool waiting_for_ping_response = false;
 
 /*
  * While streaming WAL in Copy mode, streamingDoneSending is set to true
@@ -156,6 +164,9 @@ static bool ping_sent = false;
 static bool streamingDoneSending;
 static bool streamingDoneReceiving;
 
+/* Are we there yet? */
+static bool		WalSndCaughtUp = false;
+
 /* Flags set by signal handlers for later service in main loop */
 static volatile sig_atomic_t got_SIGHUP = false;
 static volatile sig_atomic_t walsender_ready_to_stop = false;
@@ -168,24 +179,38 @@ static volatile sig_atomic_t walsender_ready_to_stop = false;
  */
 static volatile sig_atomic_t replication_active = false;
 
+static LogicalDecodingContext *logical_decoding_ctx = NULL;
+static XLogRecPtr  logical_startptr = InvalidXLogRecPtr;
+
 /* Signal handlers */
 static void WalSndSigHupHandler(SIGNAL_ARGS);
 static void WalSndXLogSendHandler(SIGNAL_ARGS);
 static void WalSndLastCycleHandler(SIGNAL_ARGS);
 
 /* Prototypes for private functions */
-static void WalSndLoop(void);
+typedef void (*WalSndSendData)(void);
+static void WalSndLoop(WalSndSendData send_data);
 static void InitWalSenderSlot(void);
 static void WalSndKill(int code, Datum arg);
-static void XLogSend(bool *caughtup);
+static void WalSndShutdown(void);
+static void XLogSendPhysical(void);
+static void XLogSendLogical(void);
+static void WalSndDone(WalSndSendData send_data);
 static XLogRecPtr GetStandbyFlushRecPtr(void);
 static void IdentifySystem(void);
+static void CreateReplicationSlot(CreateReplicationSlotCmd *cmd);
+static void DropReplicationSlot(DropReplicationSlotCmd *cmd);
 static void StartReplication(StartReplicationCmd *cmd);
+static void StartLogicalReplication(StartReplicationCmd *cmd);
 static void ProcessStandbyMessage(void);
 static void ProcessStandbyReplyMessage(void);
 static void ProcessStandbyHSFeedbackMessage(void);
 static void ProcessRepliesIfAny(void);
 static void WalSndKeepalive(bool requestReply);
+static void WalSndCheckTimeOut(void);
+static void WalSndPrepareWrite(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write);
+static void WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write);
+static void XLogRead(char *buf, XLogRecPtr startptr, Size count);
 
 
 /* Initialize walsender process before entering the main command loop */
@@ -240,6 +265,22 @@ WalSndErrorCleanup()
 	WalSndSetState(WALSNDSTATE_STARTUP);
 }
 
+static void
+WalSndShutdown(void)
+{
+	/*
+	 * Get here on send failure.  Clean up and exit.
+	 *
+	 * Reset whereToSendOutput to prevent ereport from attempting to send any
+	 * more messages to the standby.
+	 */
+	if (whereToSendOutput == DestRemote)
+		whereToSendOutput = DestNone;
+
+	proc_exit(0);
+	abort();					/* keep the compiler quiet */
+}
+
 /*
  * Handle the IDENTIFY_SYSTEM command.
  */
@@ -251,10 +292,12 @@ IdentifySystem(void)
 	char		tli[11];
 	char		xpos[MAXFNAMELEN];
 	XLogRecPtr	logptr;
+	char	   *dbname = NULL;
 
 	/*
-	 * Reply with a result set with one row, three columns. First col is
-	 * system ID, second is timeline ID, and third is current xlog location.
+	 * Reply with a result set with one row, four columns. First col is system
+	 * ID, second is timeline ID, third is current xlog location and the fourth
+	 * contains the database name if we are connected to one.
 	 */
 
 	snprintf(sysid, sizeof(sysid), UINT64_FORMAT,
@@ -273,9 +316,23 @@ IdentifySystem(void)
 
 	snprintf(xpos, sizeof(xpos), "%X/%X", (uint32) (logptr >> 32), (uint32) logptr);
 
+	if (MyDatabaseId != InvalidOid)
+	{
+		MemoryContext cur = CurrentMemoryContext;
+
+		/* syscache access needs a transaction env. */
+		StartTransactionCommand();
+		/* make dbname live outside TX context */
+		MemoryContextSwitchTo(cur);
+		dbname = get_database_name(MyDatabaseId);
+		CommitTransactionCommand();
+		/* CommitTransactionCommand switches to TopMemoryContext */
+		MemoryContextSwitchTo(cur);
+	}
+
 	/* Send a RowDescription message */
 	pq_beginmessage(&buf, 'T');
-	pq_sendint(&buf, 3, 2);		/* 3 fields */
+	pq_sendint(&buf, 4, 2);		/* 4 fields */
 
 	/* first field */
 	pq_sendstring(&buf, "systemid");	/* col name */
@@ -296,24 +353,43 @@ IdentifySystem(void)
 	pq_sendint(&buf, 0, 2);		/* format code */
 
 	/* third field */
-	pq_sendstring(&buf, "xlogpos");
-	pq_sendint(&buf, 0, 4);
-	pq_sendint(&buf, 0, 2);
-	pq_sendint(&buf, TEXTOID, 4);
-	pq_sendint(&buf, -1, 2);
-	pq_sendint(&buf, 0, 4);
-	pq_sendint(&buf, 0, 2);
+	pq_sendstring(&buf, "xlogpos"); /* col name */
+	pq_sendint(&buf, 0, 4);     /* table oid */
+	pq_sendint(&buf, 0, 2);     /* attnum */
+	pq_sendint(&buf, TEXTOID, 4);       /* type oid */
+	pq_sendint(&buf, -1, 2);        /* typlen */
+	pq_sendint(&buf, 0, 4);     /* typmod */
+	pq_sendint(&buf, 0, 2);     /* format code */
+
+	/* fourth field */
+	pq_sendstring(&buf, "dbname");  /* col name */
+	pq_sendint(&buf, 0, 4);     /* table oid */
+	pq_sendint(&buf, 0, 2);     /* attnum */
+	pq_sendint(&buf, TEXTOID, 4);       /* type oid */
+	pq_sendint(&buf, -1, 2);        /* typlen */
+	pq_sendint(&buf, 0, 4);     /* typmod */
+	pq_sendint(&buf, 0, 2);     /* format code */
 	pq_endmessage(&buf);
 
 	/* Send a DataRow message */
 	pq_beginmessage(&buf, 'D');
-	pq_sendint(&buf, 3, 2);		/* # of columns */
+	pq_sendint(&buf, 4, 2);		/* # of columns */
 	pq_sendint(&buf, strlen(sysid), 4); /* col1 len */
 	pq_sendbytes(&buf, (char *) &sysid, strlen(sysid));
 	pq_sendint(&buf, strlen(tli), 4);	/* col2 len */
 	pq_sendbytes(&buf, (char *) tli, strlen(tli));
 	pq_sendint(&buf, strlen(xpos), 4);	/* col3 len */
 	pq_sendbytes(&buf, (char *) xpos, strlen(xpos));
+	/* send NULL if not connected to a database */
+	if (dbname)
+	{
+		pq_sendint(&buf, strlen(dbname), 4);    /* col4 len */
+		pq_sendbytes(&buf, (char *) dbname, strlen(dbname));
+	}
+	else
+	{
+		pq_sendint(&buf, -1, 4);    /* col4 len, NULL */
+	}
 
 	pq_endmessage(&buf);
 }
@@ -572,7 +648,7 @@ StartReplication(StartReplicationCmd *cmd)
 		/* Main loop of walsender */
 		replication_active = true;
 
-		WalSndLoop();
+		WalSndLoop(XLogSendPhysical);
 
 		replication_active = false;
 		if (walsender_ready_to_stop)
@@ -643,12 +719,47 @@ StartReplication(StartReplicationCmd *cmd)
 }
 
 /*
+ * read_page callback for logical decoding contexts, as a walsender process.
+ *
+ * Inside the walsender we can do better than logical_read_local_xlog_page,
+ * which has to do a plain sleep/busy loop, because the walsender's latch gets
+ * woken up when WAL is flushed.
+ */
+static int
+logical_read_xlog_page(XLogReaderState* state, XLogRecPtr targetPagePtr, int reqLen,
+				 XLogRecPtr targetRecPtr, char* cur_page, TimeLineID *pageTLI)
+{
+	XLogRecPtr flushptr;
+	int		count;
+
+	/* make sure we have enough WAL available */
+	flushptr = WalSndWaitForWal(targetPagePtr + reqLen);
+
+	/* more than one block available */
+	if (targetPagePtr + XLOG_BLCKSZ <= flushptr)
+		count = XLOG_BLCKSZ;
+	/* not enough WAL synced, that can happen during shutdown */
+	else if (targetPagePtr + reqLen > flushptr)
+		return -1;
+	/* part of the page available */
+	else
+		count = flushptr - targetPagePtr;
+
+	/* now actually read the data, we know it's there */
+	XLogRead(cur_page, targetPagePtr, XLOG_BLCKSZ);
+
+	return count;
+}
+
+/*
  * Create a new replication slot.
  */
 static void
 CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 {
 	const char *slot_name;
+	const char *snapshot_name = NULL;
+	char        xpos[MAXFNAMELEN];
 	StringInfoData buf;
 
 	Assert(!MyReplicationSlot);
@@ -657,24 +768,48 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 	sendTimeLineIsHistoric = false;
 	sendTimeLine = ThisTimeLineID;
 
-	ReplicationSlotCreate(cmd->slotname,
-						  cmd->kind == REPLICATION_KIND_LOGICAL,
-						  RS_PERSISTENT);
+	if (cmd->kind == REPLICATION_KIND_PHYSICAL)
+	{
+		ReplicationSlotCreate(cmd->slotname, false, RS_PERSISTENT);
+	}
+	else
+	{
+		CheckLogicalDecodingRequirements();
+		ReplicationSlotCreate(cmd->slotname, true, RS_EPHEMERAL);
+	}
 
 	initStringInfo(&output_message);
 
 	slot_name = NameStr(MyReplicationSlot->data.name);
 
-	/*
-	 * It may seem somewhat pointless to send back the same slot name the
-	 * client just requested and nothing else, but logical replication
-	 * will add more fields here.  (We could consider removing the slot
-	 * name from what's sent back, though, since the client has specified
-	 * that.)
-	 */
+	if (cmd->kind == REPLICATION_KIND_LOGICAL)
+	{
+		LogicalDecodingContext *ctx;
+
+		ctx = CreateInitDecodingContext(
+			cmd->plugin, NIL,
+			logical_read_xlog_page,
+			WalSndPrepareWrite, WalSndWriteData);
+
+		/* build initial snapshot, might take a while */
+		DecodingContextFindStartpoint(ctx);
+
+		/* export plain, importable, snapshot to the user */
+		snapshot_name = SnapBuildExportSnapshot(ctx->snapshot_builder);
+
+		/* don't need the decoding context anymore */
+		FreeDecodingContext(ctx);
+
+		ReplicationSlotPersist();
+	}
+
+	slot_name = NameStr(MyReplicationSlot->data.name);
+	snprintf(xpos, sizeof(xpos), "%X/%X",
+			 (uint32) (MyReplicationSlot->data.confirmed_flush >> 32),
+			 (uint32) MyReplicationSlot->data.confirmed_flush);
 
 	pq_beginmessage(&buf, 'T');
-	pq_sendint(&buf, 1, 2);		/* 1 field */
+	pq_sendint(&buf, 4, 2);		/* 4 fields */
 
 	/* first field: slot name */
 	pq_sendstring(&buf, "slot_name");	/* col name */
@@ -685,16 +820,65 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 	pq_sendint(&buf, 0, 4);		/* typmod */
 	pq_sendint(&buf, 0, 2);		/* format code */
 
+	/* second field: LSN at which we became consistent */
+	pq_sendstring(&buf, "consistent_point");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
+	/* third field: exported snapshot's name */
+	pq_sendstring(&buf, "snapshot_name");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
+	/* fourth field: output plugin */
+	pq_sendstring(&buf, "output_plugin");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
 	pq_endmessage(&buf);
 
 	/* Send a DataRow message */
 	pq_beginmessage(&buf, 'D');
-	pq_sendint(&buf, 1, 2);		/* # of columns */
+	pq_sendint(&buf, 4, 2);		/* # of columns */
 
 	/* slot_name */
 	pq_sendint(&buf, strlen(slot_name), 4); /* col1 len */
 	pq_sendbytes(&buf, slot_name, strlen(slot_name));
 
+	/* consistent wal location */
+	pq_sendint(&buf, strlen(xpos), 4); /* col2 len */
+	pq_sendbytes(&buf, xpos, strlen(xpos));
+
+	/* snapshot name */
+	if (snapshot_name != NULL)
+	{
+		pq_sendint(&buf, strlen(snapshot_name), 4); /* col3 len */
+		pq_sendbytes(&buf, snapshot_name, strlen(snapshot_name));
+	}
+	else
+		pq_sendint(&buf, -1, 4);    /* col3 len, NULL */
+
+	/* plugin */
+	if (cmd->plugin != NULL)
+	{
+		pq_sendint(&buf, strlen(cmd->plugin), 4); /* col4 len */
+		pq_sendbytes(&buf, cmd->plugin, strlen(cmd->plugin));
+	}
+	else
+		pq_sendint(&buf, -1, 4);	/* col4 len, NULL */
+
 	pq_endmessage(&buf);
 
 	/*
@@ -714,6 +898,338 @@ DropReplicationSlot(DropReplicationSlotCmd *cmd)
 }
 
 /*
+ * Load previously initiated logical slot and prepare for sending data (via
+ * WalSndLoop).
+ */
+static void
+StartLogicalReplication(StartReplicationCmd *cmd)
+{
+	StringInfoData buf;
+
+	/* make sure that our requirements are still fulfilled */
+	CheckLogicalDecodingRequirements();
+
+	Assert(!MyReplicationSlot);
+
+	ReplicationSlotAcquire(cmd->slotname);
+
+	if (am_cascading_walsender && !RecoveryInProgress())
+	{
+		ereport(LOG,
+				(errmsg("terminating walsender process to force cascaded standby to update timeline and reconnect")));
+		walsender_ready_to_stop = true;
+	}
+
+	WalSndSetState(WALSNDSTATE_CATCHUP);
+
+	/* Send a CopyBothResponse message, and start streaming */
+	pq_beginmessage(&buf, 'W');
+	pq_sendbyte(&buf, 0);
+	pq_sendint(&buf, 0, 2);
+	pq_endmessage(&buf);
+	pq_flush();
+
+	/* setup state for XLogReadPage */
+	sendTimeLineIsHistoric = false;
+	sendTimeLine = ThisTimeLineID;
+
+	/*
+	 * Initialize position to the last ack'ed one, then the xlog records begin
+	 * to be shipped from that position.
+	 */
+	logical_decoding_ctx = CreateDecodingContext(
+		cmd->startpoint, cmd->options,
+		logical_read_xlog_page,
+		WalSndPrepareWrite, WalSndWriteData);
+
+	/*
+	 * XXX: For feedback purposes it would be nicer to set sentPtr to
+	 * cmd->startpoint, but we use it to know where to read xlog in the main
+	 * loop...
+	 */
+	sentPtr = MyReplicationSlot->data.restart_lsn;
+	logical_startptr = sentPtr;
+
+	/* Also update the start position status in shared memory */
+	{
+		/* use volatile pointer to prevent code rearrangement */
+		volatile WalSnd *walsnd = MyWalSnd;
+
+		SpinLockAcquire(&walsnd->mutex);
+		walsnd->sentPtr = MyReplicationSlot->data.restart_lsn;
+		SpinLockRelease(&walsnd->mutex);
+	}
+
+	replication_active = true;
+
+	SyncRepInitConfig();
+
+	/* Main loop of walsender */
+	WalSndLoop(XLogSendLogical);
+
+	FreeDecodingContext(logical_decoding_ctx);
+	ReplicationSlotRelease();
+
+	replication_active = false;
+	if (walsender_ready_to_stop)
+		proc_exit(0);
+	WalSndSetState(WALSNDSTATE_STARTUP);
+
+	/* Get out of COPY mode (CommandComplete). */
+	EndCommand("COPY 0", DestRemote);
+}
+
+/*
+ * LogicalDecodingContext 'prepare_write' callback.
+ *
+ * Prepare a write into a StringInfo.
+ *
+ * Don't do anything lasting in here, it's quite possible that nothing will done
+ * with the data.
+ */
+static void
+WalSndPrepareWrite(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write)
+{
+	/* can't have sync rep confused by sending the same LSN several times */
+	if (!last_write)
+		lsn = InvalidXLogRecPtr;
+
+	resetStringInfo(ctx->out);
+
+	pq_sendbyte(ctx->out, 'w');
+	pq_sendint64(ctx->out, lsn);	/* dataStart */
+	pq_sendint64(ctx->out, lsn);	/* walEnd */
+	/* XXX: gather that value later just as it's done in XLogSendPhysical */
+	pq_sendint64(ctx->out, 0);/* sendtime */
+}
+
+/*
+ * LogicalDecodingContext 'write' callback.
+ *
+ * Actually write out data previously prepared by WalSndPrepareWrite out to
+ * the network, take as long as needed but process replies from the other side
+ * during that.
+ */
+static void
+WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
+				bool last_write)
+{
+	/* output previously gathered data in a CopyData packet */
+	pq_putmessage_noblock('d', ctx->out->data, ctx->out->len);
+
+	/*
+	 * Fill the send timestamp last, so that it is taken as late as
+	 * possible. This is slightly ugly, but the protocol's set.
+	 */
+	resetStringInfo(&tmpbuf);
+	pq_sendint64(&tmpbuf, GetCurrentIntegerTimestamp());
+	memcpy(&ctx->out->data[1 + sizeof(int64) + sizeof(int64)],
+		   tmpbuf.data, sizeof(int64));
+
+	/* fast path */
+	/* Try to flush pending output to the client */
+	if (pq_flush_if_writable() != 0)
+		return;
+
+	if (!pq_is_send_pending())
+		return;
+
+	for (;;)
+	{
+		int			wakeEvents;
+		long		sleeptime = 10000;		/* 10s */
+
+		/*
+		 * Emergency bailout if postmaster has died.  This is to avoid the
+		 * necessity for manual cleanup of all postmaster children.
+		 */
+		if (!PostmasterIsAlive())
+			exit(1);
+
+		/* Process any requests or signals received recently */
+		if (got_SIGHUP)
+		{
+			got_SIGHUP = false;
+			ProcessConfigFile(PGC_SIGHUP);
+			SyncRepInitConfig();
+		}
+
+		CHECK_FOR_INTERRUPTS();
+
+		/* Clear any already-pending wakeups */
+		ResetLatch(&MyWalSnd->latch);
+
+		/* Check for input from the client */
+		ProcessRepliesIfAny();
+
+		/* Try to flush pending output to the client */
+		if (pq_flush_if_writable() != 0)
+			break;
+
+		/* If we finished clearing the buffered data, we're done here. */
+		if (!pq_is_send_pending())
+			break;
+
+		wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH |
+			WL_SOCKET_WRITEABLE | WL_SOCKET_READABLE | WL_TIMEOUT;
+
+		ImmediateInterruptOK = true;
+		CHECK_FOR_INTERRUPTS();
+		WaitLatchOrSocket(&MyWalSnd->latch, wakeEvents,
+						  MyProcPort->sock, sleeptime);
+		ImmediateInterruptOK = false;
+
+		/* die if timeout was reached */
+		WalSndCheckTimeOut();
+	}
+
+	/* reactivate latch so WalSndLoop knows to continue */
+	SetLatch(&MyWalSnd->latch);
+}
+
+/*
+ * Wait till WAL < loc is flushed to disk so it can be safely read.
+ */
+XLogRecPtr
+WalSndWaitForWal(XLogRecPtr loc)
+{
+	int			wakeEvents;
+	static XLogRecPtr RecentFlushPtr = InvalidXLogRecPtr;
+
+
+	/*
+	 * Fast path to avoid acquiring the spinlock in the we already know we
+	 * have enough WAL available, particularly interesting if we're far
+	 * behind.
+	 */
+	if (RecentFlushPtr != InvalidXLogRecPtr &&
+		loc <= RecentFlushPtr)
+		return RecentFlushPtr;
+
+	/*
+	 * Get a more recent flush pointer.
+	 */
+	if (!RecoveryInProgress())
+		RecentFlushPtr = GetFlushRecPtr();
+	else
+		RecentFlushPtr = GetXLogReplayRecPtr(NULL);
+
+	for (;;)
+	{
+		long		sleeptime = 10000;		/* 10 s */
+
+		wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH |
+			WL_SOCKET_READABLE | WL_TIMEOUT;
+
+		/*
+		 * Emergency bailout if postmaster has died.  This is to avoid the
+		 * necessity for manual cleanup of all postmaster children.
+		 */
+		if (!PostmasterIsAlive())
+			exit(1);
+
+		/* Process any requests or signals received recently */
+		if (got_SIGHUP)
+		{
+			got_SIGHUP = false;
+			ProcessConfigFile(PGC_SIGHUP);
+			SyncRepInitConfig();
+		}
+
+		CHECK_FOR_INTERRUPTS();
+
+		/* Check for input from the client */
+		ProcessRepliesIfAny();
+
+		/* Clear any already-pending wakeups */
+		ResetLatch(&MyWalSnd->latch);
+
+		/* Update our idea of flushed position. */
+		if (!RecoveryInProgress())
+			RecentFlushPtr = GetFlushRecPtr();
+		else
+			RecentFlushPtr = GetXLogReplayRecPtr(NULL);
+
+		/* If postmaster asked us to stop, don't wait here anymore */
+		if (walsender_ready_to_stop)
+			break;
+
+		/*
+		 * We only send regular messages to the client for full decoded
+		 * transactions, but a synchronous replication and walsender shutdown
+		 * possibly are waiting for a later location. So we send pings
+		 * containing the flush location every now and then.
+		 */
+		if (MyWalSnd->flush < sentPtr && !waiting_for_ping_response)
+		{
+			WalSndKeepalive(true);
+			waiting_for_ping_response = true;
+		}
+
+		/* check whether we're done */
+		if (loc <= RecentFlushPtr)
+			break;
+
+		/* Waiting for new WAL. Since we need to wait, we're now caught up. */
+		WalSndCaughtUp = true;
+
+		/*
+		 * Try to flush pending output to the client and also wait for the
+		 * socket becoming writable, if there's still pending output after an
+		 * attempt to flush. Otherwise we might just sit on output data while
+		 * waiting for new WAL being generated.
+		 */
+		if (pq_is_send_pending())
+		{
+			pq_flush_if_writable();
+			if (pq_is_send_pending())
+				wakeEvents |= WL_SOCKET_WRITEABLE;
+		}
+
+		/* Determine time until replication timeout */
+		if (wal_sender_timeout > 0)
+		{
+			if (!waiting_for_ping_response)
+			{
+				TimestampTz timeout;
+
+				/*
+				 * If half of wal_sender_timeout has lapsed without receiving
+				 * any reply from standby, send a keep-alive message to standby
+				 * requesting an immediate reply.
+				 */
+				timeout = TimestampTzPlusMilliseconds(last_reply_timestamp,
+													  wal_sender_timeout / 2);
+				if (GetCurrentTimestamp() >= timeout)
+				{
+					WalSndKeepalive(true);
+					waiting_for_ping_response = true;
+					wakeEvents |= WL_SOCKET_WRITEABLE;
+					/* Try to flush pending output to the client */
+					if (pq_flush_if_writable() != 0)
+						break;
+				}
+			}
+
+			sleeptime = 1 + (wal_sender_timeout / 10);
+		}
+
+		ImmediateInterruptOK = true;
+		CHECK_FOR_INTERRUPTS();
+		WaitLatchOrSocket(&MyWalSnd->latch, wakeEvents,
+						  MyProcPort->sock, sleeptime);
+		ImmediateInterruptOK = false;
+
+		/* die if timeout was reached */
+		WalSndCheckTimeOut();
+	}
+
+	/* reactivate latch so WalSndLoop knows to continue */
+	SetLatch(&MyWalSnd->latch);
+	return RecentFlushPtr;
+}
+
+/*
  * Execute an incoming replication command.
  */
 void
@@ -724,6 +1240,12 @@ exec_replication_command(const char *cmd_string)
 	MemoryContext cmd_context;
 	MemoryContext old_context;
 
+	/*
+	 * INIT_LOGICAL_REPLICATION exports a snapshot until the next command
+	 * arrives. Clean up the old stuff if there's anything.
+	 */
+	SnapBuildClearExportedSnapshot();
+
 	elog(DEBUG1, "received replication command: %s", cmd_string);
 
 	CHECK_FOR_INTERRUPTS();
@@ -769,7 +1291,7 @@ exec_replication_command(const char *cmd_string)
 				if (cmd->kind == REPLICATION_KIND_PHYSICAL)
 					StartReplication(cmd);
 				else
-					elog(ERROR, "cannot handle logical decoding yet");
+					StartLogicalReplication(cmd);
 				break;
 			}
 
@@ -887,7 +1409,7 @@ ProcessRepliesIfAny(void)
 	if (received)
 	{
 		last_reply_timestamp = GetCurrentTimestamp();
-		ping_sent = false;
+		waiting_for_ping_response = false;
 	}
 }
 
@@ -1020,7 +1542,7 @@ ProcessStandbyReplyMessage(void)
 	if (MyReplicationSlot && flushPtr != InvalidXLogRecPtr)
 	{
 		if (MyReplicationSlot->data.database != InvalidOid)
-			elog(ERROR, "cannot handle logical decoding yet");
+			LogicalConfirmReceivedLocation(flushPtr);
 		else
 			PhysicalConfirmReceivedLocation(flushPtr);
 	}
@@ -1146,12 +1668,32 @@ ProcessStandbyHSFeedbackMessage(void)
 		MyPgXact->xmin = feedbackXmin;
 }
 
-/* Main loop of walsender process that streams the WAL over Copy messages. */
 static void
-WalSndLoop(void)
+WalSndCheckTimeOut(void)
 {
-	bool		caughtup = false;
+	TimestampTz timeout;
+
+	timeout = TimestampTzPlusMilliseconds(last_reply_timestamp,
+										  wal_sender_timeout);
+
+	if (wal_sender_timeout > 0 && GetCurrentTimestamp() >= timeout)
+	{
+		/*
+		 * Since typically expiration of replication timeout means
+		 * communication problem, we don't send the error message to
+		 * the standby.
+		 */
+		ereport(COMMERROR,
+				(errmsg("terminating walsender process due to replication timeout")));
+
+		WalSndShutdown();
+	}
+}
 
+/* Main loop of walsender process that streams the WAL over Copy messages. */
+static void
+WalSndLoop(WalSndSendData send_data)
+{
 	/*
 	 * Allocate buffers that will be used for each outgoing and incoming
 	 * message.  We do this just once to reduce palloc overhead.
@@ -1162,7 +1704,7 @@ WalSndLoop(void)
 
 	/* Initialize the last reply timestamp */
 	last_reply_timestamp = GetCurrentTimestamp();
-	ping_sent = false;
+	waiting_for_ping_response = false;
 
 	/*
 	 * Loop until we reach the end of this timeline or the client requests to
@@ -1203,21 +1745,21 @@ WalSndLoop(void)
 
 		/*
 		 * If we don't have any pending data in the output buffer, try to send
-		 * some more.  If there is some, we don't bother to call XLogSend
+		 * some more.  If there is some, we don't bother to call send_data
 		 * again until we've flushed it ... but we'd better assume we are not
 		 * caught up.
 		 */
 		if (!pq_is_send_pending())
-			XLogSend(&caughtup);
+			send_data();
 		else
-			caughtup = false;
+			WalSndCaughtUp = false;
 
 		/* Try to flush pending output to the client */
 		if (pq_flush_if_writable() != 0)
-			goto send_failure;
+			WalSndShutdown();
 
 		/* If nothing remains to be sent right now ... */
-		if (caughtup && !pq_is_send_pending())
+		if (WalSndCaughtUp && !pq_is_send_pending())
 		{
 			/*
 			 * If we're in catchup state, move to streaming.  This is an
@@ -1243,41 +1785,28 @@ WalSndLoop(void)
 			 * the walsender is not sure which.
 			 */
 			if (walsender_ready_to_stop)
-			{
-				/* ... let's just be real sure we're caught up ... */
-				XLogSend(&caughtup);
-				if (caughtup && sentPtr == MyWalSnd->flush &&
-					!pq_is_send_pending())
-				{
-					/* Inform the standby that XLOG streaming is done */
-					EndCommand("COPY 0", DestRemote);
-					pq_flush();
-
-					proc_exit(0);
-				}
-			}
+				WalSndDone(send_data);
 		}
 
 		/*
 		 * We don't block if not caught up, unless there is unsent data
 		 * pending in which case we'd better block until the socket is
-		 * write-ready.  This test is only needed for the case where XLogSend
+		 * write-ready.  This test is only needed for the case where send_data
 		 * loaded a subset of the available data but then pq_flush_if_writable
 		 * flushed it all --- we should immediately try to send more.
 		 */
-		if ((caughtup && !streamingDoneSending) || pq_is_send_pending())
+		if ((WalSndCaughtUp && !streamingDoneSending) || pq_is_send_pending())
 		{
-			TimestampTz timeout = 0;
 			long		sleeptime = 10000;		/* 10 s */
 			int			wakeEvents;
 
 			wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_TIMEOUT |
 				WL_SOCKET_READABLE;
 
-			if (pq_is_send_pending())
-				wakeEvents |= WL_SOCKET_WRITEABLE;
-			else if (wal_sender_timeout > 0 && !ping_sent)
+			if (wal_sender_timeout > 0 && !waiting_for_ping_response)
 			{
+				TimestampTz timeout;
+
 				/*
 				 * If half of wal_sender_timeout has lapsed without receiving
 				 * any reply from standby, send a keep-alive message to
@@ -1288,20 +1817,22 @@ WalSndLoop(void)
 				if (GetCurrentTimestamp() >= timeout)
 				{
 					WalSndKeepalive(true);
-					ping_sent = true;
+					waiting_for_ping_response = true;
 					/* Try to flush pending output to the client */
 					if (pq_flush_if_writable() != 0)
-						goto send_failure;
+						WalSndShutdown();
 				}
 			}
 
-			/* Determine time until replication timeout */
+			if (pq_is_send_pending())
+				wakeEvents |= WL_SOCKET_WRITEABLE;
+
+			/*
+			 * Wake up regularly enough to check whether wal_sender_timeout
+			 * has passed.
+			 */
 			if (wal_sender_timeout > 0)
-			{
-				timeout = TimestampTzPlusMilliseconds(last_reply_timestamp,
-													  wal_sender_timeout);
 				sleeptime = 1 + (wal_sender_timeout / 10);
-			}
 
 			/* Sleep until something happens or we time out */
 			ImmediateInterruptOK = true;
@@ -1315,34 +1846,10 @@ WalSndLoop(void)
 			 * possibility that the client replied just as we reached the
 			 * timeout ... he's supposed to reply *before* that.
 			 */
-			if (wal_sender_timeout > 0 && GetCurrentTimestamp() >= timeout)
-			{
-				/*
-				 * Since typically expiration of replication timeout means
-				 * communication problem, we don't send the error message to
-				 * the standby.
-				 */
-				ereport(COMMERROR,
-						(errmsg("terminating walsender process due to replication timeout")));
-				goto send_failure;
-			}
+			WalSndCheckTimeOut();
 		}
 	}
 	return;
-
-send_failure:
-
-	/*
-	 * Get here on send failure.  Clean up and exit.
-	 *
-	 * Reset whereToSendOutput to prevent ereport from attempting to send any
-	 * more messages to the standby.
-	 */
-	if (whereToSendOutput == DestRemote)
-		whereToSendOutput = DestNone;
-
-	proc_exit(0);
-	abort();					/* keep the compiler quiet */
 }
 
 /* Initialize a per-walsender data structure for this walsender process */
@@ -1600,15 +2107,17 @@ retry:
 }
 
 /*
+ * Send out the WAL in its normal physical/stored form.
+ *
  * Read up to MAX_SEND_SIZE bytes of WAL that's been flushed to disk,
  * but not yet sent to the client, and buffer it in the libpq output
  * buffer.
  *
- * If there is no unsent WAL remaining, *caughtup is set to true, otherwise
- * *caughtup is set to false.
+ * If there is no unsent WAL remaining, WalSndCaughtUp is set to true,
+ * otherwise WalSndCaughtUp is set to false.
  */
 static void
-XLogSend(bool *caughtup)
+XLogSendPhysical(void)
 {
 	XLogRecPtr	SendRqstPtr;
 	XLogRecPtr	startptr;
@@ -1617,7 +2126,7 @@ XLogSend(bool *caughtup)
 
 	if (streamingDoneSending)
 	{
-		*caughtup = true;
+		WalSndCaughtUp = true;
 		return;
 	}
 
@@ -1734,7 +2243,7 @@ XLogSend(bool *caughtup)
 		pq_putmessage_noblock('c', NULL, 0);
 		streamingDoneSending = true;
 
-		*caughtup = true;
+		WalSndCaughtUp = true;
 
 		elog(DEBUG1, "walsender reached end of timeline at %X/%X (sent up to %X/%X)",
 			 (uint32) (sendTimeLineValidUpto >> 32), (uint32) sendTimeLineValidUpto,
@@ -1746,7 +2255,7 @@ XLogSend(bool *caughtup)
 	Assert(sentPtr <= SendRqstPtr);
 	if (SendRqstPtr <= sentPtr)
 	{
-		*caughtup = true;
+		WalSndCaughtUp = true;
 		return;
 	}
 
@@ -1770,15 +2279,15 @@ XLogSend(bool *caughtup)
 	{
 		endptr = SendRqstPtr;
 		if (sendTimeLineIsHistoric)
-			*caughtup = false;
+			WalSndCaughtUp = false;
 		else
-			*caughtup = true;
+			WalSndCaughtUp = true;
 	}
 	else
 	{
 		/* round down to page boundary. */
 		endptr -= (endptr % XLOG_BLCKSZ);
-		*caughtup = false;
+		WalSndCaughtUp = false;
 	}
 
 	nbytes = endptr - startptr;
@@ -1839,6 +2348,85 @@ XLogSend(bool *caughtup)
 }
 
 /*
+ * Send out the WAL after it being decoded into a logical format by the output
+ * plugin specified in INIT_LOGICAL_DECODING
+ */
+static void
+XLogSendLogical(void)
+{
+	XLogRecord *record;
+	char	   *errm;
+
+	/*
+	 * Don't know whether we've caught up yet. We'll set it to true in
+	 * WalSndWaitForWal, if we're actually waiting. We also set to true if
+	 * XLogReadRecord() had to stop reading but WalSndWaitForWal didn't wait -
+	 * i.e. when we're shutting down.
+	 */
+	WalSndCaughtUp = false;
+
+	record = XLogReadRecord(logical_decoding_ctx->reader, logical_startptr, &errm);
+	logical_startptr = InvalidXLogRecPtr;
+
+	/* xlog record was invalid */
+	if (errm != NULL)
+		elog(ERROR, "%s", errm);
+
+	if (record != NULL)
+	{
+		LogicalDecodingProcessRecord(logical_decoding_ctx, record);
+
+		sentPtr = logical_decoding_ctx->reader->EndRecPtr;
+	}
+	else
+	{
+		/*
+		 * If the record we just wanted read is at or beyond the flushed point,
+		 * then we're caught up.
+		 */
+		if (logical_decoding_ctx->reader->EndRecPtr >= GetFlushRecPtr())
+			WalSndCaughtUp = true;
+	}
+
+	/* Update shared memory status */
+	{
+		/* use volatile pointer to prevent code rearrangement */
+		volatile WalSnd *walsnd = MyWalSnd;
+
+		SpinLockAcquire(&walsnd->mutex);
+		walsnd->sentPtr = sentPtr;
+		SpinLockRelease(&walsnd->mutex);
+	}
+}
+
+/*
+ * The sender is caught up, so we can go away for shutdown processing
+ * to finish normally.  (This should only be called when the shutdown
+ * signal has been received from postmaster.)
+ *
+ * Note that if while doing this we determine that there's still more
+ * data to send, this function will return control to the caller.
+ */
+static void
+WalSndDone(WalSndSendData send_data)
+{
+	/* ... let's just be real sure we're caught up ... */
+	send_data();
+
+	if (WalSndCaughtUp && sentPtr == MyWalSnd->flush &&
+		!pq_is_send_pending())
+	{
+		/* Inform the standby that XLOG streaming is done */
+		EndCommand("COPY 0", DestRemote);
+		pq_flush();
+
+		proc_exit(0);
+	}
+	if (!waiting_for_ping_response)
+		WalSndKeepalive(true);
+}
+
+/*
  * Returns the latest point in WAL that has been safely flushed to disk, and
  * can be sent to the standby. This should only be called when in recovery,
  * ie. we're streaming to a cascaded standby.
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 3ecc4d3..2a57ed3 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -742,7 +742,12 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 			ereport(FATAL,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 					 errmsg("must be superuser or replication role to start walsender")));
+	}
 
+	if (am_walsender &&
+		(in_dbname == NULL || in_dbname[0] == '\0') &&
+		dboid == InvalidOid)
+	{
 		/* process any options passed in the startup packet */
 		if (MyProcPort != NULL)
 			process_startup_options(MyProcPort, am_superuser);
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index 919805f..f93b8c9 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -1639,11 +1639,11 @@ BaseBackup(void)
 				progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
 		disconnect_and_exit(1);
 	}
-	if (PQntuples(res) != 1 || PQnfields(res) != 3)
+	if (PQntuples(res) != 1 || PQnfields(res) < 3)
 	{
 		fprintf(stderr,
-				_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-				progname, PQntuples(res), PQnfields(res), 1, 3);
+				_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+				progname, PQntuples(res), PQnfields(res));
 		disconnect_and_exit(1);
 	}
 	sysidentifier = pg_strdup(PQgetvalue(res, 0, 0));
diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c
index 0f191ce..7ae20d1 100644
--- a/src/bin/pg_basebackup/pg_receivexlog.c
+++ b/src/bin/pg_basebackup/pg_receivexlog.c
@@ -275,11 +275,11 @@ StreamLog(void)
 				progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
 		disconnect_and_exit(1);
 	}
-	if (PQntuples(res) != 1 || PQnfields(res) != 3)
+	if (PQntuples(res) != 1 || PQnfields(res) < 3)
 	{
 		fprintf(stderr,
-				_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-				progname, PQntuples(res), PQnfields(res), 1, 3);
+				_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+				progname, PQntuples(res), PQnfields(res));
 		disconnect_and_exit(1);
 	}
 	servertli = atoi(PQgetvalue(res, 0, 1));
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index ef73b4b..64730d9 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -563,11 +563,11 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 			PQclear(res);
 			return false;
 		}
-		if (PQnfields(res) != 3 || PQntuples(res) != 1)
+		if (PQntuples(res) != 1 || PQnfields(res) < 3)
 		{
 			fprintf(stderr,
-					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-					progname, PQntuples(res), PQnfields(res), 1, 3);
+					_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+					progname, PQntuples(res), PQnfields(res));
 			PQclear(res);
 			return false;
 		}
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
index b67cf63..cff2be6 100644
--- a/src/include/replication/walsender.h
+++ b/src/include/replication/walsender.h
@@ -19,6 +19,7 @@
 /* global state */
 extern bool am_walsender;
 extern bool am_cascading_walsender;
+extern bool am_db_walsender;
 extern bool wake_wal_senders;
 
 /* user-settable parameters */
diff --git a/src/include/replication/walsender_private.h b/src/include/replication/walsender_private.h
index dff3354..c38d08d 100644
--- a/src/include/replication/walsender_private.h
+++ b/src/include/replication/walsender_private.h
@@ -108,4 +108,7 @@ extern void replication_scanner_finish(void);
 
 extern Node *replication_parse_result;
 
+/* logical wal sender data gathering functions */
+extern XLogRecPtr WalSndWaitForWal(XLogRecPtr loc);
+
 #endif   /* _WALSENDER_PRIVATE_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index f960454..69eeac5 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1909,6 +1909,7 @@ WalRcvData
 WalRcvState
 WalSnd
 WalSndCtlData
+WalSndSendData
 WalSndState
 WholeRowVarExprState
 WindowAgg
-- 
1.8.3.251.g1462b67

0003-Introduce-pg_receivexlog-equivalent-for-logical-deco.patchtext/x-patch; charset=us-asciiDownload
>From 268fc8b39cd4d79fa98a023cc6fa620fb69ffca9 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 00:15:39 +0100
Subject: [PATCH 3/4] Introduce pg_receivexlog equivalent for logical decoding.

Andres Freund
---
 doc/src/sgml/ref/allfiles.sgml         |   1 +
 doc/src/sgml/ref/pg_recvlogical.sgml   | 303 ++++++++++++
 doc/src/sgml/reference.sgml            |   1 +
 src/bin/pg_basebackup/.gitignore       |   2 +
 src/bin/pg_basebackup/Makefile         |  11 +-
 src/bin/pg_basebackup/pg_recvlogical.c | 875 +++++++++++++++++++++++++++++++++
 src/bin/pg_basebackup/receivelog.c     | 139 +-----
 src/bin/pg_basebackup/receivelog.h     |   2 +
 src/bin/pg_basebackup/streamutil.c     | 123 ++++-
 src/bin/pg_basebackup/streamutil.h     |  10 +
 10 files changed, 1342 insertions(+), 125 deletions(-)
 create mode 100644 doc/src/sgml/ref/pg_recvlogical.sgml
 create mode 100644 src/bin/pg_basebackup/pg_recvlogical.c

diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index ce7a5e3..1b0962c 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -183,6 +183,7 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY pgDumpall          SYSTEM "pg_dumpall.sgml">
 <!ENTITY pgIsready          SYSTEM "pg_isready.sgml">
 <!ENTITY pgReceivexlog      SYSTEM "pg_receivexlog.sgml">
+<!ENTITY pgRecvlogical      SYSTEM "pg_recvlogical.sgml">
 <!ENTITY pgResetxlog        SYSTEM "pg_resetxlog.sgml">
 <!ENTITY pgRestore          SYSTEM "pg_restore.sgml">
 <!ENTITY postgres           SYSTEM "postgres-ref.sgml">
diff --git a/doc/src/sgml/ref/pg_recvlogical.sgml b/doc/src/sgml/ref/pg_recvlogical.sgml
new file mode 100644
index 0000000..9fbd686
--- /dev/null
+++ b/doc/src/sgml/ref/pg_recvlogical.sgml
@@ -0,0 +1,303 @@
+<!--
+doc/src/sgml/ref/pg_recvlogical.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="app-pgrecvlogical">
+ <refmeta>
+  <refentrytitle><application>pg_recvlogical</application></refentrytitle>
+  <manvolnum>1</manvolnum>
+  <refmiscinfo>Application</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>pg_recvlogical</refname>
+  <refpurpose>Control changeset extraction
+  (see <xref linkend="changesetextraction">) replication streams over a
+  walsender connection.</refpurpose>
+ </refnamediv>
+
+ <indexterm zone="app-pgrecvlogical">
+  <primary>pg_recvlogical</primary>
+ </indexterm>
+
+ <refsynopsisdiv>
+  <cmdsynopsis>
+   <command>pg_recvlogical</command>
+   <arg rep="repeat" choice="opt"><option>option</option></arg>
+  </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="R1-APP-PGRECVLOGICAL-1">
+  <title>Description</title>
+  <para>
+   <command>pg_recvlogical</command> controls changeset extraction replication
+   slots and streams data from such replication slots.
+  </para>
+  <para>
+   It makes a replication-mode connection, so it is subject to the same
+   constraints as <link
+   linkend="app-pgreceivexlog"><application>pg_receivexlog</application></link>,
+   plus those for logical replication (see <xref
+   linkend="changesetextraction">).
+  </para>
+
+ </refsect1>
+
+ <refsect1>
+  <title>Options</title>
+
+   <para>
+    <application>pg_recvlogical</application> runs in one of three modes, which
+    control its primary action:
+
+    <variablelist>
+
+     <varlistentry>
+      <term><option>--create</option></term>
+      <listitem>
+       <para>
+       Create a new logical replication slot with the name specified in
+       <option>--slot</option>, using the output plugin
+       <option>--plugin</option>, then exit. The slot is created for the
+       database given in <option>--dbname</option>.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--start</option></term>
+      <listitem>
+       <para>
+       Begin streaming changes from the logical replication slot with the name
+       specified in <option>--slot</option>, continuing until terminated with a
+       signal. If the server side change stream ends with a server
+       shutdown / disconnect, retry in a loop unless <option>--no-loop</option>
+       is specified. The stream format is determined by the output plugin
+       specified when the slot was created.
+       </para>
+       <para>
+       You must connect to the same <option>--dbname</option> as the slot was
+       created with to stream changes from a logical replication slot.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--drop</option></term>
+      <listitem>
+       <para>
+       Drop the replication slot with the name specified in <option>--slot</option>, then exit.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
+
+   </para>
+
+   <para>
+    <application>pg_recvlogical</application> supports all the usual
+    <literal>libpq</literal>-based options. These are explained in detail in
+    the documentation for
+    <link linkend="APP-PSQL"><application>psql</application></link> and for
+    <link linkend="libpq"><literal>libpq</literal></link>.
+
+    <variablelist>
+
+      <varlistentry>
+       <term><option>-U <replaceable>user</replaceable></option></term>
+       <term><option>--username <replaceable>user</replaceable></option></term>
+       <listitem>
+        <para>
+         Username to connect as. Must have a suitable <literal>pg_hba.conf</literal>
+         entry allowing <literal>replication</literal> connections. Defaults to
+         current operating system user name.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-d <replaceable>database</replaceable></option></term>
+       <term><option>--dbname <replaceable>database</replaceable></option></term>
+       <listitem>
+        <para>
+         The database to connect to in <literal>replication</literal> mode; see
+         mode descriptions for details. May be
+         a <link linkend="LIBPQ-CONNSTRING">libpq connstring</link>
+         instead. Defaults to user name.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-h <replaceable>hostname-or-ip</replaceable></option></term>
+       <term><option>--host <replaceable>hostname-or-ip</replaceable></option></term>
+       <listitem>
+        <para>
+         Host or socket to connect
+         to. See <link linkend="APP-PSQL"><application>psql</application></link>
+         and <link linkend="libpq"><literal>libpq</literal></link>
+         documentation.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-p <replaceable>port</replaceable></option></term>
+       <term><option>--port <replaceable>port</replaceable></option></term>
+       <listitem>
+        <para>
+         Port number to connect to. See
+         <link linkend="R1-APP-PSQL-3"><application>psql</application></link>
+         for an explanation of default port choices when this is not
+         specified.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-w</option></term>
+       <term><option>--no-password</option></term>
+       <listitem>
+        <para>
+         Prevent prompting for a password. Will exit with an error code if a password is
+         required but not available.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>-W</option></term>
+       <term><option>--password</option></term>
+       <listitem>
+        <para>
+         Provide a password for this connection. Please use the pgservice file
+         (see <xref linkend="libpq-pgservice">) or an environment variable
+         instead of this option.
+        </para>
+       </listitem>
+      </varlistentry>
+
+     </variablelist>
+
+   </para>
+
+   <para>
+    The following command-line options control the location and format of the
+    output and other replication behaviour:
+
+    <variablelist>
+
+     <varlistentry>
+      <term><option>-f <replaceable>filename</replaceable></option></term>
+      <term><option>--file=<replaceable>filename</replaceable></option></term>
+      <listitem>
+       <para>
+        Receive decoded transaction data into this file. Use <literal>-</> for stdout.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
+     <varlistentry>
+      <term><option>-n</option></term>
+      <term><option>--no-loop</option></term>
+      <listitem>
+       <para>
+        When the connection to the server is lost, do not retry in a loop, just exit.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-P <replaceable>plugin</replaceable></option></term>
+      <term><option>--plugin=<replaceable>plugin</replaceable></option></term>
+      <listitem>
+       <para>
+        When creating a slot, use the specified changeset decoding output
+        plugin. See <xref linkend="changesetextraction">. This option has no
+        effect if the slot already exists.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-s <replaceable>interval_seconds</replaceable></option></term>
+      <term><option>--status-interval=<replaceable>interval_seconds</replaceable></option></term>
+      <listitem>
+       <para>
+        This option has the same effect as the option of the same name in <link
+        linkend="app-pgreceivexlog"><application>pg_receivexlog</application></link>.
+        See the description there.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-S <replaceable>slot_name</replaceable></option></term>
+      <term><option>--slot=<replaceable>slot_name</replaceable></option></term>
+      <listitem>
+       <para>
+        In <option>--start</option> mode, use the existing logical replication slot named
+        <replaceable>slot_name</replaceable>. In <option>--create</option> mode, create the
+        slot with this name. In <option>--drop</option> mode, delete the slot with this name.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-I <replaceable>lsn</replaceable></option></term>
+      <term><option>--startpos=<replaceable>lsn</replaceable></option></term>
+      <listitem>
+       <para>
+        In <option>--start</option> mode, start replication from the given LSN.
+        For details on the effect of this, see the documentation in <xref linkend="changesetextraction">
+        and <xref linkend="protocol-replication">. Ignored in other modes.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
+
+   </para>
+
+   <para>
+
+    The following additional options are available:
+
+    <variablelist>
+
+     <varlistentry>
+       <term><option>-v</></term>
+       <term><option>--verbose</></term>
+       <listitem>
+       <para>
+        Output verbose (detailed) error messages suitable for debugging and fault diagnosis.
+       </para>
+       </listitem>
+     </varlistentry>
+
+     <varlistentry>
+       <term><option>-V</></term>
+       <term><option>--version</></term>
+       <listitem>
+       <para>
+       Print the <application>pg_recvlogical</application> version and exit.
+       </para>
+       </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-?</></term>
+      <term><option>--help</></term>
+       <listitem>
+        <para>
+         Show help about <application>pg_recvlogical</application> command line
+         arguments, and exit.
+        </para>
+       </listitem>
+      </varlistentry>
+
+    </variablelist>
+   </para>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 87e8e9e..a6575f5 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -231,6 +231,7 @@
    &pgDumpall;
    &pgIsready;
    &pgReceivexlog;
+   &pgRecvlogical;
    &pgRestore;
    &psqlRef;
    &reindexdb;
diff --git a/src/bin/pg_basebackup/.gitignore b/src/bin/pg_basebackup/.gitignore
index 1334a1f..3bd45f4 100644
--- a/src/bin/pg_basebackup/.gitignore
+++ b/src/bin/pg_basebackup/.gitignore
@@ -1,2 +1,4 @@
 /pg_basebackup
 /pg_receivexlog
+/pg_receivellog
+/pg_recvlogical
diff --git a/src/bin/pg_basebackup/Makefile b/src/bin/pg_basebackup/Makefile
index 17c91af..346560e 100644
--- a/src/bin/pg_basebackup/Makefile
+++ b/src/bin/pg_basebackup/Makefile
@@ -20,7 +20,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
 
 OBJS=receivelog.o streamutil.o $(WIN32RES)
 
-all: pg_basebackup pg_receivexlog
+all: pg_basebackup pg_receivexlog pg_recvlogical
 
 pg_basebackup: pg_basebackup.o $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_basebackup.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
@@ -28,9 +28,13 @@ pg_basebackup: pg_basebackup.o $(OBJS) | submake-libpq submake-libpgport
 pg_receivexlog: pg_receivexlog.o $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_receivexlog.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
+pg_recvlogical: pg_recvlogical.o $(OBJS) | submake-libpq submake-libpgport
+	$(CC) $(CFLAGS) pg_recvlogical.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+
 install: all installdirs
 	$(INSTALL_PROGRAM) pg_basebackup$(X) '$(DESTDIR)$(bindir)/pg_basebackup$(X)'
 	$(INSTALL_PROGRAM) pg_receivexlog$(X) '$(DESTDIR)$(bindir)/pg_receivexlog$(X)'
+	$(INSTALL_PROGRAM) pg_recvlogical$(X) '$(DESTDIR)$(bindir)/pg_recvlogical$(X)'
 
 installdirs:
 	$(MKDIR_P) '$(DESTDIR)$(bindir)'
@@ -38,6 +42,9 @@ installdirs:
 uninstall:
 	rm -f '$(DESTDIR)$(bindir)/pg_basebackup$(X)'
 	rm -f '$(DESTDIR)$(bindir)/pg_receivexlog$(X)'
+	rm -f '$(DESTDIR)$(bindir)/pg_recvlogical$(X)'
 
 clean distclean maintainer-clean:
-	rm -f pg_basebackup$(X) pg_receivexlog$(X) $(OBJS) pg_basebackup.o pg_receivexlog.o
+	rm -f pg_basebackup$(X) pg_receivexlog$(X) pg_recvlogical$(X) \
+		pg_basebackup.o pg_receivexlog.o pg_recvlogical.o \
+		$(OBJS)
diff --git a/src/bin/pg_basebackup/pg_recvlogical.c b/src/bin/pg_basebackup/pg_recvlogical.c
new file mode 100644
index 0000000..8cef9fc
--- /dev/null
+++ b/src/bin/pg_basebackup/pg_recvlogical.c
@@ -0,0 +1,875 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_recvlogical.c - receive streaming logical log data and write it
+ *					  to a local file.
+ *
+ * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		  src/bin/pg_basebackup/pg_recvlogical.c
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include "streamutil.h"
+
+#include "getopt_long.h"
+
+#include "libpq-fe.h"
+#include "libpq/pqsignal.h"
+
+#include "access/xlog_internal.h"
+#include "common/fe_memutils.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Time to sleep between reconnection attempts */
+#define RECONNECT_SLEEP_TIME 5
+
+/* Global Options */
+static char    *outfile = NULL;
+static int		verbose = 0;
+static int		noloop = 0;
+static int		standby_message_timeout = 10 * 1000;		/* 10 sec = default */
+static XLogRecPtr startpos = InvalidXLogRecPtr;
+static bool		do_create_slot = false;
+static bool		do_start_slot = false;
+static bool		do_drop_slot = false;
+
+/* filled pairwise with option, value. value may be NULL */
+static char	  **options;
+static size_t	noptions = 0;
+static const char *plugin = "test_decoding";
+
+/* Global State */
+static int		outfd = -1;
+static volatile bool time_to_abort = false;
+
+static void usage(void);
+static void StreamLog();
+static void disconnect_and_exit(int code);
+
+static void
+usage(void)
+{
+	printf(_("%s receives PostgreSQL logical change stream.\n\n"),
+		   progname);
+	printf(_("Usage:\n"));
+	printf(_("  %s [OPTION]...\n"), progname);
+	printf(_("\nOptions:\n"));
+	printf(_("  -f, --file=FILE        receive log into this file. - for stdout\n"));
+	printf(_("  -n, --no-loop          do not loop on connection lost\n"));
+	printf(_("  -v, --verbose          output verbose messages\n"));
+	printf(_("  -V, --version          output version information, then exit\n"));
+	printf(_("  -?, --help             show this help, then exit\n"));
+	printf(_("\nConnection options:\n"));
+	printf(_("  -d, --dbname=DBNAME    database to connect to\n"));
+	printf(_("  -h, --host=HOSTNAME    database server host or socket directory\n"));
+	printf(_("  -p, --port=PORT        database server port number\n"));
+	printf(_("  -U, --username=NAME    connect as specified database user\n"));
+	printf(_("  -w, --no-password      never prompt for password\n"));
+	printf(_("  -W, --password         force password prompt (should happen automatically)\n"));
+	printf(_("\nReplication options:\n"));
+	printf(_("  -o, --option=NAME[=VALUE]\n"
+			 "                         Specify option NAME with optional value VAL, to be passed\n"
+			 "                         to the output plugin\n"));
+	printf(_("  -P, --plugin=PLUGIN    use output plugin PLUGIN (defaults to test_decoding)\n"));
+	printf(_("  -s, --status-interval=INTERVAL\n"
+			 "                         time between status packets sent to server (in seconds)\n"));
+	printf(_("  -S, --slot=SLOT        use existing replication slot SLOT instead of starting a new one\n"));
+	printf(_("  -I, --startpos=PTR     Where in an existing slot should the streaming start"));
+	printf(_("\nAction to be performed:\n"));
+	printf(_("      --create           create a new replication slot (for the slotname see --slot)\n"));
+	printf(_("      --start            start streaming in a replication slot (for the slotname see --slot)\n"));
+	printf(_("      --drop             drop the replication slot (for the slotname see --slot)\n"));
+	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
+}
+
+/*
+ * Send a Standby Status Update message to server.
+ */
+static bool
+sendFeedback(PGconn *conn, XLogRecPtr blockpos, int64 now, bool force, bool replyRequested)
+{
+	char		replybuf[1 + 8 + 8 + 8 + 8 + 1];
+	int			len = 0;
+
+	/*
+	 * we normally don't want to send superflous feedbacks, but if
+	 * it's because of a timeout we need to, otherwise
+	 * replication_timeout will kill us.
+	 */
+	if (blockpos == startpos && !force)
+		return true;
+
+	if (verbose)
+		fprintf(stderr,
+				_("%s: confirming flush up to %X/%X (slot %s)\n"),
+				progname, (uint32) (blockpos >> 32), (uint32) blockpos,
+				replication_slot);
+
+	replybuf[len] = 'r';
+	len += 1;
+	fe_sendint64(blockpos, &replybuf[len]);		/* write */
+	len += 8;
+	fe_sendint64(blockpos, &replybuf[len]);		/* flush */
+	len += 8;
+	fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
+	len += 8;
+	fe_sendint64(now, &replybuf[len]);		/* sendTime */
+	len += 8;
+	replybuf[len] = replyRequested ? 1 : 0;		/* replyRequested */
+	len += 1;
+
+	startpos = blockpos;
+
+	if (PQputCopyData(conn, replybuf, len) <= 0 || PQflush(conn))
+	{
+		fprintf(stderr, _("%s: could not send feedback packet: %s"),
+				progname, PQerrorMessage(conn));
+		return false;
+	}
+
+	return true;
+}
+
+static void
+disconnect_and_exit(int code)
+{
+	if (conn != NULL)
+		PQfinish(conn);
+
+	exit(code);
+}
+
+
+/*
+ * Start the log streaming
+ */
+static void
+StreamLog(void)
+{
+	PGresult   *res;
+	char		query[512];
+	char	   *copybuf = NULL;
+	int64		last_status = -1;
+	XLogRecPtr	logoff = InvalidXLogRecPtr;
+	int			written;
+	int			i;
+
+	/*
+	 * Connect in replication mode to the server
+	 */
+	if (!conn)
+		conn = GetConnection();
+	if (!conn)
+		/* Error message already written in GetConnection() */
+		return;
+
+	/*
+	 * Start the replication
+	 */
+	if (verbose)
+		fprintf(stderr,
+				_("%s: starting log streaming at %X/%X (slot %s)\n"),
+				progname, (uint32) (startpos >> 32), (uint32) startpos,
+				replication_slot);
+
+	/* Initiate the replication stream at specified location */
+	written = snprintf(query, sizeof(query), "START_REPLICATION SLOT \"%s\" LOGICAL %X/%X",
+			 replication_slot, (uint32) (startpos >> 32), (uint32) startpos);
+
+	/*
+	 * add options to string, if present
+	 * Oh, if we just had stringinfo in src/common...
+	 */
+	if (noptions)
+		written += snprintf(query + written, sizeof(query) - written, " (");
+
+	for (i = 0; i < noptions; i++)
+	{
+		/* separator */
+		if (i > 0)
+			written += snprintf(query + written, sizeof(query) - written, ", ");
+
+		/* write option name */
+		written += snprintf(query + written, sizeof(query) - written, "\"%s\"",
+							options[(i * 2)]);
+
+		if (written >= sizeof(query) - 1)
+		{
+			fprintf(stderr, _("%s: option string too long\n"), progname);
+			exit(1); /* no point in retrying, fatal error */
+		}
+
+		/* write option name if specified */
+		if (options[(i * 2) + 1] != NULL)
+		{
+			written += snprintf(query + written, sizeof(query) - written, " '%s'",
+								options[(i * 2) + 1]);
+
+			if (written >= sizeof(query) - 1)
+			{
+				fprintf(stderr, _("%s: option string too long\n"), progname);
+				exit(1); /* no point in retrying, fatal error */
+			}
+		}
+	}
+
+	if (noptions)
+	{
+		written += snprintf(query + written, sizeof(query) - written, ")");
+		if (written >= sizeof(query) - 1)
+		{
+			fprintf(stderr, _("%s: option string too long\n"), progname);
+			exit(1); /* no point in retrying, fatal error */
+		}
+	}
+
+	res = PQexec(conn, query);
+	if (PQresultStatus(res) != PGRES_COPY_BOTH)
+	{
+		fprintf(stderr, _("%s: could not send replication command \"%s\": %s\n"),
+				progname, query, PQresultErrorMessage(res));
+		PQclear(res);
+		goto error;
+	}
+	PQclear(res);
+
+	if (verbose)
+		fprintf(stderr,
+				_("%s: initiated streaming\n"),
+				progname);
+
+	while (!time_to_abort)
+	{
+		int			r;
+		int			bytes_left;
+		int			bytes_written;
+		int64		now;
+		int			hdr_len;
+
+		if (copybuf != NULL)
+		{
+			PQfreemem(copybuf);
+			copybuf = NULL;
+		}
+
+		/*
+		 * Potentially send a status message to the master
+		 */
+		now = feGetCurrentTimestamp();
+		if (standby_message_timeout > 0 &&
+			feTimestampDifferenceExceeds(last_status, now,
+										 standby_message_timeout))
+		{
+			/* Time to send feedback! */
+			if (!sendFeedback(conn, logoff, now, true, false))
+				goto error;
+
+			last_status = now;
+		}
+
+		r = PQgetCopyData(conn, &copybuf, 1);
+		if (r == 0)
+		{
+			/*
+			 * In async mode, and no data available. We block on reading but
+			 * not more than the specified timeout, so that we can send a
+			 * response back to the client.
+			 */
+			fd_set		input_mask;
+			struct timeval timeout;
+			struct timeval *timeoutptr;
+
+			FD_ZERO(&input_mask);
+			FD_SET(PQsocket(conn), &input_mask);
+			if (standby_message_timeout)
+			{
+				int64		targettime;
+				long		secs;
+				int			usecs;
+
+				targettime = last_status + (standby_message_timeout - 1) *
+					((int64) 1000);
+				feTimestampDifference(now,
+									  targettime,
+									  &secs,
+									  &usecs);
+				if (secs <= 0)
+					timeout.tv_sec = 1; /* Always sleep at least 1 sec */
+				else
+					timeout.tv_sec = secs;
+				timeout.tv_usec = usecs;
+				timeoutptr = &timeout;
+			}
+			else
+				timeoutptr = NULL;
+
+			r = select(PQsocket(conn) + 1, &input_mask, NULL, NULL, timeoutptr);
+			if (r == 0 || (r < 0 && errno == EINTR))
+			{
+				/*
+				 * Got a timeout or signal. Continue the loop and either
+				 * deliver a status packet to the server or just go back into
+				 * blocking.
+				 */
+				continue;
+			}
+			else if (r < 0)
+			{
+				fprintf(stderr, _("%s: select() failed: %s\n"),
+						progname, strerror(errno));
+				goto error;
+			}
+			/* Else there is actually data on the socket */
+			if (PQconsumeInput(conn) == 0)
+			{
+				fprintf(stderr,
+						_("%s: could not receive data from WAL stream: %s"),
+						progname, PQerrorMessage(conn));
+				goto error;
+			}
+			continue;
+		}
+		if (r == -1)
+			/* End of copy stream */
+			break;
+		if (r == -2)
+		{
+			fprintf(stderr, _("%s: could not read COPY data: %s"),
+					progname, PQerrorMessage(conn));
+			goto error;
+		}
+
+		/* Check the message type. */
+		if (copybuf[0] == 'k')
+		{
+			int			pos;
+			bool		replyRequested;
+			XLogRecPtr	walEnd;
+
+			/*
+			 * Parse the keepalive message, enclosed in the CopyData message.
+			 * We just check if the server requested a reply, and ignore the
+			 * rest.
+			 */
+			pos = 1;			/* skip msgtype 'k' */
+			walEnd = fe_recvint64(&copybuf[pos]);
+			logoff = Max(walEnd, logoff);
+
+			pos += 8;			/* read walEnd */
+
+			pos += 8;			/* skip sendTime */
+
+			if (r < pos + 1)
+			{
+				fprintf(stderr, _("%s: streaming header too small: %d\n"),
+						progname, r);
+				goto error;
+			}
+			replyRequested = copybuf[pos];
+
+			/* If the server requested an immediate reply, send one. */
+			if (replyRequested)
+			{
+				now = feGetCurrentTimestamp();
+				if (!sendFeedback(conn, logoff, now, true, false))
+					goto error;
+				last_status = now;
+			}
+			continue;
+		}
+		else if (copybuf[0] != 'w')
+		{
+			fprintf(stderr, _("%s: unrecognized streaming header: \"%c\"\n"),
+					progname, copybuf[0]);
+			goto error;
+		}
+
+
+		/*
+		 * Read the header of the XLogData message, enclosed in the CopyData
+		 * message. We only need the WAL location field (dataStart), the rest
+		 * of the header is ignored.
+		 */
+		hdr_len = 1;			/* msgtype 'w' */
+		hdr_len += 8;			/* dataStart */
+		hdr_len += 8;			/* walEnd */
+		hdr_len += 8;			/* sendTime */
+		if (r < hdr_len + 1)
+		{
+			fprintf(stderr, _("%s: streaming header too small: %d\n"),
+					progname, r);
+			goto error;
+		}
+
+		/* Extract WAL location for this block */
+		{
+			XLogRecPtr	temp = fe_recvint64(&copybuf[1]);
+
+			logoff = Max(temp, logoff);
+		}
+
+		if (outfd == -1 && strcmp(outfile, "-") == 0)
+		{
+			outfd = fileno(stdout);
+		}
+		else if (outfd == -1)
+		{
+			outfd = open(outfile, O_CREAT | O_APPEND | O_WRONLY | PG_BINARY,
+						 S_IRUSR | S_IWUSR);
+			if (outfd == -1)
+			{
+				fprintf(stderr,
+						_("%s: could not open log file \"%s\": %s\n"),
+						progname, outfile, strerror(errno));
+				goto error;
+			}
+		}
+
+		bytes_left = r - hdr_len;
+		bytes_written = 0;
+
+
+		while (bytes_left)
+		{
+			int			ret;
+
+			ret = write(outfd,
+						copybuf + hdr_len + bytes_written,
+						bytes_left);
+
+			if (ret < 0)
+			{
+				fprintf(stderr,
+				  _("%s: could not write %u bytes to log file \"%s\": %s\n"),
+						progname, bytes_left, outfile,
+						strerror(errno));
+				goto error;
+			}
+
+			/* Write was successful, advance our position */
+			bytes_written += ret;
+			bytes_left -= ret;
+		}
+
+		if (write(outfd, "\n", 1) != 1)
+		{
+			fprintf(stderr,
+				  _("%s: could not write %u bytes to log file \"%s\": %s\n"),
+					progname, 1, outfile,
+					strerror(errno));
+			goto error;
+		}
+	}
+
+	res = PQgetResult(conn);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
+	{
+		fprintf(stderr,
+				_("%s: unexpected termination of replication stream: %s"),
+				progname, PQresultErrorMessage(res));
+		goto error;
+	}
+	PQclear(res);
+
+	if (copybuf != NULL)
+		PQfreemem(copybuf);
+
+	if (outfd != -1 && strcmp(outfile, "-") != 0 && close(outfd) != 0)
+		fprintf(stderr, _("%s: could not close file \"%s\": %s\n"),
+				progname, outfile, strerror(errno));
+	outfd = -1;
+error:
+	PQfinish(conn);
+	conn = NULL;
+}
+
+/*
+ * When sigint is called, just tell the system to exit at the next possible
+ * moment.
+ */
+#ifndef WIN32
+
+static void
+sigint_handler(int signum)
+{
+	time_to_abort = true;
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+	PGresult   *res;
+	static struct option long_options[] = {
+/* general options */
+		{"file", required_argument, NULL, 'f'},
+		{"no-loop", no_argument, NULL, 'n'},
+		{"verbose", no_argument, NULL, 'v'},
+		{"version", no_argument, NULL, 'V'},
+		{"help", no_argument, NULL, '?'},
+/* connnection options */
+		{"dbname", required_argument, NULL, 'd'},
+		{"host", required_argument, NULL, 'h'},
+		{"port", required_argument, NULL, 'p'},
+		{"username", required_argument, NULL, 'U'},
+		{"no-password", no_argument, NULL, 'w'},
+		{"password", no_argument, NULL, 'W'},
+/* replication options */
+		{"option", required_argument, NULL, 'o'},
+		{"plugin", required_argument, NULL, 'P'},
+		{"status-interval", required_argument, NULL, 's'},
+		{"slot", required_argument, NULL, 'S'},
+		{"startpos", required_argument, NULL, 'I'},
+/* action */
+		{"create", no_argument, NULL, 1},
+		{"start", no_argument, NULL, 2},
+		{"drop", no_argument, NULL, 3},
+		{NULL, 0, NULL, 0}
+	};
+	int			c;
+	int			option_index;
+	uint32		hi,
+				lo;
+
+	progname = get_progname(argv[0]);
+	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_recvlogical"));
+
+	if (argc > 1)
+	{
+		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
+		{
+			usage();
+			exit(0);
+		}
+		else if (strcmp(argv[1], "-V") == 0 ||
+				 strcmp(argv[1], "--version") == 0)
+		{
+			puts("pg_recvlogical (PostgreSQL) " PG_VERSION);
+			exit(0);
+		}
+	}
+
+	while ((c = getopt_long(argc, argv, "f:nvd:h:o:p:U:wWP:s:S:",
+							long_options, &option_index)) != -1)
+	{
+		switch (c)
+		{
+/* general options */
+			case 'f':
+				outfile = pg_strdup(optarg);
+				break;
+			case 'n':
+				noloop = 1;
+				break;
+			case 'v':
+				verbose++;
+				break;
+/* connnection options */
+			case 'd':
+				dbname = pg_strdup(optarg);
+				break;
+			case 'h':
+				dbhost = pg_strdup(optarg);
+				break;
+			case 'p':
+				if (atoi(optarg) <= 0)
+				{
+					fprintf(stderr, _("%s: invalid port number \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				dbport = pg_strdup(optarg);
+				break;
+			case 'U':
+				dbuser = pg_strdup(optarg);
+				break;
+			case 'w':
+				dbgetpassword = -1;
+				break;
+			case 'W':
+				dbgetpassword = 1;
+				break;
+/* replication options */
+			case 'o':
+				{
+					char *data = pg_strdup(optarg);
+					char *val = strchr(data, '=');
+
+					if (val != NULL)
+					{
+						/* remove =; separate data from val */
+						*val = '\0';
+						val++;
+					}
+
+					noptions += 1;
+					options = pg_realloc(options, sizeof(char*) * noptions * 2);
+
+					options[(noptions - 1) * 2] = data;
+					options[(noptions - 1) * 2 + 1] = val;
+				}
+
+				break;
+			case 'P':
+				plugin = pg_strdup(optarg);
+				break;
+			case 's':
+				standby_message_timeout = atoi(optarg) * 1000;
+				if (standby_message_timeout < 0)
+				{
+					fprintf(stderr, _("%s: invalid status interval \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				break;
+			case 'S':
+				replication_slot = pg_strdup(optarg);
+				break;
+			case 'I':
+				if (sscanf(optarg, "%X/%X", &hi, &lo) != 2)
+				{
+					fprintf(stderr,
+							_("%s: could not parse start position \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				startpos = ((uint64) hi) << 32 | lo;
+				break;
+/* action */
+			case 1:
+				do_create_slot = true;
+				break;
+			case 2:
+				do_start_slot = true;
+				break;
+			case 3:
+				do_drop_slot = true;
+				break;
+
+			default:
+
+				/*
+				 * getopt_long already emitted a complaint
+				 */
+				fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+						progname);
+				exit(1);
+		}
+	}
+
+	/*
+	 * Any non-option arguments?
+	 */
+	if (optind < argc)
+	{
+		fprintf(stderr,
+				_("%s: too many command-line arguments (first is \"%s\")\n"),
+				progname, argv[optind]);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	/*
+	 * Required arguments
+	 */
+	if (replication_slot == NULL)
+	{
+		fprintf(stderr, _("%s: no slot specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (do_start_slot && outfile == NULL)
+	{
+		fprintf(stderr, _("%s: no target file specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (!do_drop_slot && dbname == NULL)
+	{
+		fprintf(stderr, _("%s: no database specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (!do_drop_slot && !do_create_slot && !do_start_slot)
+	{
+		fprintf(stderr, _("%s: at least one action needs to be specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (do_drop_slot && (do_create_slot || do_start_slot))
+	{
+		fprintf(stderr, _("%s: --stop cannot be combined with --init or --start\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (startpos && (do_create_slot || do_drop_slot))
+	{
+		fprintf(stderr, _("%s: --startpos cannot be combined with --init or --stop\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+#ifndef WIN32
+	pqsignal(SIGINT, sigint_handler);
+#endif
+
+	/*
+	 * don't really need this but it actually helps to get more precise error
+	 * messages about authentication, required GUCs and such without starting
+	 * to loop around connection attempts lateron.
+	 */
+	{
+		conn = GetConnection();
+		if (!conn)
+			/* Error message already written in GetConnection() */
+			exit(1);
+
+		/*
+		 * Run IDENTIFY_SYSTEM so we can get the timeline and current xlog
+		 * position.
+		 */
+		res = PQexec(conn, "IDENTIFY_SYSTEM");
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 1 || PQnfields(res) != 4)
+		{
+			fprintf(stderr,
+					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 4);
+			disconnect_and_exit(1);
+		}
+		PQclear(res);
+	}
+
+
+	/*
+	 * stop a replication slot
+	 */
+	if (do_drop_slot)
+	{
+		char		query[256];
+
+		if (verbose)
+			fprintf(stderr,
+					_("%s: freeing replication slot \"%s\"\n"),
+					progname, replication_slot);
+
+		snprintf(query, sizeof(query), "DROP_REPLICATION_SLOT \"%s\"",
+				 replication_slot);
+		res = PQexec(conn, query);
+		if (PQresultStatus(res) != PGRES_COMMAND_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, query, PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 0 || PQnfields(res) != 0)
+		{
+			fprintf(stderr,
+					_("%s: could not stop logical rep: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 0, 0);
+			disconnect_and_exit(1);
+		}
+
+		PQclear(res);
+		disconnect_and_exit(0);
+	}
+
+	/*
+	 * init a replication slot
+	 */
+	if (do_create_slot)
+	{
+		char		query[256];
+
+		if (verbose)
+			fprintf(stderr,
+					_("%s: initializing replication slot \"%s\"\n"),
+					progname, replication_slot);
+
+		snprintf(query, sizeof(query), "CREATE_REPLICATION_SLOT \"%s\" LOGICAL \"%s\"",
+				 replication_slot, plugin);
+
+		res = PQexec(conn, query);
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, query, PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 1 || PQnfields(res) != 4)
+		{
+			fprintf(stderr,
+					_("%s: could not init logical rep: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 4);
+			disconnect_and_exit(1);
+		}
+
+		if (sscanf(PQgetvalue(res, 0, 1), "%X/%X", &hi, &lo) != 2)
+		{
+			fprintf(stderr,
+					_("%s: could not parse log location \"%s\"\n"),
+					progname, PQgetvalue(res, 0, 1));
+			disconnect_and_exit(1);
+		}
+		startpos = ((uint64) hi) << 32 | lo;
+
+		replication_slot = strdup(PQgetvalue(res, 0, 0));
+		PQclear(res);
+	}
+
+
+	if (!do_start_slot)
+		disconnect_and_exit(0);
+
+	while (true)
+	{
+		StreamLog();
+		if (time_to_abort)
+		{
+			/*
+			 * We've been Ctrl-C'ed. That's not an error, so exit without an
+			 * errorcode.
+			 */
+			disconnect_and_exit(0);
+		}
+		else if (noloop)
+		{
+			fprintf(stderr, _("%s: disconnected.\n"), progname);
+			exit(1);
+		}
+		else
+		{
+			fprintf(stderr,
+			/* translator: check source for value for %d */
+					_("%s: disconnected. Waiting %d seconds to try again.\n"),
+					progname, RECONNECT_SLEEP_TIME);
+			pg_usleep(RECONNECT_SLEEP_TIME * 1000000);
+		}
+	}
+}
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index 64730d9..26343c9 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -11,21 +11,18 @@
  *		  src/bin/pg_basebackup/receivelog.c
  *-------------------------------------------------------------------------
  */
+
 #include "postgres_fe.h"
 
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-/* for ntohl/htonl */
-#include <netinet/in.h>
-#include <arpa/inet.h>
+/* local includes */
+#include "receivelog.h"
+#include "streamutil.h"
 
 #include "libpq-fe.h"
 #include "access/xlog_internal.h"
 
-#include "receivelog.h"
-#include "streamutil.h"
+#include <sys/stat.h>
+#include <unistd.h>
 
 
 /* fd and filename for currently open WAL file */
@@ -195,63 +192,6 @@ close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos)
 
 
 /*
- * Local version of GetCurrentTimestamp(), since we are not linked with
- * backend code. The protocol always uses integer timestamps, regardless of
- * server setting.
- */
-static int64
-localGetCurrentTimestamp(void)
-{
-	int64		result;
-	struct timeval tp;
-
-	gettimeofday(&tp, NULL);
-
-	result = (int64) tp.tv_sec -
-		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-
-	result = (result * USECS_PER_SEC) + tp.tv_usec;
-
-	return result;
-}
-
-/*
- * Local version of TimestampDifference(), since we are not linked with
- * backend code.
- */
-static void
-localTimestampDifference(int64 start_time, int64 stop_time,
-						 long *secs, int *microsecs)
-{
-	int64		diff = stop_time - start_time;
-
-	if (diff <= 0)
-	{
-		*secs = 0;
-		*microsecs = 0;
-	}
-	else
-	{
-		*secs = (long) (diff / USECS_PER_SEC);
-		*microsecs = (int) (diff % USECS_PER_SEC);
-	}
-}
-
-/*
- * Local version of TimestampDifferenceExceeds(), since we are not
- * linked with backend code.
- */
-static bool
-localTimestampDifferenceExceeds(int64 start_time,
-								int64 stop_time,
-								int msec)
-{
-	int64		diff = stop_time - start_time;
-
-	return (diff >= msec * INT64CONST(1000));
-}
-
-/*
  * Check if a timeline history file exists.
  */
 static bool
@@ -371,47 +311,6 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
 }
 
 /*
- * Converts an int64 to network byte order.
- */
-static void
-sendint64(int64 i, char *buf)
-{
-	uint32		n32;
-
-	/* High order half first, since we're doing MSB-first */
-	n32 = (uint32) (i >> 32);
-	n32 = htonl(n32);
-	memcpy(&buf[0], &n32, 4);
-
-	/* Now the low order half */
-	n32 = (uint32) i;
-	n32 = htonl(n32);
-	memcpy(&buf[4], &n32, 4);
-}
-
-/*
- * Converts an int64 from network byte order to native format.
- */
-static int64
-recvint64(char *buf)
-{
-	int64		result;
-	uint32		h32;
-	uint32		l32;
-
-	memcpy(&h32, buf, 4);
-	memcpy(&l32, buf + 4, 4);
-	h32 = ntohl(h32);
-	l32 = ntohl(l32);
-
-	result = h32;
-	result <<= 32;
-	result |= l32;
-
-	return result;
-}
-
-/*
  * Send a Standby Status Update message to server.
  */
 static bool
@@ -422,16 +321,16 @@ sendFeedback(PGconn *conn, XLogRecPtr blockpos, int64 now, bool replyRequested)
 
 	replybuf[len] = 'r';
 	len += 1;
-	sendint64(blockpos, &replybuf[len]);		/* write */
+	fe_sendint64(blockpos, &replybuf[len]);		/* write */
 	len += 8;
 	if (reportFlushPosition)
-		sendint64(lastFlushPosition, &replybuf[len]);		/* flush */
+		fe_sendint64(lastFlushPosition, &replybuf[len]);		/* flush */
 	else
-		sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
+		fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
 	len += 8;
-	sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
+	fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
 	len += 8;
-	sendint64(now, &replybuf[len]);		/* sendTime */
+	fe_sendint64(now, &replybuf[len]);		/* sendTime */
 	len += 8;
 	replybuf[len] = replyRequested ? 1 : 0;		/* replyRequested */
 	len += 1;
@@ -864,9 +763,9 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 		/*
 		 * Potentially send a status message to the master
 		 */
-		now = localGetCurrentTimestamp();
+		now = feGetCurrentTimestamp();
 		if (still_sending && standby_message_timeout > 0 &&
-			localTimestampDifferenceExceeds(last_status, now,
+			feTimestampDifferenceExceeds(last_status, now,
 											standby_message_timeout))
 		{
 			/* Time to send feedback! */
@@ -895,10 +794,10 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 				int			usecs;
 
 				targettime = last_status + (standby_message_timeout - 1) * ((int64) 1000);
-				localTimestampDifference(now,
-										 targettime,
-										 &secs,
-										 &usecs);
+				feTimestampDifference(now,
+									  targettime,
+									  &secs,
+									  &usecs);
 				if (secs <= 0)
 					timeout.tv_sec = 1; /* Always sleep at least 1 sec */
 				else
@@ -1002,7 +901,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 			/* If the server requested an immediate reply, send one. */
 			if (replyRequested && still_sending)
 			{
-				now = localGetCurrentTimestamp();
+				now = feGetCurrentTimestamp();
 				if (!sendFeedback(conn, blockpos, now, false))
 					goto error;
 				last_status = now;
@@ -1032,7 +931,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 						progname, r);
 				goto error;
 			}
-			blockpos = recvint64(&copybuf[1]);
+			blockpos = fe_recvint64(&copybuf[1]);
 
 			/* Extract WAL location for this block */
 			xlogoff = blockpos % XLOG_SEG_SIZE;
diff --git a/src/bin/pg_basebackup/receivelog.h b/src/bin/pg_basebackup/receivelog.h
index 7c983cd..f4789a5 100644
--- a/src/bin/pg_basebackup/receivelog.h
+++ b/src/bin/pg_basebackup/receivelog.h
@@ -1,3 +1,5 @@
+#include "libpq-fe.h"
+
 #include "access/xlogdefs.h"
 
 /*
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 041076f..441abbf 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -11,11 +11,28 @@
  *-------------------------------------------------------------------------
  */
 
-#include "postgres_fe.h"
+/*
+ * We have to use postgres.h not postgres_fe.h here, because there's
+ * backend-only stuff in the datetime include files we need.  But we need a
+ * frontend-ish environment otherwise. Hence this ugly hack.
+ */
+#define FRONTEND 1
+#include "postgres.h"
+
 #include "streamutil.h"
 
+#include "common/fe_memutils.h"
+#include "utils/datetime.h"
+
 #include <stdio.h>
 #include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* for ntohl/htonl */
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 const char *progname;
 char	   *connection_string = NULL;
@@ -23,6 +40,7 @@ char	   *dbhost = NULL;
 char	   *dbuser = NULL;
 char	   *dbport = NULL;
 char	   *replication_slot = NULL;
+char	   *dbname = NULL;
 int			dbgetpassword = 0;	/* 0=auto, -1=never, 1=always */
 static char *dbpassword = NULL;
 PGconn	   *conn = NULL;
@@ -87,10 +105,10 @@ GetConnection(void)
 	}
 
 	keywords[i] = "dbname";
-	values[i] = "replication";
+	values[i] = dbname == NULL ? "replication" : dbname;
 	i++;
 	keywords[i] = "replication";
-	values[i] = "true";
+	values[i] = dbname == NULL ? "true" : "database";
 	i++;
 	keywords[i] = "fallback_application_name";
 	values[i] = progname;
@@ -212,3 +230,102 @@ GetConnection(void)
 
 	return tmpconn;
 }
+
+
+/*
+ * Frontend version of GetCurrentTimestamp(), since we are not linked with
+ * backend code. The protocol always uses integer timestamps, regardless of
+ * server setting.
+ */
+int64
+feGetCurrentTimestamp(void)
+{
+	int64		result;
+	struct timeval tp;
+
+	gettimeofday(&tp, NULL);
+
+	result = (int64) tp.tv_sec -
+		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
+
+	result = (result * USECS_PER_SEC) + tp.tv_usec;
+
+	return result;
+}
+
+/*
+ * Frontend version of TimestampDifference(), since we are not linked with
+ * backend code.
+ */
+void
+feTimestampDifference(int64 start_time, int64 stop_time,
+						 long *secs, int *microsecs)
+{
+	int64		diff = stop_time - start_time;
+
+	if (diff <= 0)
+	{
+		*secs = 0;
+		*microsecs = 0;
+	}
+	else
+	{
+		*secs = (long) (diff / USECS_PER_SEC);
+		*microsecs = (int) (diff % USECS_PER_SEC);
+	}
+}
+
+/*
+ * Frontend version of TimestampDifferenceExceeds(), since we are not
+ * linked with backend code.
+ */
+bool
+feTimestampDifferenceExceeds(int64 start_time,
+								int64 stop_time,
+								int msec)
+{
+	int64		diff = stop_time - start_time;
+
+	return (diff >= msec * INT64CONST(1000));
+}
+
+/*
+ * Converts an int64 to network byte order.
+ */
+void
+fe_sendint64(int64 i, char *buf)
+{
+	uint32		n32;
+
+	/* High order half first, since we're doing MSB-first */
+	n32 = (uint32) (i >> 32);
+	n32 = htonl(n32);
+	memcpy(&buf[0], &n32, 4);
+
+	/* Now the low order half */
+	n32 = (uint32) i;
+	n32 = htonl(n32);
+	memcpy(&buf[4], &n32, 4);
+}
+
+/*
+ * Converts an int64 from network byte order to native format.
+ */
+int64
+fe_recvint64(char *buf)
+{
+	int64		result;
+	uint32		h32;
+	uint32		l32;
+
+	memcpy(&h32, buf, 4);
+	memcpy(&l32, buf + 4, 4);
+	h32 = ntohl(h32);
+	l32 = ntohl(l32);
+
+	result = h32;
+	result <<= 32;
+	result |= l32;
+
+	return result;
+}
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index 7c7d022..d0f3799 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -5,6 +5,7 @@ extern char *connection_string;
 extern char *dbhost;
 extern char *dbuser;
 extern char *dbport;
+extern char *dbname;
 extern int	dbgetpassword;
 extern char *replication_slot;
 
@@ -12,3 +13,12 @@ extern char *replication_slot;
 extern PGconn *conn;
 
 extern PGconn *GetConnection(void);
+
+extern int64 feGetCurrentTimestamp(void);
+extern void feTimestampDifference(int64 start_time, int64 stop_time,
+									 long *secs, int *microsecs);
+
+extern bool feTimestampDifferenceExceeds(int64 start_time, int64 stop_time,
+											int msec);
+extern void fe_sendint64(int64 i, char *buf);
+extern int64 fe_recvint64(char *buf);
-- 
1.8.3.251.g1462b67

0004-Documentation-for-logical-decoding.patchtext/x-patch; charset=us-asciiDownload
>From 5c4a2c308f084632be8bb5d6293fca92c10de3f8 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 00:15:39 +0100
Subject: [PATCH 4/4] Documentation for logical decoding.

Craig Ringer, Andres Freund, Christian Kruse
---
 doc/src/sgml/catalogs.sgml            |  27 +-
 doc/src/sgml/changesetextraction.sgml | 586 ++++++++++++++++++++++++++++++++++
 doc/src/sgml/filelist.sgml            |   2 +
 doc/src/sgml/func.sgml                | 102 +++++-
 doc/src/sgml/postgres.sgml            |   1 +
 doc/src/sgml/protocol.sgml            |  95 +++++-
 doc/src/sgml/ref/alter_table.sgml     |   2 +-
 doc/src/sgml/ref/create_table.sgml    |  15 +-
 8 files changed, 808 insertions(+), 22 deletions(-)
 create mode 100644 doc/src/sgml/changesetextraction.sgml

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 908f947..727a201 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -5177,7 +5177,7 @@
 
   <para>
    For more on replication slots,
-   see <xref linkend="streaming-replication-slots">.
+   see <xref linkend="streaming-replication-slots"> and <xref linkend="changesetextraction">.
   </para>
 
   <table>
@@ -5210,6 +5210,13 @@
      </row>
 
      <row>
+      <entry><structfield>plugin</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>The basename of the shared object containing the output plugin this logical slot is using, or null for physical slots.</entry>
+     </row>
+
+     <row>
       <entry><structfield>datoid</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry>
@@ -5243,6 +5250,24 @@
      </row>
 
      <row>
+      <entry><structfield>xmin</structfield></entry>
+      <entry><type>xid</type></entry>
+      <entry></entry>
+      <entry>The oldest transaction that this slot needs the database to
+      retain.  <literal>VACUUM</literal> cannot remove catalog tuples deleted
+      by any later transaction.
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>catalog_xmin</structfield></entry>
+      <entry><type>xid</type></entry>
+      <entry></entry>
+      <entry>The <literal>xmin</literal>, or oldest transaction ID, that this
+      slot forces to be retained in the system catalogs. </entry>
+     </row>
+
+     <row>
       <entry><structfield>restart_lsn</structfield></entry>
       <entry><type>pg_lsn</type></entry>
       <entry></entry>
diff --git a/doc/src/sgml/changesetextraction.sgml b/doc/src/sgml/changesetextraction.sgml
new file mode 100644
index 0000000..60b915c
--- /dev/null
+++ b/doc/src/sgml/changesetextraction.sgml
@@ -0,0 +1,586 @@
+<!-- doc/src/sgml/changesetextraction.sgml -->
+ <chapter id="changesetextraction">
+  <title>Changeset Extraction</title>
+  <indexterm zone="changesetextraction">
+   <primary>Changeset Extraction</primary>
+  </indexterm>
+  <para>
+   PostgreSQL provides infrastructure to stream the modifications performed
+   via SQL to external consumers which can be used to implement replication
+   solutions, perform auditing and similar tasks.
+  </para>
+
+  <para>
+   <indexterm><primary>Changeset Extraction Slot</primary></indexterm>
+   A changeset extraction slot ("logical replication slot") is a persistent
+   server-side record of the replay progress of a stream of changes. A stream of
+   changes is read from the slot to a receiving client program.
+  </para>
+  <para>
+   The format in which those changes are streamed is determined by the output
+   plugin used. While an example plugin is provided, additional plugins can be
+   written to extend the choice of available formats without modifying any
+   core code.
+   Every output plugin has access to each individual new row produced
+   by <command>INSERT</command>, and the new row version created
+   by <command>UPDATE</command>. Which data is available for rows affected
+   by <command>DELETE</command> and for the old row version in
+   an <command>UPDATE</command> depends on the relation's
+   configured <link linkend="SQL-CREATETABLE-REPLICA-IDENTITY"><literal>REPLICA
+   IDENTITY</literal></link>.
+  </para>
+  <para>
+   Changes can be consumed either using one streaming replication protocol
+   (see <xref linkend="protocol-replication"> and
+   <xref linkend="changesetextraction-walsender">), or by calling functions
+   via SQL (see <xref linkend="changesetextraction-sql">). It is also possible
+   to write additional methods of consuming the output of a replication slot
+   without modifying core code
+   (see <xref linkend="changesetextraction-writer">).
+  </para>
+
+  <sect1 id="changesetextraction-example">
+   <title>Changeset Extraction Example</title>
+   <para>
+    The following example shows usage of the SQL interface.
+   </para>
+   <para>
+    Before you can use changeset extraction you must edit
+    <literal>postgresql.conf</literal> and ensure the following parameters are
+    set to at least:
+    <programlisting>
+wal_level = logical
+max_replication_slots = 1
+max_wal_senders = 1
+    </programlisting>
+    and restart PostgreSQL. Then connect to the target database (in the example
+    below, <literal>postgres</literal>) as a superuser.
+   </para>
+   <programlisting>
+postgres=# -- max_replication_slots must be nonzero and wal_level must be logical
+postgres=# SHOW max_replication_slots;
+ max_replication_slots
+-----------------------
+ 1
+(1 row)
+
+postgres=# SHOW wal_level;
+ wal_level
+-----------
+ logical
+(1 row)
+
+postgres=# SELECT * FROM pg_replication_slots;
+ slot_name | plugin | slot_type | datoid | database | active | xmin | catalog_xmin | restart_lsn
+-----------+--------+-----------+--------+----------+--------+------+--------------+-------------
+(0 rows)
+
+postgres=# -- Create a slot named 'regression_slot' using the output plugin 'test_decoding'
+postgres=# SELECT * FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
+    slotname     | xlog_position
+-----------------+---------------
+ regression_slot | 0/16B1970
+(1 row)
+
+postgres=# SELECT * FROM pg_replication_slots;
+    slot_name    |    plugin     | slot_type | datoid | database | active |  xmin  | catalog_xmin | restart_lsn
+-----------------+---------------+-----------+--------+----------+--------+--------+--------------+-------------
+ regression_slot | test_decoding | logical   |  12052 | postgres | f      |        |          684 | 0/16A4408
+(1 row)
+
+postgres=# -- There are no changes to see yet
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location | xid | data
+----------+-----+------
+(0 rows)
+
+postgres=# CREATE TABLE data(id serial primary key, data text);
+CREATE TABLE
+
+postgres=# -- DDL isn't replicated, so all you'll see is the transaction
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location  | xid |    data
+-----------+-----+------------
+ 0/16D5D48 | 688 | BEGIN 688
+ 0/16E0380 | 688 | COMMIT 688
+(2 rows)
+
+postgres=# -- Once changes are read, they're consumed and not emitted
+postgres=# -- in a subsequent call:
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location | xid | data
+----------+-----+------
+(0 rows)
+
+postgres=# BEGIN;
+postgres=# INSERT INTO data(data) VALUES('1');
+postgres=# INSERT INTO data(data) VALUES('2');
+postgres=# COMMIT;
+
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E0478 | 689 | BEGIN 689
+ 0/16E0478 | 689 | table public.data: INSERT: id[int4]:1 data[text]:'1'
+ 0/16E0580 | 689 | table public.data: INSERT: id[int4]:2 data[text]:'2'
+ 0/16E0650 | 689 | COMMIT 689
+(4 rows)
+
+postgres=# INSERT INTO data(data) VALUES('3');
+
+postgres=# -- You can also peek ahead in the change stream without consuming changes
+postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E09C0 | 690 | BEGIN 690
+ 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3'
+ 0/16E0B90 | 690 | COMMIT 690
+(3 rows)
+
+postgres=# -- You can also peek ahead in the change stream without consuming changes
+postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E09C0 | 690 | BEGIN 690
+ 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3'
+ 0/16E0B90 | 690 | COMMIT 690
+(3 rows)
+
+postgres=# -- options can be passed to output plugin, to influence the formatting
+postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL, 'include-timestamp', 'on');
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E09C0 | 690 | BEGIN 690
+ 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3'
+ 0/16E0B90 | 690 | COMMIT 690 (at 2014-02-27 16:41:51.863092+01)
+(3 rows)
+
+postgres=# -- Remember to destroy a slot you no longer need to stop it consuming
+postgres=# -- server resources:
+postgres=# SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot
+-----------------------
+
+(1 row)
+    </programlisting>
+   <para>
+    The following example shows usage of the walsender interface using
+    the <link linkend="app-pgrecvlogical"><command>pg_recvlogical</command></link>
+    shell command. It requires the replication configurations to be allowed
+    (see <xref linkend="streaming-replication-authentication">)
+    and <varname>max_wal_senders</varname> to be set sufficiently high for
+    another connection.
+   </para>
+   <programlisting>
+# pg_recvlogical -d testdb --slot test --create
+# pg_recvlogical -d testdb --slot test --start -f -
+CTRL-Z
+# psql -c "INSERT INTO data(data) VALUES('4');"
+# fg
+BEGIN 693
+table public.data: INSERT: id[int4]:4 data[text]:'4'
+COMMIT 693
+CTRL-C
+# pg_recvlogical -d testdb --slot test --drop
+   </programlisting>
+  </sect1>
+  <sect1 id="changesetextraction-explanation">
+   <title>Changeset Extraction Concepts</title>
+   <sect2>
+    <indexterm>
+     <primary>Changeset Extraction</primary>
+    </indexterm>
+    <indexterm>
+     <primary>Changeset Generation</primary>
+    </indexterm>
+    <title>Changeset Extraction</title>
+    <para>
+     Changeset Extraction is the the process of extracting all persistent
+     changes to a database's tables into a coherent, easy to understand format
+     which can be interpreted without detailed knowledge of the database's
+     internal state.
+    </para>
+    <para>
+     In <productname>PostgreSQL</productname> changeset extraction is
+     implemented by decoding the <link linkend="wal">WAL's</link> contents,
+     which describe changes on a storage level, into an application-specific
+     form such as a stream of tuples or SQL statements.
+    </para>
+   </sect2>
+
+   <sect2>
+    <indexterm>
+     <primary>Logical Replication Slot</primary>
+    </indexterm>
+    <indexterm>
+     <primary>Replication Slot</primary>
+    </indexterm>
+    <title>Replication Slots</title>
+    <para>
+     In the context of changeset extraction a replication slot represents a
+     stream of changes which can be replayed to a client in the order they
+     were made on the origin server. Each slot streams a sequence of changes
+     from a single database, sending each change exactly once (unless peeking
+     forward in the stream).
+    </para>
+    <note>
+     <para>PostgreSQL also has streaming replication slots
+     (see <xref linkend="streaming-replication">), but they are used somewhat
+     differently there.
+     </para>
+    </note>
+    <para>
+     Replication slots have an identifier which is unique across all databases
+     in a <productname>PostgreSQL</productname> cluster. Slots persist
+     independently of the connection using them and are crash-safe.  They can
+     be allocated in primary servers and hot-standby servers (streaming
+     replicas or archive-replaying hot standbys), so it's possible to
+     replicate changes over physical replication then read a logical change
+     stream from a physical replica server.
+    </para>
+    <para>
+     Multiple independent slots may exist for a single database. Each slot has
+     its own state, allowing different consumers to receive changes from
+     different points in the database change stream. For most applications a
+     separate slot is required for each changeset consumer.
+    </para>
+    <para>
+     A changeset extraction slot knows nothing about the state of the
+     receiver(s).  It's even possible to have multiple different receivers use
+     the same slot at different times; they'll just get the changes following
+     on from when the last receiver stopped consuming them. Only one receiver
+     may consume changes from a slot at any given time.
+    </para>
+    <sect3 id="changesetextraction-abandoned-slots">
+     <title>Unused/abandoned slots</title>
+     <para>
+      Changeset extraction slots persist across crashes and know nothing about
+      the state of their consumer(s). They will prevent removal of required
+      resources even when there is no connection using them. This consumes
+      storage because neither required WAL nor required rows from the system
+      catalogs can be removed by VACUUM as long as they are required by a
+      replication slot, so if a slot is no longer required it should be
+      dropped.
+     </para>
+     <para>
+      Slots may be created manually, or using a client like a replication
+      tool. Keep this in mind when you retire a client that uses a changeset
+      extraction slot, like a logical replica - you may need to give it a
+      specific command to remove its changeset extraction slot, or drop the
+      slot yourself, even if you did not initially create the slot by hand.
+     </para>
+    </sect3>
+   </sect2>
+   <sect2>
+    <title>Exported Snapshots</title>
+    <para>
+     When a new replication slot is created over the walsender interface a
+     snapshot is exported
+     (see <xref linkend="functions-snapshot-synchronization">) which will show
+     exactly the state of the database after which all changes will be
+     included in the changestream. This can be used to create a new replica by
+     using <link linkend="sql-set-transaction"><literal>SET TRANSACTION
+     SNAPSHOT</literal></link> to read the state of the database at the moment
+     the slot was created. This transaction can then be used to dump the
+     database's state at that point in time which afterwards can be updated
+     using the slot's contents without loosing any changes.
+    </para>
+   </sect2>
+  </sect1>
+  <sect1 id="changesetextraction-walsender">
+   <title>Streaming Replication Protocol Interface</title>
+   <para>
+    The <literal>CREATE_REPLICATION_SLOT SLOT slotname LOGICAL
+    options</literal>, <literal>DROP_REPLICATION_SLOT SLOT slotname</literal>
+    and <literal>START_REPLICATION SLOT slotname LOGICAL options</literal>
+    commands can be used to create, drop and stream changes from a replication
+    slot respectively. These commands are only available over a replication
+    connection; the won't work from the SQL
+    level. See <xref linkend="protocol-replication">.
+   </para>
+   <para>
+    The <command>pg_recvlogical</command> command
+    (see <xref linkend="app-pgrecvlogical">) can be used to control changeset
+    extraction over a walsender connection.
+   </para>
+  </sect1>
+  <sect1 id="changesetextraction-sql">
+   <title>Changeset Extraction <acronym>SQL</acronym> Interface</title>
+   <para>
+     See <xref linkend="functions-replication"> for detailed
+     documentation on the SQL-level API for interacting with changeset
+     extraction.
+   </para>
+   <para>
+    Synchronous replication (see <xref linkend="synchronous-replication">) is
+    only supported on replication slots used over the walsender interface. The
+    function interface and additional, non-core, interfaces, do not support
+    synchronous replication.
+   </para>
+  </sect1>
+  <sect1 id="changesetextraction-catalogs">
+   <title>System catalogs related to changeset extraction</title>
+   <para>
+    The <xref linkend="catalog-pg-replication-slots"> view and the
+    <literal>pg_stat_replication</literal> view
+    in <xref linkend="monitoring-stats-views-table"> provide information about
+    the current state of replication slots and walsender connections
+    respectively. These views apply to both physical and logical replication.
+   </para>
+  </sect1>
+  <sect1 id="changesetextraction-output-plugin">
+   <title>Changeset Extraction Output Plugins</title>
+   <para>
+    An example output plugin can be found in the
+    <link linkend="test-decoding">
+     <filename>contrib/test_decoding</filename>
+    </link>
+    subdirectory of the PostgreSQL source tree.
+   </para>
+   <sect2 id="changesetextraction-output-init">
+    <title>Initialization Function</title>
+    <indexterm zone="changesetextraction">
+     <primary>_PG_output_plugin_init</primary>
+    </indexterm>
+    <para>
+     An output plugin is loaded by dynamically loading a shared library with
+     the output plugin's name as the library basename. The normal library
+     search path is used to locate the library. To provide the required output
+     plugin callbacks and to indicate that the library is actually an output
+     plugin it needs to provide a function named
+     <function>_PG_output_plugin_init</function>. This function is passed a
+     struct that needs to be filled with the callback function pointers for
+     individual actions.
+     <programlisting>
+typedef struct OutputPluginCallbacks
+{
+    LogicalDecodeStartupCB startup_cb;
+    LogicalDecodeBeginCB begin_cb;
+    LogicalDecodeChangeCB change_cb;
+    LogicalDecodeCommitCB commit_cb;
+    LogicalDecodeShutdownCB shutdown_cb;
+} OutputPluginCallbacks;
+typedef void (*LogicalOutputPluginInit)(struct OutputPluginCallbacks *cb);
+     </programlisting>
+     The <function>begin_cb</function>, <function>change_cb</function>
+     and <function>commit_cb</function> callbacks are required,
+     while <function>startup_cb</function>
+     and <function>shutdown_cb</function> are optional.
+    </para>
+   </sect2>
+
+   <sect2 id="changesetextraction-capabilities">
+    <title>Capabilities</title>
+    <para>
+     To decode, format and output changes, output plugins can use most of the
+     backend's normal infrastructure, including calling output functions. Read
+     only access to relations is permitted as long as only relations are
+     accessed that either have been created by initdb in
+     the <literal>pg_catalog</literal> schema, or have are marked as user
+     provided catalog tables using
+     <programlisting>
+ALTER TABLE user_catalog_table SET (user_catalog_table = true);
+CREATE TABLE another_catalog_table(data text) WITH (user_catalog_table = true);
+     </programlisting>
+     Any actions leading to XID assignment are prohibited. That, among others,
+     includes writing to tables, performing DDL changes and
+     calling <literal>txid_current()</literal>.
+    </para>
+   </sect2>
+
+   <sect2 id="changesetextraction-output-plugin-callbacks">
+    <title>Output Plugin Callbacks</title>
+    <para>
+     An output plugin gets notified about changes that are happening via
+     various callbacks it needs to provide.
+    </para>
+    <para>
+     Concurrent transactions are decoded in commit order and only changes
+     belonging to a specific transaction are decoded inbetween
+     the <literal>begin</literal> and <literal>commit</literal>
+     callbacks. Transaction that were rolled back explicitly or implicitly
+     will never be
+     decoded. Successfull <link linkend="SQL-SAVEPOINT">SAVEPOINTs</link> are
+     folded into the transaction containing them in the order they were
+     exectuded within that transaction.
+    </para>
+    <note>
+     <para>
+      Only transactions that have already safely been flushed to disk will be
+      decoded. That can lead to a COMMIT not immediately being decoded in a
+      directly following <literal>pg_logical_slot_get_changes()</literal>
+      when <varname>synchronous_commit</varname> is set
+      to <literal>off</literal>.
+     </para>
+    </note>
+    <sect3 id="changesetextraction-output-plugin-startup">
+     <title>Startup Callback</title>
+     <para>
+      The optional <function>startup_cb</function> callback is called whenever
+      an replication slot is created or asked to stream changes, independent
+      of the number of changes that are ready to be output.
+      <programlisting>
+typedef void (*LogicalDecodeStartupCB) (
+    struct LogicalDecodingContext *ctx,
+    OutputPluginOptions *options,
+    bool is_init
+);
+      </programlisting>
+      The <literal>is_init</literal> paramter will be true when the
+      replication slot is being created and false
+      otherwise. <parameter>options</parameter> points to a struct of options
+      that output plugins can set:
+      <programlisting>
+typedef struct OutputPluginOptions
+{
+    OutputPluginOutputType output_type;
+} OutputPluginOptions;
+      </programlisting>
+      <literal>output_type</literal> has to either be set to
+      <literal>OUTPUT_PLUGIN_TEXTUAL_OUTPUT</literal>
+      or <literal>OUTPUT_PLUGIN_BINARY_OUTPUT</literal>.
+     </para>
+     <para>
+      The startup callback should validate the options present in
+      <literal>ctx-&gt;output_plugin_options</literal>. If the output plugin
+      needs to have a state, it can
+      use <literal>ctx-&gt;output_plugin_private</literal> to store it.
+     </para>
+    </sect3>
+    <sect3 id="changesetextraction-output-plugin-shutdown">
+     <title>Shutdown Callback</title>
+     <para>
+      The optional <function>shutdown_cb</function> callback is called
+      whenever a formerly active replication slot is not used anymore and can
+      be used to deallocate resources private to the output plugin. The slot
+      isn't necessarily being dropped, streaming is just being stopped.
+      <programlisting>
+typedef void (*LogicalDecodeShutdownCB) (
+    struct LogicalDecodingContext *ctx
+);
+      </programlisting>
+     </para>
+   </sect3>
+    <sect3 id="changesetextraction-output-plugin-begin">
+     <title>Transaction Begin Callback</title>
+     <para>
+      The required <function>begin_cb</function> callback is called whenever a
+      transaction start has been decoded, but only if we know that the
+      transaction has committed. Aborted transactions and their contents are
+      never decoded.
+      <programlisting>
+typedef void (*LogicalDecodeBeginCB) (
+    struct LogicalDecodingContext *,
+    ReorderBufferTXN *txn
+);
+      </programlisting>
+      The <parameter>txn</parameter> parameter contains meta information about
+      the transaction, like the timestamp at which it committed and its XID.
+     </para>
+   </sect3>
+    <sect3 id="changesetextraction-output-plugin-commit">
+     <title>Transaction End Callback</title>
+     <para>
+      The required <function>commit_cb</function> callback is called whenever
+      a transaction commit has been
+      decoded. The <function>change_cb</function> callbacks for all modified
+      rows will have been called before this, if there have been any modified
+      rows.
+      <programlisting>
+typedef void (*LogicalDecodeCommitCB) (
+    struct LogicalDecodingContext *,
+    ReorderBufferTXN *txn
+);
+      </programlisting>
+     </para>
+    </sect3>
+    <sect3 id="changesetextraction-output-plugin-change">
+     <title>Callback called for each individual change in a
+     transaction</title>
+     <para>
+      The required <function>change_cb</function> callback is called for every
+      individual row modification inside a transaction, may it be
+      an <command>INSERT</command>, <command>UPDATE</command>
+      or <command>DELETE</command>. Even if the original command modified
+      several rows at once the callback will be called indvidually for each
+      row.
+      <programlisting>
+typedef void (*LogicalDecodeChangeCB) (
+    struct LogicalDecodingContext *ctx,
+    ReorderBufferTXN *txn,
+    Relation relation,
+    ReorderBufferChange *change
+);
+      </programlisting>
+      The <parameter>ctx</parameter> and <parameter>txn</parameter> parameters
+      have the same contents as for the <function>begin_cb</function>
+      and <function>commit_cb</function> callbacks, but additionally the
+      relation descriptor <parameter>relation</parameter> for the relation the
+      row belongs to and a struct
+      <parameter>change</parameter> describing the row modification are passed
+      in.
+     </para>
+     <note>
+      <para>
+       Only changes in user defined tables that are not unlogged
+       (see <xref linkend="SQL-CREATETABLE-UNLOGGED">) and not temporary
+       (see <xref linkend="SQL-CREATETABLE-TEMPORARY">) can be extracted using
+       changeset extraction.
+      </para>
+     </note>
+    </sect3>
+   </sect2>
+   <sect2 id="changesetextraction-output-plugin-output">
+    <title>Functions for producing output from an output plugin</title>
+    <para>
+     To actually produce output, output plugins can write data to
+     the <literal>StringInfo</literal> output buffer
+     in <literal>ctx-&gt;out</literal> when inside
+     the <function>begin_cb</function>, <function>commit_cb</function>
+     or <function>change_cb</function> callbacks. Before writing to the output
+     buffer <function>OutputPluginPrepareWrite(ctx, last_write)</function> has
+     to be called, and after finishing writing to the
+     buffer <function>OutputPluginWrite(ctx, last_write)</function> has to be
+     called to perform the write. The <parameter>last_write</parameter>
+     indicates whether a particular write was the callback's last write.
+    </para>
+    <para>
+     The following example shows how to output data to the consumer of an
+     output plugin:
+     <programlisting>
+OutputPluginPrepareWrite(ctx, true);
+appendStringInfo(ctx->out, "BEGIN %u", txn->xid);
+OutputPluginWrite(ctx, true);
+     </programlisting>
+    </para>
+   </sect2>
+  </sect1>
+  <sect1 id="changesetextraction-writer">
+   <title>Changeset Extraction Output Writers</title>
+   <para>
+    It is possible to add more output methods in addition to the SQL
+    and replication protocol variants for consuming changeset extraction
+    data. For details look at the implementation of the SQL interface
+    functions
+    in <filename>src/backend/replication/logical/logicalfuncs.c</filename>.
+    Essentially three functions need to be provided, one to read WAL, one to
+    prepare writing output and one to write the output
+    (see <xref linkend="changesetextraction-output-plugin-output">).
+   </para>
+  </sect1>
+  <sect1 id="changesetextraction-synchronous">
+   <title>Synchronous replication support for Changeset Extraction</title>
+   <para>
+    The Changeset Extraction support in <productname>PostgreSQL</productname>
+    may be used to to
+    build <link linkend="synchronous-replication">synchronous
+    replication</link> solutions with the same user interface as synchronous
+    replication for <link linkend="streaming-replication">streaming
+    replication</link> if the walsender interface
+    (see <xref linkend="changesetextraction-walsender">) is used to stream out
+    data. Clients have to send <literal>Standby status update (F)</literal>
+    (see <xref linkend="protocol-replication">), just like streaming
+    replication clients do.
+   </para>
+  </sect1>
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 0e863ee..0208ca2 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -91,6 +91,7 @@
 <!ENTITY nls        SYSTEM "nls.sgml">
 <!ENTITY plhandler  SYSTEM "plhandler.sgml">
 <!ENTITY fdwhandler SYSTEM "fdwhandler.sgml">
+<!ENTITY changesetextraction SYSTEM "changesetextraction.sgml">
 <!ENTITY protocol   SYSTEM "protocol.sgml">
 <!ENTITY sources    SYSTEM "sources.sgml">
 <!ENTITY storage    SYSTEM "storage.sgml">
@@ -146,6 +147,7 @@
 <!ENTITY test-decoding   SYSTEM "test-decoding.sgml">
 <!ENTITY test-parser     SYSTEM "test-parser.sgml">
 <!ENTITY test-shm-mq     SYSTEM "test-shm-mq.sgml">
+<!ENTITY test-decoding   SYSTEM "test-decoding.sgml">
 <!ENTITY tsearch2        SYSTEM "tsearch2.sgml">
 <!ENTITY unaccent      SYSTEM "unaccent.sgml">
 <!ENTITY uuid-ossp       SYSTEM "uuid-ossp.sgml">
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index a1f627c..8a18602 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -16363,8 +16363,9 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
 
    <para>
     PostgreSQL exposes a number of functions for controlling and interacting
-    with replication features. See <xref linkend="streaming-replication">
-    and <xref linkend="streaming-replication-slots">.
+    with replication features. See <xref linkend="streaming-replication">,
+    <xref linkend="streaming-replication-slots">
+    and <xref linkend="changesetextraction">.
    </para>
 
    <para>
@@ -16423,9 +16424,106 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
         command <literal>DROP_REPLICATION_SLOT</>.
        </entry>
       </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_create_logical_replication_slot</primary>
+        </indexterm>
+        <literal><function>pg_create_logical_replication_slot(<parameter>slotname</parameter> <type>name</type>, <parameter>plugin</parameter> <type>name</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>slotname</parameter> <type>name</type>, <parameter>xlog_position</parameter> <type>pg_lsn</type>)
+       </entry>
+       <entry>
+        Creates a new logical (decoding) replication slot named
+        <parameter>slotname</parameter> using the output plugin
+        <parameter>plugin</parameter>. Output plugins are listed amongst the
+        extensions in <literal>pg_catalog.pg_available_extensions</literal>,
+        but there is no specific listing of only output plugins. Same as
+        walsender protocol command <literal>CREATE REPLICATION SLOT ... LOGICAL</literal>.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_get_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_get_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>pg_lsn</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Returns changes in the slot <parameter>slotname</parameter>, starting
+        from the point at which since changes have been consumed last. Changes
+        are extracted upto the current end of the WAL, or if nonnull only if
+        their transactions have committed
+        before <parameter>upto_lsn</parameter>, or if nonnull
+        until <parameter>upto_nchanges</parameter> rows have been
+        collected. Note that the <parameter>upto_nchanges</parameter> limit is
+        only enforced everytime a transaction commits. Changes will not be
+        consumed.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_peek_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_peek_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>text</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Behaves just like
+        the <function>pg_logical_slot_get_changes()</function> function,
+        except that changes are not consumed, i.e. will be returned again on
+        future calls.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_get_binary_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_get_binary_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>pg_lsn</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>bytea</type>)
+       </entry>
+       <entry>
+        Behaves just like
+        the <function>pg_logical_slot_get_changes()</function> function,
+        except that changes are returned as <type>bytea</type>.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_peek_binary_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_peek_binary_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>pg_lsn</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>bytea</type>)
+       </entry>
+       <entry>
+        Behaves just like
+        the <function>pg_logical_slot_get_changes()</function> function,
+        except that changes are returned as <type>bytea</type> and that
+        changes are not consumed, i.e. will be returned again on future calls.
+       </entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
+
   </sect2>
 
   <sect2 id="functions-admin-dbobject">
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index b47bf52..dd1709f 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -219,6 +219,7 @@
 
   &spi;
   &bgworker;
+  &changesetextraction;
 
  </part>
 
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 510bf9a..3621772 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1301,24 +1301,48 @@
 <title>Streaming Replication Protocol</title>
 
 <para>
-To initiate streaming replication, the frontend sends the
-<literal>replication</> parameter in the startup message. A boolean value
-of <literal>true</> tells the backend to go into walsender mode, wherein a
-small set of replication commands can be issued instead of SQL statements. Only
-the simple query protocol can be used in walsender mode.
-Passing a <literal>database</> as the value instructs walsender to connect to
-the database specified in the <literal>dbname</> paramter which will in future
-allow some additional commands to the ones specified below to be run.
+ To initiate streaming replication, the frontend sends the
+ <literal>replication</> parameter in the startup message. This accepts the
+ values <literal>true</literal>, <literal>false</literal> (and their 1/0
+ numeric equivalents) or in 9.4 and above, <literal>database</literal>.
+</para>
+<para>
+ Any valid non-false value tells the backend to go into walsender mode, wherein
+ the small set of replication commands documented below can be issued instead
+ of SQL statements.  Only the simple query protocol can be used in walsender
+ mode.
+</para>
+<para>
+ If <literal>replication</literal> is <literal>true</literal>, no specific
+ database is connected to. In this mode only a subset of walsender subcommands
+ are available. To use database-specific walsender commands like the logical
+ replication commands, <literal>replication</> must be set to
+ <literal>database</> and the name of a database to connect to must be
+ specified in the <literal>database</> startup packet field.
+</para>
+<para>
+ For the purpose of testing replication commands, you can make a replication
+ connection via <application>psql</application> or any other <literal>libpq</literal>-using
+ tool with a connection string including the <literal>replication</literal> option,
+ e.g.:
+ <programlisting>
+  psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
+ </programlisting>
+ However it is usually more useful to use
+ <application>pg_receivexlog</application> (for physical replication) or
+ <application>pg_recvlogical</application> (for logical replication).
+</para>
 
+<para>
 The commands accepted in walsender mode are:
-
 <variablelist>
   <varlistentry>
     <term>IDENTIFY_SYSTEM</term>
     <listitem>
      <para>
-      Requests the server to identify itself. Server replies with a result
-      set of a single row, containing four fields:
+      Requests the server to identify itself. Does not require a database name
+      to be specified for the connection. Server replies with a result set of a
+      single row, containing four fields:
      </para>
 
      <para>
@@ -1381,7 +1405,8 @@ The commands accepted in walsender mode are:
     <listitem>
      <para>
       Requests the server to send over the timeline history file for timeline
-      <replaceable class="parameter">tli</replaceable>.  Server replies with a
+      <replaceable class="parameter">tli</replaceable>. Does not require a database
+      name to be specified for the connection. Server replies with a
       result set of a single row, containing two fields:
      </para>
 
@@ -1764,17 +1789,55 @@ The commands accepted in walsender mode are:
      </para>
     </listitem>
   </varlistentry>
+  <varlistentry>
+    <term><literal>START_REPLICATION</literal> <literal>SLOT</literal> <replaceable class="parameter">slotname</> <literal>LOGICAL</literal> <replaceable class="parameter">XXX/XXX</></term>
+    <listitem>
+     <para>
+      Instructs server to start streaming WAL for logical replication, starting
+      at WAL position <replaceable class="parameter">XXX/XXX</>. The server can
+      reply with an error, e.g. if the requested section of WAL has already
+      been recycled. On success, server responds with a CopyBothResponse
+      message, and then starts to stream WAL to the frontend.
+     </para>
+     <para>
+      The output plugin associated with the selected slot is used
+      to process the output for streaming.
+     </para>
+     <variablelist>
+      <varlistentry>
+       <term><literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
+       <listitem>
+         <para>
+          The name of the slot to stream changes from. This parameter is required,
+          and must correspond to an existing logical replication slot created
+          with <literal>CREATE_REPLICATION_SLOT</literal> in
+          <literal>LOGICAL</literal> mode.
+         </para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><replaceable class="parameter">XXX/XXX</></term>
+       <listitem>
+        <para>
+         The WAL position to begin streaming at.
+        </para>
+       </listitem>
+      </varlistentry>
+     </variablelist>
+    </listitem>
+  </varlistentry>
 
   <varlistentry>
-    <term><literal>DROP_REPLICATION_SLOT</literal> <replaceable class="parameter">slotname</></term>
+    <term><literal>DROP_REPLICATION_SLOT</literal> <literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
     <listitem>
      <para>
-      Drops a replication slot, freeing any reserved server-side resources. If
-      the slot is currently in use by an active connection, this command fails.
+     Drops a physical or logical replication slot, freeing any reserved server-side
+     resources. If the slot is currently in use by an active connection this command
+     fails.
      </para>
      <variablelist>
       <varlistentry>
-       <term><replaceable class="parameter">slotname</></term>
+       <term><literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
        <listitem>
          <para>
           The name of the slot to drop.
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 2b02e66..4847d66 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -580,7 +580,7 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-REPLICA-IDENTITY">
     <term><literal>REPLICA IDENTITY</literal></term>
     <listitem>
      <para>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index fc7ad09..f5a3e3e 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -137,7 +137,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
 
   <variablelist>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-TEMPORARY">
     <term><literal>TEMPORARY</> or <literal>TEMP</></term>
     <listitem>
      <para>
@@ -171,7 +171,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-UNLOGGED">
     <term><literal>UNLOGGED</></term>
     <listitem>
      <para>
@@ -1051,6 +1051,17 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>user_catalog_table</literal> (<type>boolean</type>)</term>
+    <listitem>
+     <para>
+      Declare a table as an additional catalog table, e.g. for the purpose of
+      logical replication. See
+      <xref linkend="changesetextraction-capabilities"> for details.
+     </para>
+    </listitem>
+   </varlistentry>
+
    </variablelist>
 
   </refsect2>
-- 
1.8.3.251.g1462b67

#120Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#119)
Re: Changeset Extraction v7.9.1

On Tue, Mar 4, 2014 at 6:26 PM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-03-03 16:48:15 -0500, Robert Haas wrote:

OK, I've committed the 0001 patch, which is the core of this feature,
with a bit of minor additional hacking.

Attached are the rebased patches that are remaining.

Changes:
* minor conflict due to 7558cc95d31edb
* removal of the last XXX in the walsender patch by setting the
timestamps in the 'd' messages correctly.
* Some documentation wordsmithing by Craig

The walsender patch currently contains the changes about feedback we
argued about elsewhere, I guess I either need to back them out, or we
need to argue out that minor bit.

OK, reading through the walsender patch (0002 in this series):

PLEASE stop using a comma to join two independent thoughts. Don't do
it in the comments, and definitely don't do it in error messages. I'm
referring to things like this: "invalid value for option
\"replication\", legal values are false, 0, true, 1 or database". I
know that you're not a native English speaker, and if you were
submitting a smaller amount of code I wouldn't just fix it for you,
but you do this A LOT and I've probably fixed a hundred instances of
it already and I can't cope with fixing another hundred. In code
comments, a semicolon is often an adequate substitute, but that even
with that change this won't do for an error message. For that, you
should copy the style of something done elsewhere. For example, in
this instance, perhaps look to this precedent:

rhaas=# set synchronous_commit = barfle;
ERROR: invalid value for parameter "synchronous_commit": "barfle"
HINT: Available values: local, remote_write, on, off.

This patch still treats "allow a walsender to connect to a database"
as a separate feature from "allow logical replication". I'm not
convinced that's a good idea. What you're proposing to do is allow
replication=database in addition to replication=true and
replication=false. But how about instead allowing
replication=physical and replication=logical? "physical" can just be
a synonym for "true" and the database name can be ignored as it is
today. "logical" can pay attention the database name. I'm not
totally wedded to that exact design, but basically, I'm not
comfortable with allowing a physical WAL sender to connect to a
database in advance of a concrete need. We might want to leave some
room to go there later if we think it's a likely direction, but
allowing people to do it in advance of any functional advantage just
seems like a recipe for bugs. Practically nobody will run that way so
breakage won't be timely detected. (And no, I don't know exactly what
will break.)

+       if (am_cascading_walsender && !RecoveryInProgress())
+       {
+               ereport(LOG,
+                               (errmsg("terminating walsender process
to force cascaded standby to update timeline and reconnect")));
+               walsender_ready_to_stop = true;
+       }

Does this apply to logical replication? Seems like it could at least
have a comment.

+       /*
+        * XXX: For feedback purposes it would be nicer to set sentPtr to
+        * cmd->startpoint, but we use it to know where to read xlog in the main
+        * loop...
+        */

I'm not sure I understand this.

WalSndWriteData() looks kind of cut-and-pasty.

WalSndWaitForWal() is yet another slightly-modified copy of the same
darn loop. Surely we need a better way of doing this. It's
absolutely inevitable that some future hacker will not patch every
copy of this loop in some situation where that is required.

There might be more; that's all I see at the moment.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#121Josh Berkus
josh@agliodbs.com
In reply to: Andres Freund (#1)
Re: Changeset Extraction v7.9.1

On 03/05/2014 10:49 AM, Robert Haas wrote:

This patch still treats "allow a walsender to connect to a database"
as a separate feature from "allow logical replication". I'm not
convinced that's a good idea. What you're proposing to do is allow
replication=database in addition to replication=true and
replication=false. But how about instead allowing
replication=physical and replication=logical? "physical" can just be
a synonym for "true" and the database name can be ignored as it is
today. "logical" can pay attention the database name. I'm not
totally wedded to that exact design, but basically, I'm not
comfortable with allowing a physical WAL sender to connect to a
database in advance of a concrete need. We might want to leave some
room to go there later if we think it's a likely direction, but
allowing people to do it in advance of any functional advantage just
seems like a recipe for bugs. Practically nobody will run that way so
breakage won't be timely detected. (And no, I don't know exactly what
will break.)

Personally, I'd prefer to just have the permission here governed by the
existing replication permission; why make things complicated for users?
But maybe Andres has some other requirement he's trying to fullfill?

--
Josh Berkus
PostgreSQL Experts Inc.
http://pgexperts.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#122Robert Haas
robertmhaas@gmail.com
In reply to: Josh Berkus (#121)
Re: Changeset Extraction v7.9.1

On Wed, Mar 5, 2014 at 1:57 PM, Josh Berkus <josh@agliodbs.com> wrote:

On 03/05/2014 10:49 AM, Robert Haas wrote:

This patch still treats "allow a walsender to connect to a database"
as a separate feature from "allow logical replication". I'm not
convinced that's a good idea. What you're proposing to do is allow
replication=database in addition to replication=true and
replication=false. But how about instead allowing
replication=physical and replication=logical? "physical" can just be
a synonym for "true" and the database name can be ignored as it is
today. "logical" can pay attention the database name. I'm not
totally wedded to that exact design, but basically, I'm not
comfortable with allowing a physical WAL sender to connect to a
database in advance of a concrete need. We might want to leave some
room to go there later if we think it's a likely direction, but
allowing people to do it in advance of any functional advantage just
seems like a recipe for bugs. Practically nobody will run that way so
breakage won't be timely detected. (And no, I don't know exactly what
will break.)

Personally, I'd prefer to just have the permission here governed by the
existing replication permission; why make things complicated for users?
But maybe Andres has some other requirement he's trying to fullfill?

This isn't about permissions; it's about the fact that physical
replication is cluster-wide, but logical replication is per-database.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#123Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#120)
Re: Changeset Extraction v7.9.1

Hi,

On 2014-03-05 13:49:23 -0500, Robert Haas wrote:

PLEASE stop using a comma to join two independent thoughts.

Ok. I'll try.

Is this a personal preference, or a general rule? There seems to be a
fair amount of comments in pg doing so?

This patch still treats "allow a walsender to connect to a database"
as a separate feature from "allow logical replication". I'm not
convinced that's a good idea. What you're proposing to do is allow
replication=database in addition to replication=true and
replication=false. But how about instead allowing
replication=physical and replication=logical? "physical" can just be
a synonym for "true" and the database name can be ignored as it is
today. "logical" can pay attention the database name. I'm not
totally wedded to that exact design, but basically, I'm not
comfortable with allowing a physical WAL sender to connect to a
database in advance of a concrete need. We might want to leave some
room to go there later if we think it's a likely direction, but
allowing people to do it in advance of any functional advantage just
seems like a recipe for bugs. Practically nobody will run that way so
breakage won't be timely detected. (And no, I don't know exactly what
will break.)

I am only mildly against doing so, so you certainly can nudge me in that
direction.
Would you want to refuse using existing commands in logical mode? It's not
unrealistic to first want to perform a basebackup and then establish a
logical slot to replay from there on. It's probably not too bad to force
separate connections there, but it seems like a somewhwat pointless
exercise to me?

+       if (am_cascading_walsender && !RecoveryInProgress())
+       {
+               ereport(LOG,
+                               (errmsg("terminating walsender process
to force cascaded standby to update timeline and reconnect")));
+               walsender_ready_to_stop = true;
+       }

Does this apply to logical replication? Seems like it could at least
have a comment.

I think it does make sense to force a disconnect in this case to
simplify code, but you're right, both a comment and some TLC for the
message are in order.

WalSndWriteData() looks kind of cut-and-pasty.

You mean from the WalSndLoop? Yea. I tried to reduce it by introducing
WalSndCheckTimeOut() but I think at the very least
WalSndComputeTimeOut() is in order.

I very much dislike having the three different event loops, but it's
pretty much forced by the design of the xlogreader. "My" xlogreader
version didn't block when it neeeded to wait for WAL but just returned
"need input/output", but with the eventually committed version you're
pretty much forced to block inside the read_page callback.

I don't really have a idea how we could sensibly unify them atm.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#124Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#123)
Re: Changeset Extraction v7.9.1

On Wed, Mar 5, 2014 at 3:04 PM, Andres Freund <andres@2ndquadrant.com> wrote:

Hi,

On 2014-03-05 13:49:23 -0500, Robert Haas wrote:

PLEASE stop using a comma to join two independent thoughts.

Ok. I'll try.

Is this a personal preference, or a general rule? There seems to be a
fair amount of comments in pg doing so?

http://en.wikipedia.org/wiki/Comma_splice

This patch still treats "allow a walsender to connect to a database"
as a separate feature from "allow logical replication". I'm not
convinced that's a good idea. What you're proposing to do is allow
replication=database in addition to replication=true and
replication=false. But how about instead allowing
replication=physical and replication=logical? "physical" can just be
a synonym for "true" and the database name can be ignored as it is
today. "logical" can pay attention the database name. I'm not
totally wedded to that exact design, but basically, I'm not
comfortable with allowing a physical WAL sender to connect to a
database in advance of a concrete need. We might want to leave some
room to go there later if we think it's a likely direction, but
allowing people to do it in advance of any functional advantage just
seems like a recipe for bugs. Practically nobody will run that way so
breakage won't be timely detected. (And no, I don't know exactly what
will break.)

I am only mildly against doing so, so you certainly can nudge me in that
direction.
Would you want to refuse using existing commands in logical mode? It's not
unrealistic to first want to perform a basebackup and then establish a
logical slot to replay from there on. It's probably not too bad to force
separate connections there, but it seems like a somewhwat pointless
exercise to me?

Hmm, that's an interesting point. I didn't consider the case of a
base backup followed by replication, on the same connection. That
might be sufficient justification for doing it the way you have it.

WalSndWriteData() looks kind of cut-and-pasty.

You mean from the WalSndLoop? Yea. I tried to reduce it by introducing
WalSndCheckTimeOut() but I think at the very least
WalSndComputeTimeOut() is in order.

I very much dislike having the three different event loops, but it's
pretty much forced by the design of the xlogreader. "My" xlogreader
version didn't block when it neeeded to wait for WAL but just returned
"need input/output", but with the eventually committed version you're
pretty much forced to block inside the read_page callback.

I don't really have a idea how we could sensibly unify them atm.

WalSndLoop(void (*gutsfn)())?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#125Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#124)
Re: Changeset Extraction v7.9.1

On 2014-03-05 17:05:24 -0500, Robert Haas wrote:

I very much dislike having the three different event loops, but it's
pretty much forced by the design of the xlogreader. "My" xlogreader
version didn't block when it neeeded to wait for WAL but just returned
"need input/output", but with the eventually committed version you're
pretty much forced to block inside the read_page callback.

I don't really have a idea how we could sensibly unify them atm.

WalSndLoop(void (*gutsfn)())?

The problem is that they are actually different. In the WalSndLoop we're
also maintaining the walsender's state, in WalSndWriteData() we're just
waiting for writes to be flushed, in WalSndWaitForWal we're primarily
waiting for the flush pointer to pass some LSN. And the timing of the
individual checks isn't trivial (just added some more comments about
it).

I'll simplify it by pulling out more common code, maybe it'll become
apparent how it should look.

Greetings,

Andres Freund

PS: I so far considered my language counted poetic, that's why I used
the splicing comma so liberally... Thanks for the link.

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#126Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#125)
1 attachment(s)
Re: Changeset Extraction v7.9.1

Hi,

On 2014-03-05 23:20:57 +0100, Andres Freund wrote:

On 2014-03-05 17:05:24 -0500, Robert Haas wrote:

I very much dislike having the three different event loops, but it's
pretty much forced by the design of the xlogreader. "My" xlogreader
version didn't block when it neeeded to wait for WAL but just returned
"need input/output", but with the eventually committed version you're
pretty much forced to block inside the read_page callback.

I don't really have a idea how we could sensibly unify them atm.

WalSndLoop(void (*gutsfn)())?

The problem is that they are actually different. In the WalSndLoop we're
also maintaining the walsender's state, in WalSndWriteData() we're just
waiting for writes to be flushed, in WalSndWaitForWal we're primarily
waiting for the flush pointer to pass some LSN. And the timing of the
individual checks isn't trivial (just added some more comments about
it).

I'll simplify it by pulling out more common code, maybe it'll become
apparent how it should look.

I've attached a new version of the walsender patch. It's been rebased
ontop of Heikki's latest commit to walsender.c. I've changed a fair bit
of stuff:
* The sleeptime is now computed to sleep until we either need to send a
keepalive or kill ourselves, as Heikki sugggested.
* Sleep time computation, sending pings, checking timeouts is now done
in separate functions.
* Comment and codestyle improvements.

Although they are shorter and simpler now, I have not managed to unify
the three loops however. They seem to be too different to unify them
inside one. I tried a common function with an 'wait_for' bitmask
argument, but that turned out to be fairly illegible. The checks in
WalSndWaitForWal() and WalSndLoop() just seem to be too different.

I'd be grateful if you (or somebody else!) could have a quick look at
body of the loops in WalSndWriteData(), WalSndWaitForWal() and
WalSndLoop(). Maybe I am just staring at it the wrong way.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-Add-walsender-interface-for-the-logical-decoding-fun.patchtext/x-patch; charset=iso-8859-1Download
From ca84cd3d2966f0e7297d1c7270b094122eec2f18 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 00:15:38 +0100
Subject: [PATCH] Add walsender interface for the logical decoding
 functionality.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This exposes the changeset extraction feature via walsenders which
allows the data to be received in a streaming fashion and supports
synchronous replication.

To do this walsenders need to be able to connect to a specific
database. For that it extend the existing 'replication' parameter to
not only allow a boolean value but also "database". If the latter is
specified we connect to the database specified in 'dbname'.

Andres Freund, with contributions from Álvaro Herrera, reviewed by
Robert Haas.
---
 doc/src/sgml/protocol.sgml                         |  24 +-
 src/backend/postmaster/postmaster.c                |  28 +-
 .../libpqwalreceiver/libpqwalreceiver.c            |   4 +-
 src/backend/replication/repl_gram.y                |  81 +-
 src/backend/replication/repl_scanner.l             |   1 +
 src/backend/replication/walsender.c                | 914 ++++++++++++++++++---
 src/backend/utils/init/postinit.c                  |  15 +-
 src/bin/pg_basebackup/pg_basebackup.c              |   6 +-
 src/bin/pg_basebackup/pg_receivexlog.c             |   6 +-
 src/bin/pg_basebackup/receivelog.c                 |   6 +-
 src/include/replication/walsender.h                |   1 +
 src/tools/pgindent/typedefs.list                   |   1 +
 12 files changed, 918 insertions(+), 169 deletions(-)

diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index d36f2f3..510bf9a 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1302,10 +1302,13 @@
 
 <para>
 To initiate streaming replication, the frontend sends the
-<literal>replication</> parameter in the startup message. This tells the
-backend to go into walsender mode, wherein a small set of replication commands
-can be issued instead of SQL statements. Only the simple query protocol can be
-used in walsender mode.
+<literal>replication</> parameter in the startup message. A boolean value
+of <literal>true</> tells the backend to go into walsender mode, wherein a
+small set of replication commands can be issued instead of SQL statements. Only
+the simple query protocol can be used in walsender mode.
+Passing a <literal>database</> as the value instructs walsender to connect to
+the database specified in the <literal>dbname</> paramter which will in future
+allow some additional commands to the ones specified below to be run.
 
 The commands accepted in walsender mode are:
 
@@ -1315,7 +1318,7 @@ The commands accepted in walsender mode are:
     <listitem>
      <para>
       Requests the server to identify itself. Server replies with a result
-      set of a single row, containing three fields:
+      set of a single row, containing four fields:
      </para>
 
      <para>
@@ -1357,6 +1360,17 @@ The commands accepted in walsender mode are:
       </listitem>
       </varlistentry>
 
+      <varlistentry>
+      <term>
+       dbname
+      </term>
+      <listitem>
+      <para>
+       Database connected to or NULL.
+      </para>
+      </listitem>
+      </varlistentry>
+
       </variablelist>
      </para>
     </listitem>
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index b7f99fc..8426824 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1884,10 +1884,23 @@ retry1:
 				port->cmdline_options = pstrdup(valptr);
 			else if (strcmp(nameptr, "replication") == 0)
 			{
-				if (!parse_bool(valptr, &am_walsender))
+				/*
+				 * Due to backward compatibility concerns the replication
+				 * parameter is a hybrid beast which allows the value to be
+				 * either boolean or the string 'database'. The latter
+				 * connects to a specific database which is e.g. required for
+				 * logical decoding while.
+				 */
+				if (strcmp(valptr, "database") == 0)
+				{
+					am_walsender = true;
+					am_db_walsender = true;
+				}
+				else if (!parse_bool(valptr, &am_walsender))
 					ereport(FATAL,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("invalid value for boolean option \"replication\"")));
+							 errmsg("invalid value for parameter \"replication\""),
+							 errhint("Valid values are: false, 0, true, 1, database.")));
 			}
 			else
 			{
@@ -1968,8 +1981,15 @@ retry1:
 	if (strlen(port->user_name) >= NAMEDATALEN)
 		port->user_name[NAMEDATALEN - 1] = '\0';
 
-	/* Walsender is not related to a particular database */
-	if (am_walsender)
+	/*
+	 * Normal walsender backens, e.g. for streaming replication, are not
+	 * connected to a particular database. But walsenders used for logical
+	 * replication need to connect to a specific database. We allow streaming
+	 * replication commands to be issued even if connected to a database as it
+	 * can make sense to first make a basebackup and then stream changes
+	 * starting from that.
+	 */
+	if (am_walsender && !am_db_walsender)
 		port->database_name[0] = '\0';
 
 	/*
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index c10374c..2fb731b 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -131,7 +131,7 @@ libpqrcv_identify_system(TimeLineID *primary_tli)
 						"the primary server: %s",
 						PQerrorMessage(streamConn))));
 	}
-	if (PQnfields(res) != 3 || PQntuples(res) != 1)
+	if (PQnfields(res) < 3 || PQntuples(res) != 1)
 	{
 		int			ntuples = PQntuples(res);
 		int			nfields = PQnfields(res);
@@ -139,7 +139,7 @@ libpqrcv_identify_system(TimeLineID *primary_tli)
 		PQclear(res);
 		ereport(ERROR,
 				(errmsg("invalid response from primary server"),
-				 errdetail("Expected 1 tuple with 3 fields, got %d tuples with %d fields.",
+				 errdetail("Expected 1 tuple with 3 or more fields, got %d tuples with %d fields.",
 						   ntuples, nfields)));
 	}
 	primary_sysid = PQgetvalue(res, 0, 0);
diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y
index 308889b..154aaac 100644
--- a/src/backend/replication/repl_gram.y
+++ b/src/backend/replication/repl_gram.y
@@ -73,13 +73,17 @@ Node *replication_parse_result;
 %token K_WAL
 %token K_TIMELINE
 %token K_PHYSICAL
+%token K_LOGICAL
 %token K_SLOT
 
 %type <node>	command
-%type <node>	base_backup start_replication create_replication_slot drop_replication_slot identify_system timeline_history
+%type <node>	base_backup start_replication start_logical_replication create_replication_slot drop_replication_slot identify_system timeline_history
 %type <list>	base_backup_opt_list
 %type <defelt>	base_backup_opt
 %type <uintval>	opt_timeline
+%type <list>	plugin_options plugin_opt_list
+%type <defelt>	plugin_opt_elem
+%type <node>	plugin_opt_arg
 %type <str>		opt_slot
 
 %%
@@ -98,6 +102,7 @@ command:
 			identify_system
 			| base_backup
 			| start_replication
+			| start_logical_replication
 			| create_replication_slot
 			| drop_replication_slot
 			| timeline_history
@@ -165,8 +170,8 @@ base_backup_opt:
 				}
 			;
 
-/* CREATE_REPLICATION_SLOT SLOT slot PHYSICAL */
 create_replication_slot:
+			/* CREATE_REPLICATION_SLOT slot PHYSICAL */
 			K_CREATE_REPLICATION_SLOT IDENT K_PHYSICAL
 				{
 					CreateReplicationSlotCmd *cmd;
@@ -175,9 +180,19 @@ create_replication_slot:
 					cmd->slotname = $2;
 					$$ = (Node *) cmd;
 				}
+			/* CREATE_REPLICATION_SLOT slot LOGICAL plugin */
+			| K_CREATE_REPLICATION_SLOT IDENT K_LOGICAL IDENT
+				{
+					CreateReplicationSlotCmd *cmd;
+					cmd = makeNode(CreateReplicationSlotCmd);
+					cmd->kind = REPLICATION_KIND_LOGICAL;
+					cmd->slotname = $2;
+					cmd->plugin = $4;
+					$$ = (Node *) cmd;
+				}
 			;
 
-/* DROP_REPLICATION_SLOT SLOT slot */
+/* DROP_REPLICATION_SLOT slot */
 drop_replication_slot:
 			K_DROP_REPLICATION_SLOT IDENT
 				{
@@ -205,19 +220,19 @@ start_replication:
 				}
 			;
 
-opt_timeline:
-			K_TIMELINE UCONST
+/* START_REPLICATION SLOT slot LOGICAL %X/%X options */
+start_logical_replication:
+			K_START_REPLICATION K_SLOT IDENT K_LOGICAL RECPTR plugin_options
 				{
-					if ($2 <= 0)
-						ereport(ERROR,
-								(errcode(ERRCODE_SYNTAX_ERROR),
-								 (errmsg("invalid timeline %u", $2))));
-					$$ = $2;
+					StartReplicationCmd *cmd;
+					cmd = makeNode(StartReplicationCmd);
+					cmd->kind = REPLICATION_KIND_LOGICAL;;
+					cmd->slotname = $3;
+					cmd->startpoint = $5;
+					cmd->options = $6;
+					$$ = (Node *) cmd;
 				}
-			| /* EMPTY */
-				{ $$ = 0; }
 			;
-
 /*
  * TIMELINE_HISTORY %d
  */
@@ -250,6 +265,46 @@ opt_slot:
 				{ $$ = NULL; }
 			;
 
+opt_timeline:
+			K_TIMELINE UCONST
+				{
+					if ($2 <= 0)
+						ereport(ERROR,
+								(errcode(ERRCODE_SYNTAX_ERROR),
+								 (errmsg("invalid timeline %u", $2))));
+					$$ = $2;
+				}
+				| /* EMPTY */			{ $$ = 0; }
+			;
+
+
+plugin_options:
+			'(' plugin_opt_list ')'			{ $$ = $2; }
+			| /* EMPTY */					{ $$ = NIL; }
+		;
+
+plugin_opt_list:
+			plugin_opt_elem
+				{
+					$$ = list_make1($1);
+				}
+			| plugin_opt_list ',' plugin_opt_elem
+				{
+					$$ = lappend($1, $3);
+				}
+		;
+
+plugin_opt_elem:
+			IDENT plugin_opt_arg
+				{
+					$$ = makeDefElem($1, $2);
+				}
+		;
+
+plugin_opt_arg:
+			SCONST							{ $$ = (Node *) makeString($1); }
+			| /* EMPTY */					{ $$ = NULL; }
+		;
 %%
 
 #include "repl_scanner.c"
diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l
index ca32aa6..a257124 100644
--- a/src/backend/replication/repl_scanner.l
+++ b/src/backend/replication/repl_scanner.l
@@ -94,6 +94,7 @@ CREATE_REPLICATION_SLOT		{ return K_CREATE_REPLICATION_SLOT; }
 DROP_REPLICATION_SLOT		{ return K_DROP_REPLICATION_SLOT; }
 TIMELINE_HISTORY	{ return K_TIMELINE_HISTORY; }
 PHYSICAL			{ return K_PHYSICAL; }
+LOGICAL				{ return K_LOGICAL; }
 SLOT				{ return K_SLOT; }
 
 ","				{ return ','; }
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 003c797..4c48cd6 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -45,15 +45,22 @@
 
 #include "access/timeline.h"
 #include "access/transam.h"
+#include "access/xact.h"
 #include "access/xlog_internal.h"
+
 #include "catalog/pg_type.h"
+#include "commands/dbcommands.h"
 #include "funcapi.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "nodes/replnodes.h"
 #include "replication/basebackup.h"
+#include "replication/decode.h"
+#include "replication/logical.h"
+#include "replication/logicalfuncs.h"
 #include "replication/slot.h"
+#include "replication/snapbuild.h"
 #include "replication/syncrep.h"
 #include "replication/slot.h"
 #include "replication/walreceiver.h"
@@ -92,9 +99,10 @@ WalSndCtlData *WalSndCtl = NULL;
 WalSnd	   *MyWalSnd = NULL;
 
 /* Global state */
-bool		am_walsender = false;		/* Am I a walsender process ? */
+bool		am_walsender = false;		/* Am I a walsender process? */
 bool		am_cascading_walsender = false;		/* Am I cascading WAL to
-												 * another standby ? */
+												 * another standby? */
+bool		am_db_walsender = false;	/* Connected to a database? */
 
 /* User-settable parameters for walsender */
 int			max_wal_senders = 0;	/* the maximum number of concurrent walsenders */
@@ -145,7 +153,7 @@ static StringInfoData tmpbuf;
 static TimestampTz last_reply_timestamp;
 
 /* Have we sent a heartbeat message asking for reply, since last reply? */
-static bool ping_sent = false;
+static bool waiting_for_ping_response = false;
 
 /*
  * While streaming WAL in Copy mode, streamingDoneSending is set to true
@@ -156,6 +164,9 @@ static bool ping_sent = false;
 static bool streamingDoneSending;
 static bool streamingDoneReceiving;
 
+/* Are we there yet? */
+static bool		WalSndCaughtUp = false;
+
 /* Flags set by signal handlers for later service in main loop */
 static volatile sig_atomic_t got_SIGHUP = false;
 static volatile sig_atomic_t walsender_ready_to_stop = false;
@@ -168,24 +179,42 @@ static volatile sig_atomic_t walsender_ready_to_stop = false;
  */
 static volatile sig_atomic_t replication_active = false;
 
+static LogicalDecodingContext *logical_decoding_ctx = NULL;
+static XLogRecPtr  logical_startptr = InvalidXLogRecPtr;
+
 /* Signal handlers */
 static void WalSndSigHupHandler(SIGNAL_ARGS);
 static void WalSndXLogSendHandler(SIGNAL_ARGS);
 static void WalSndLastCycleHandler(SIGNAL_ARGS);
 
 /* Prototypes for private functions */
-static void WalSndLoop(void);
+typedef void (*WalSndSendDataCallback)(void);
+static void WalSndLoop(WalSndSendDataCallback send_data);
 static void InitWalSenderSlot(void);
 static void WalSndKill(int code, Datum arg);
-static void XLogSend(bool *caughtup);
+static void WalSndShutdown(void) __attribute__((noreturn));
+static void XLogSendPhysical(void);
+static void XLogSendLogical(void);
+static void WalSndDone(WalSndSendDataCallback send_data);
 static XLogRecPtr GetStandbyFlushRecPtr(void);
 static void IdentifySystem(void);
+static void CreateReplicationSlot(CreateReplicationSlotCmd *cmd);
+static void DropReplicationSlot(DropReplicationSlotCmd *cmd);
 static void StartReplication(StartReplicationCmd *cmd);
+static void StartLogicalReplication(StartReplicationCmd *cmd);
 static void ProcessStandbyMessage(void);
 static void ProcessStandbyReplyMessage(void);
 static void ProcessStandbyHSFeedbackMessage(void);
 static void ProcessRepliesIfAny(void);
 static void WalSndKeepalive(bool requestReply);
+static void WalSndKeepaliveIfNecessary(TimestampTz now);
+static void WalSndCheckTimeOut(TimestampTz now);
+static long WalSndComputeSleeptime(TimestampTz now);
+static void WalSndPrepareWrite(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write);
+static void WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write);
+static XLogRecPtr WalSndWaitForWal(XLogRecPtr loc);
+
+static void XLogRead(char *buf, XLogRecPtr startptr, Size count);
 
 
 /* Initialize walsender process before entering the main command loop */
@@ -241,6 +270,23 @@ WalSndErrorCleanup()
 }
 
 /*
+ * Handle a client's connection abort in an orderly manner.
+ */
+static void
+WalSndShutdown(void)
+{
+	/*
+	 * Reset whereToSendOutput to prevent ereport from attempting to send any
+	 * more messages to the standby.
+	 */
+	if (whereToSendOutput == DestRemote)
+		whereToSendOutput = DestNone;
+
+	proc_exit(0);
+	abort();					/* keep the compiler quiet */
+}
+
+/*
  * Handle the IDENTIFY_SYSTEM command.
  */
 static void
@@ -251,10 +297,12 @@ IdentifySystem(void)
 	char		tli[11];
 	char		xpos[MAXFNAMELEN];
 	XLogRecPtr	logptr;
+	char	   *dbname = NULL;
 
 	/*
-	 * Reply with a result set with one row, three columns. First col is
-	 * system ID, second is timeline ID, and third is current xlog location.
+	 * Reply with a result set with one row, four columns. First col is system
+	 * ID, second is timeline ID, third is current xlog location and the fourth
+	 * contains the database name if we are connected to one.
 	 */
 
 	snprintf(sysid, sizeof(sysid), UINT64_FORMAT,
@@ -273,9 +321,23 @@ IdentifySystem(void)
 
 	snprintf(xpos, sizeof(xpos), "%X/%X", (uint32) (logptr >> 32), (uint32) logptr);
 
+	if (MyDatabaseId != InvalidOid)
+	{
+		MemoryContext cur = CurrentMemoryContext;
+
+		/* syscache access needs a transaction env. */
+		StartTransactionCommand();
+		/* make dbname live outside TX context */
+		MemoryContextSwitchTo(cur);
+		dbname = get_database_name(MyDatabaseId);
+		CommitTransactionCommand();
+		/* CommitTransactionCommand switches to TopMemoryContext */
+		MemoryContextSwitchTo(cur);
+	}
+
 	/* Send a RowDescription message */
 	pq_beginmessage(&buf, 'T');
-	pq_sendint(&buf, 3, 2);		/* 3 fields */
+	pq_sendint(&buf, 4, 2);		/* 4 fields */
 
 	/* first field */
 	pq_sendstring(&buf, "systemid");	/* col name */
@@ -296,24 +358,43 @@ IdentifySystem(void)
 	pq_sendint(&buf, 0, 2);		/* format code */
 
 	/* third field */
-	pq_sendstring(&buf, "xlogpos");
-	pq_sendint(&buf, 0, 4);
-	pq_sendint(&buf, 0, 2);
-	pq_sendint(&buf, TEXTOID, 4);
-	pq_sendint(&buf, -1, 2);
-	pq_sendint(&buf, 0, 4);
-	pq_sendint(&buf, 0, 2);
+	pq_sendstring(&buf, "xlogpos"); /* col name */
+	pq_sendint(&buf, 0, 4);     /* table oid */
+	pq_sendint(&buf, 0, 2);     /* attnum */
+	pq_sendint(&buf, TEXTOID, 4);       /* type oid */
+	pq_sendint(&buf, -1, 2);        /* typlen */
+	pq_sendint(&buf, 0, 4);     /* typmod */
+	pq_sendint(&buf, 0, 2);     /* format code */
+
+	/* fourth field */
+	pq_sendstring(&buf, "dbname");  /* col name */
+	pq_sendint(&buf, 0, 4);     /* table oid */
+	pq_sendint(&buf, 0, 2);     /* attnum */
+	pq_sendint(&buf, TEXTOID, 4);       /* type oid */
+	pq_sendint(&buf, -1, 2);        /* typlen */
+	pq_sendint(&buf, 0, 4);     /* typmod */
+	pq_sendint(&buf, 0, 2);     /* format code */
 	pq_endmessage(&buf);
 
 	/* Send a DataRow message */
 	pq_beginmessage(&buf, 'D');
-	pq_sendint(&buf, 3, 2);		/* # of columns */
+	pq_sendint(&buf, 4, 2);		/* # of columns */
 	pq_sendint(&buf, strlen(sysid), 4); /* col1 len */
 	pq_sendbytes(&buf, (char *) &sysid, strlen(sysid));
 	pq_sendint(&buf, strlen(tli), 4);	/* col2 len */
 	pq_sendbytes(&buf, (char *) tli, strlen(tli));
 	pq_sendint(&buf, strlen(xpos), 4);	/* col3 len */
 	pq_sendbytes(&buf, (char *) xpos, strlen(xpos));
+	/* send NULL if not connected to a database */
+	if (dbname)
+	{
+		pq_sendint(&buf, strlen(dbname), 4);    /* col4 len */
+		pq_sendbytes(&buf, (char *) dbname, strlen(dbname));
+	}
+	else
+	{
+		pq_sendint(&buf, -1, 4);    /* col4 len, NULL */
+	}
 
 	pq_endmessage(&buf);
 }
@@ -572,7 +653,7 @@ StartReplication(StartReplicationCmd *cmd)
 		/* Main loop of walsender */
 		replication_active = true;
 
-		WalSndLoop();
+		WalSndLoop(XLogSendPhysical);
 
 		replication_active = false;
 		if (walsender_ready_to_stop)
@@ -643,12 +724,47 @@ StartReplication(StartReplicationCmd *cmd)
 }
 
 /*
+ * read_page callback for logical decoding contexts, as a walsender process.
+ *
+ * Inside the walsender we can do better than logical_read_local_xlog_page,
+ * which has to do a plain sleep/busy loop, because the walsender's latch gets
+ * set everytime WAL is flushed.
+ */
+static int
+logical_read_xlog_page(XLogReaderState* state, XLogRecPtr targetPagePtr, int reqLen,
+				 XLogRecPtr targetRecPtr, char* cur_page, TimeLineID *pageTLI)
+{
+	XLogRecPtr flushptr;
+	int		count;
+
+	/* make sure we have enough WAL available */
+	flushptr = WalSndWaitForWal(targetPagePtr + reqLen);
+
+	/* more than one block available */
+	if (targetPagePtr + XLOG_BLCKSZ <= flushptr)
+		count = XLOG_BLCKSZ;
+	/* not enough WAL synced, that can happen during shutdown */
+	else if (targetPagePtr + reqLen > flushptr)
+		return -1;
+	/* part of the page available */
+	else
+		count = flushptr - targetPagePtr;
+
+	/* now actually read the data, we know it's there */
+	XLogRead(cur_page, targetPagePtr, XLOG_BLCKSZ);
+
+	return count;
+}
+
+/*
  * Create a new replication slot.
  */
 static void
 CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 {
 	const char *slot_name;
+	const char *snapshot_name = NULL;
+	char        xpos[MAXFNAMELEN];
 	StringInfoData buf;
 
 	Assert(!MyReplicationSlot);
@@ -657,24 +773,51 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 	sendTimeLineIsHistoric = false;
 	sendTimeLine = ThisTimeLineID;
 
-	ReplicationSlotCreate(cmd->slotname,
-						  cmd->kind == REPLICATION_KIND_LOGICAL,
-						  RS_PERSISTENT);
+	if (cmd->kind == REPLICATION_KIND_PHYSICAL)
+	{
+		ReplicationSlotCreate(cmd->slotname, false, RS_PERSISTENT);
+	}
+	else
+	{
+		CheckLogicalDecodingRequirements();
+		ReplicationSlotCreate(cmd->slotname, true, RS_EPHEMERAL);
+	}
 
 	initStringInfo(&output_message);
 
 	slot_name = NameStr(MyReplicationSlot->data.name);
 
-	/*
-	 * It may seem somewhat pointless to send back the same slot name the
-	 * client just requested and nothing else, but logical replication
-	 * will add more fields here.  (We could consider removing the slot
-	 * name from what's sent back, though, since the client has specified
-	 * that.)
-	 */
+	if (cmd->kind == REPLICATION_KIND_LOGICAL)
+	{
+		LogicalDecodingContext *ctx;
+
+		ctx = CreateInitDecodingContext(
+			cmd->plugin, NIL,
+			logical_read_xlog_page,
+			WalSndPrepareWrite, WalSndWriteData);
+
+		/* build initial snapshot, might take a while */
+		DecodingContextFindStartpoint(ctx);
+
+		/*
+		 * Export a plain (not of the snapbuild.c type) snapshot to the user
+		 * that can be imported into another session.
+		 */
+		snapshot_name = SnapBuildExportSnapshot(ctx->snapshot_builder);
+
+		/* don't need the decoding context anymore */
+		FreeDecodingContext(ctx);
+
+		ReplicationSlotPersist();
+	}
+
+	slot_name = NameStr(MyReplicationSlot->data.name);
+	snprintf(xpos, sizeof(xpos), "%X/%X",
+			 (uint32) (MyReplicationSlot->data.confirmed_flush >> 32),
+			 (uint32) MyReplicationSlot->data.confirmed_flush);
 
 	pq_beginmessage(&buf, 'T');
-	pq_sendint(&buf, 1, 2);		/* 1 field */
+	pq_sendint(&buf, 4, 2);		/* 4 fields */
 
 	/* first field: slot name */
 	pq_sendstring(&buf, "slot_name");	/* col name */
@@ -685,16 +828,65 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 	pq_sendint(&buf, 0, 4);		/* typmod */
 	pq_sendint(&buf, 0, 2);		/* format code */
 
+	/* second field: LSN at which we became consistent */
+	pq_sendstring(&buf, "consistent_point");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
+	/* third field: exported snapshot's name */
+	pq_sendstring(&buf, "snapshot_name");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
+	/* fourth field: output plugin */
+	pq_sendstring(&buf, "output_plugin");	/* col name */
+	pq_sendint(&buf, 0, 4);		/* table oid */
+	pq_sendint(&buf, 0, 2);		/* attnum */
+	pq_sendint(&buf, TEXTOID, 4);		/* type oid */
+	pq_sendint(&buf, -1, 2);	/* typlen */
+	pq_sendint(&buf, 0, 4);		/* typmod */
+	pq_sendint(&buf, 0, 2);		/* format code */
+
 	pq_endmessage(&buf);
 
 	/* Send a DataRow message */
 	pq_beginmessage(&buf, 'D');
-	pq_sendint(&buf, 1, 2);		/* # of columns */
+	pq_sendint(&buf, 4, 2);		/* # of columns */
 
 	/* slot_name */
 	pq_sendint(&buf, strlen(slot_name), 4); /* col1 len */
 	pq_sendbytes(&buf, slot_name, strlen(slot_name));
 
+	/* consistent wal location */
+	pq_sendint(&buf, strlen(xpos), 4); /* col2 len */
+	pq_sendbytes(&buf, xpos, strlen(xpos));
+
+	/* snapshot name */
+	if (snapshot_name != NULL)
+	{
+		pq_sendint(&buf, strlen(snapshot_name), 4); /* col3 len */
+		pq_sendbytes(&buf, snapshot_name, strlen(snapshot_name));
+	}
+	else
+		pq_sendint(&buf, -1, 4);    /* col3 len, NULL */
+
+	/* plugin */
+	if (cmd->plugin != NULL)
+	{
+		pq_sendint(&buf, strlen(cmd->plugin), 4); /* col4 len */
+		pq_sendbytes(&buf, cmd->plugin, strlen(cmd->plugin));
+	}
+	else
+		pq_sendint(&buf, -1, 4);	/* col4 len, NULL */
+
 	pq_endmessage(&buf);
 
 	/*
@@ -714,6 +906,339 @@ DropReplicationSlot(DropReplicationSlotCmd *cmd)
 }
 
 /*
+ * Load previously initiated logical slot and prepare for sending data (via
+ * WalSndLoop).
+ */
+static void
+StartLogicalReplication(StartReplicationCmd *cmd)
+{
+	StringInfoData buf;
+
+	/* make sure that our requirements are still fulfilled */
+	CheckLogicalDecodingRequirements();
+
+	Assert(!MyReplicationSlot);
+
+	ReplicationSlotAcquire(cmd->slotname);
+
+	/*
+	 * Force a disconnect, so that the decoding code doesn't need to care
+	 * about a eventual switch from running in recovery, to running in a
+	 * normal environment. Client code is expected to handle reconnects.
+	 */
+	if (am_cascading_walsender && !RecoveryInProgress())
+	{
+		ereport(LOG,
+				(errmsg("terminating walsender process after promotion.")));
+		walsender_ready_to_stop = true;
+	}
+
+	WalSndSetState(WALSNDSTATE_CATCHUP);
+
+	/* Send a CopyBothResponse message, and start streaming */
+	pq_beginmessage(&buf, 'W');
+	pq_sendbyte(&buf, 0);
+	pq_sendint(&buf, 0, 2);
+	pq_endmessage(&buf);
+	pq_flush();
+
+	/* setup state for XLogReadPage */
+	sendTimeLineIsHistoric = false;
+	sendTimeLine = ThisTimeLineID;
+
+	/*
+	 * Initialize position to the last ack'ed one, then the xlog records begin
+	 * to be shipped from that position.
+	 */
+	logical_decoding_ctx = CreateDecodingContext(
+		cmd->startpoint, cmd->options,
+		logical_read_xlog_page,
+		WalSndPrepareWrite, WalSndWriteData);
+
+	/* Start reading WAL from the oldest required WAL. */
+	logical_startptr = MyReplicationSlot->data.restart_lsn;
+
+	/*
+	 * Report the location after which we'll send out further commits as the
+	 * current sentPtr.
+	 */
+	sentPtr = MyReplicationSlot->data.confirmed_flush;
+
+	/* Also update the sent position status in shared memory */
+	{
+		/* use volatile pointer to prevent code rearrangement */
+		volatile WalSnd *walsnd = MyWalSnd;
+
+		SpinLockAcquire(&walsnd->mutex);
+		walsnd->sentPtr = MyReplicationSlot->data.restart_lsn;
+		SpinLockRelease(&walsnd->mutex);
+	}
+
+	replication_active = true;
+
+	SyncRepInitConfig();
+
+	/* Main loop of walsender */
+	WalSndLoop(XLogSendLogical);
+
+	FreeDecodingContext(logical_decoding_ctx);
+	ReplicationSlotRelease();
+
+	replication_active = false;
+	if (walsender_ready_to_stop)
+		proc_exit(0);
+	WalSndSetState(WALSNDSTATE_STARTUP);
+
+	/* Get out of COPY mode (CommandComplete). */
+	EndCommand("COPY 0", DestRemote);
+}
+
+/*
+ * LogicalDecodingContext 'prepare_write' callback.
+ *
+ * Prepare a write into a StringInfo.
+ *
+ * Don't do anything lasting in here, it's quite possible that nothing will done
+ * with the data.
+ */
+static void
+WalSndPrepareWrite(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid, bool last_write)
+{
+	/* can't have sync rep confused by sending the same LSN several times */
+	if (!last_write)
+		lsn = InvalidXLogRecPtr;
+
+	resetStringInfo(ctx->out);
+
+	pq_sendbyte(ctx->out, 'w');
+	pq_sendint64(ctx->out, lsn);	/* dataStart */
+	pq_sendint64(ctx->out, lsn);	/* walEnd */
+	/*
+	 * Fill out the sendtime later, just as it's done in XLogSendPhysical, but
+	 * reserve space here.
+	 */
+	pq_sendint64(ctx->out, 0);		/* sendtime */
+}
+
+/*
+ * LogicalDecodingContext 'write' callback.
+ *
+ * Actually write out data previously prepared by WalSndPrepareWrite out to
+ * the network. Take as long as needed, but process replies from the other
+ * side and check timeouts during that.
+ */
+static void
+WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
+				bool last_write)
+{
+	/* output previously gathered data in a CopyData packet */
+	pq_putmessage_noblock('d', ctx->out->data, ctx->out->len);
+
+	/*
+	 * Fill the send timestamp last, so that it is taken as late as
+	 * possible. This is somewhat ugly, but the protocol's set as it's already
+	 * used for several releases by streaming physical replication.
+	 */
+	resetStringInfo(&tmpbuf);
+	pq_sendint64(&tmpbuf, GetCurrentIntegerTimestamp());
+	memcpy(&ctx->out->data[1 + sizeof(int64) + sizeof(int64)],
+		   tmpbuf.data, sizeof(int64));
+
+	/* fast path */
+	/* Try to flush pending output to the client */
+	if (pq_flush_if_writable() != 0)
+		WalSndShutdown();
+
+	if (!pq_is_send_pending())
+		return;
+
+	for (;;)
+	{
+		int			wakeEvents;
+		long		sleeptime;
+		TimestampTz	now;
+
+		/*
+		 * Emergency bailout if postmaster has died.  This is to avoid the
+		 * necessity for manual cleanup of all postmaster children.
+		 */
+		if (!PostmasterIsAlive())
+			exit(1);
+
+		/* Process any requests or signals received recently */
+		if (got_SIGHUP)
+		{
+			got_SIGHUP = false;
+			ProcessConfigFile(PGC_SIGHUP);
+			SyncRepInitConfig();
+		}
+
+		/* Check for input from the client */
+		ProcessRepliesIfAny();
+
+		/* Clear any already-pending wakeups */
+		ResetLatch(&MyWalSnd->latch);
+
+		/* Try to flush pending output to the client */
+		if (pq_flush_if_writable() != 0)
+			WalSndShutdown();
+
+		/* If we finished clearing the buffered data, we're done here. */
+		if (!pq_is_send_pending())
+			break;
+
+		now = GetCurrentTimestamp();
+
+		/* die if timeout was reached */
+		WalSndCheckTimeOut(now);
+
+		/* Send keepalive if the time has come */
+		WalSndKeepaliveIfNecessary(now);
+
+		sleeptime = WalSndComputeSleeptime(now);
+
+		wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH |
+			WL_SOCKET_WRITEABLE | WL_SOCKET_READABLE | WL_TIMEOUT;
+
+		/* Sleep until something happens or we time out */
+		ImmediateInterruptOK = true;
+		CHECK_FOR_INTERRUPTS();
+		WaitLatchOrSocket(&MyWalSnd->latch, wakeEvents,
+						  MyProcPort->sock, sleeptime);
+		ImmediateInterruptOK = false;
+	}
+
+	/* reactivate latch so WalSndLoop knows to continue */
+	SetLatch(&MyWalSnd->latch);
+}
+
+/*
+ * Wait till WAL < loc is flushed to disk so it can be safely read.
+ */
+static XLogRecPtr
+WalSndWaitForWal(XLogRecPtr loc)
+{
+	int			wakeEvents;
+	static XLogRecPtr RecentFlushPtr = InvalidXLogRecPtr;
+
+
+	/*
+	 * Fast path to avoid acquiring the spinlock in the we already know we
+	 * have enough WAL available. This is particularly interesting if we're
+	 * far behind.
+	 */
+	if (RecentFlushPtr != InvalidXLogRecPtr &&
+		loc <= RecentFlushPtr)
+		return RecentFlushPtr;
+
+	/* Get a more recent flush pointer. */
+	if (!RecoveryInProgress())
+		RecentFlushPtr = GetFlushRecPtr();
+	else
+		RecentFlushPtr = GetXLogReplayRecPtr(NULL);
+
+	for (;;)
+	{
+		long		sleeptime;
+		TimestampTz	now;
+
+		/*
+		 * Emergency bailout if postmaster has died.  This is to avoid the
+		 * necessity for manual cleanup of all postmaster children.
+		 */
+		if (!PostmasterIsAlive())
+			exit(1);
+
+		/* Process any requests or signals received recently */
+		if (got_SIGHUP)
+		{
+			got_SIGHUP = false;
+			ProcessConfigFile(PGC_SIGHUP);
+			SyncRepInitConfig();
+		}
+
+		/* Check for input from the client */
+		ProcessRepliesIfAny();
+
+		/* Clear any already-pending wakeups */
+		ResetLatch(&MyWalSnd->latch);
+
+		/* Update our idea of the currently flushed position. */
+		if (!RecoveryInProgress())
+			RecentFlushPtr = GetFlushRecPtr();
+		else
+			RecentFlushPtr = GetXLogReplayRecPtr(NULL);
+
+		/*
+		 * If postmaster asked us to stop, don't wait here anymore. This will
+		 * cause the xlogreader to return without reading a full record, which
+		 * is the fastest way to reach the mainloop which then can quit.
+		 *
+		 * It's important to do this check after the recomputation of
+		 * RecentFlushPtr, so we can send all remaining data before shutting
+		 * down.
+		 */
+		if (walsender_ready_to_stop)
+			break;
+
+		/*
+		 * We only send regular messages to the client for full decoded
+		 * transactions, but a synchronous replication and walsender shutdown
+		 * possibly are waiting for a later location. So we send pings
+		 * containing the flush location every now and then.
+		 */
+		if (MyWalSnd->flush < sentPtr && !waiting_for_ping_response)
+		{
+			WalSndKeepalive(true);
+			waiting_for_ping_response = true;
+		}
+
+		/* check whether we're done */
+		if (loc <= RecentFlushPtr)
+			break;
+
+		/* Waiting for new WAL. Since we need to wait, we're now caught up. */
+		WalSndCaughtUp = true;
+
+		/*
+		 * Try to flush pending output to the client. Also wait for the socket
+		 * becoming writable, if there's still pending output after an attempt
+		 * to flush. Otherwise we might just sit on output data while waiting
+		 * for new WAL being generated.
+		 */
+		if (pq_flush_if_writable() != 0)
+			WalSndShutdown();
+
+		now = GetCurrentTimestamp();
+
+		/* die if timeout was reached */
+		WalSndCheckTimeOut(now);
+
+		/* Send keepalive if the time has come */
+		WalSndKeepaliveIfNecessary(now);
+
+		sleeptime = WalSndComputeSleeptime(now);
+
+		wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH |
+			WL_SOCKET_READABLE | WL_TIMEOUT;
+
+		if (pq_is_send_pending())
+			wakeEvents |= WL_SOCKET_WRITEABLE;
+
+		/* Sleep until something happens or we time out */
+		ImmediateInterruptOK = true;
+		CHECK_FOR_INTERRUPTS();
+		WaitLatchOrSocket(&MyWalSnd->latch, wakeEvents,
+						  MyProcPort->sock, sleeptime);
+		ImmediateInterruptOK = false;
+	}
+
+	/* reactivate latch so WalSndLoop knows to continue */
+	SetLatch(&MyWalSnd->latch);
+	return RecentFlushPtr;
+}
+
+/*
  * Execute an incoming replication command.
  */
 void
@@ -724,6 +1249,12 @@ exec_replication_command(const char *cmd_string)
 	MemoryContext cmd_context;
 	MemoryContext old_context;
 
+	/*
+	 * CREATE_REPLICATION_SLOT ... LOGICAL exports a snapshot until the next
+	 * command arrives. Clean up the old stuff if there's anything.
+	 */
+	SnapBuildClearExportedSnapshot();
+
 	elog(DEBUG1, "received replication command: %s", cmd_string);
 
 	CHECK_FOR_INTERRUPTS();
@@ -769,7 +1300,7 @@ exec_replication_command(const char *cmd_string)
 				if (cmd->kind == REPLICATION_KIND_PHYSICAL)
 					StartReplication(cmd);
 				else
-					elog(ERROR, "cannot handle logical decoding yet");
+					StartLogicalReplication(cmd);
 				break;
 			}
 
@@ -887,7 +1418,7 @@ ProcessRepliesIfAny(void)
 	if (received)
 	{
 		last_reply_timestamp = GetCurrentTimestamp();
-		ping_sent = false;
+		waiting_for_ping_response = false;
 	}
 }
 
@@ -1020,7 +1551,7 @@ ProcessStandbyReplyMessage(void)
 	if (MyReplicationSlot && flushPtr != InvalidXLogRecPtr)
 	{
 		if (MyReplicationSlot->data.database != InvalidOid)
-			elog(ERROR, "cannot handle logical decoding yet");
+			LogicalConfirmReceivedLocation(flushPtr);
 		else
 			PhysicalConfirmReceivedLocation(flushPtr);
 	}
@@ -1146,12 +1677,81 @@ ProcessStandbyHSFeedbackMessage(void)
 		MyPgXact->xmin = feedbackXmin;
 }
 
-/* Main loop of walsender process that streams the WAL over Copy messages. */
+/*
+ * Compute how long send/receive loops should sleep.
+ *
+ * If wal_sender_timeout is enabled we want to wake up in time to send
+ * keepalives and to abort the connection if wal_sender_timeout has been
+ * reached.
+ */
+static long
+WalSndComputeSleeptime(TimestampTz now)
+{
+	long		sleeptime = 10000;		/* 10 s */
+
+	if (wal_sender_timeout > 0)
+	{
+		TimestampTz wakeup_time;
+		long sec_to_timeout;
+		int microsec_to_timeout;
+
+		/*
+		 * At the latest stop sleeping once wal_sender_timeout has been
+		 * reached.
+		 */
+		wakeup_time = TimestampTzPlusMilliseconds(last_reply_timestamp,
+												  wal_sender_timeout);
+
+		/*
+		 * If no ping has been sent yet, wakeup when it's time to do
+		 * so. WalSndKeepaliveIfNecessary() wants to send a keepalive once
+		 * half of the timeout passed without a response.
+		 */
+		if (!waiting_for_ping_response)
+			wakeup_time = TimestampTzPlusMilliseconds(last_reply_timestamp,
+													wal_sender_timeout / 2);
+
+		/* Compute relative time until wakeup. */
+		TimestampDifference(now, wakeup_time,
+							&sec_to_timeout, &microsec_to_timeout);
+
+		sleeptime = sec_to_timeout * 1000 +
+			microsec_to_timeout / 1000;
+	}
+
+	return sleeptime;
+}
+
+/*
+ * Check whether there have been responses by the client within
+ * wal_sender_timeout and shutdown if not.
+ */
 static void
-WalSndLoop(void)
+WalSndCheckTimeOut(TimestampTz now)
 {
-	bool		caughtup = false;
+	TimestampTz timeout;
+
+	timeout = TimestampTzPlusMilliseconds(last_reply_timestamp,
+										  wal_sender_timeout);
 
+	if (wal_sender_timeout > 0 && now >= timeout)
+	{
+		/*
+		 * Since typically expiration of replication timeout means
+		 * communication problem, we don't send the error message to
+		 * the standby.
+		 */
+		ereport(COMMERROR,
+				(errmsg("terminating walsender process due to replication timeout")));
+
+		WalSndShutdown();
+	}
+}
+
+/* Main loop of walsender process that streams the WAL over Copy messages. */
+static void
+WalSndLoop(WalSndSendDataCallback send_data)
+{
 	/*
 	 * Allocate buffers that will be used for each outgoing and incoming
 	 * message.  We do this just once to reduce palloc overhead.
@@ -1162,7 +1762,7 @@ WalSndLoop(void)
 
 	/* Initialize the last reply timestamp */
 	last_reply_timestamp = GetCurrentTimestamp();
-	ping_sent = false;
+	waiting_for_ping_response = false;
 
 	/*
 	 * Loop until we reach the end of this timeline or the client requests to
@@ -1170,8 +1770,7 @@ WalSndLoop(void)
 	 */
 	for (;;)
 	{
-		/* Clear any already-pending wakeups */
-		ResetLatch(&MyWalSnd->latch);
+		TimestampTz	now;
 
 		/*
 		 * Emergency bailout if postmaster has died.  This is to avoid the
@@ -1193,6 +1792,9 @@ WalSndLoop(void)
 		/* Check for input from the client */
 		ProcessRepliesIfAny();
 
+		/* Clear any already-pending wakeups */
+		ResetLatch(&MyWalSnd->latch);
+
 		/*
 		 * If we have received CopyDone from the client, sent CopyDone
 		 * ourselves, and the output buffer is empty, it's time to exit
@@ -1203,21 +1805,21 @@ WalSndLoop(void)
 
 		/*
 		 * If we don't have any pending data in the output buffer, try to send
-		 * some more.  If there is some, we don't bother to call XLogSend
+		 * some more.  If there is some, we don't bother to call send_data
 		 * again until we've flushed it ... but we'd better assume we are not
 		 * caught up.
 		 */
 		if (!pq_is_send_pending())
-			XLogSend(&caughtup);
+			send_data();
 		else
-			caughtup = false;
+			WalSndCaughtUp = false;
 
 		/* Try to flush pending output to the client */
 		if (pq_flush_if_writable() != 0)
-			goto send_failure;
+			WalSndShutdown();
 
 		/* If nothing remains to be sent right now ... */
-		if (caughtup && !pq_is_send_pending())
+		if (WalSndCaughtUp && !pq_is_send_pending())
 		{
 			/*
 			 * If we're in catchup state, move to streaming.  This is an
@@ -1243,111 +1845,47 @@ WalSndLoop(void)
 			 * the walsender is not sure which.
 			 */
 			if (walsender_ready_to_stop)
-			{
-				/* ... let's just be real sure we're caught up ... */
-				XLogSend(&caughtup);
-				if (caughtup && sentPtr == MyWalSnd->flush &&
-					!pq_is_send_pending())
-				{
-					/* Inform the standby that XLOG streaming is done */
-					EndCommand("COPY 0", DestRemote);
-					pq_flush();
-
-					proc_exit(0);
-				}
-			}
+				WalSndDone(send_data);
 		}
 
-		/*
-		 * If half of wal_sender_timeout has elapsed without receiving any
-		 * reply from standby, send a keep-alive message requesting an
-		 * immediate reply.
-		 */
-		if (wal_sender_timeout > 0 && !ping_sent)
-		{
-			TimestampTz timeout;
+		now = GetCurrentTimestamp();
 
-			timeout = TimestampTzPlusMilliseconds(last_reply_timestamp,
-												  wal_sender_timeout / 2);
-			if (GetCurrentTimestamp() >= timeout)
-			{
-				WalSndKeepalive(true);
-				ping_sent = true;
-				/* Try to flush pending output to the client */
-				if (pq_flush_if_writable() != 0)
-					goto send_failure;
-			}
-		}
+		/* Check for replication timeout. */
+		WalSndCheckTimeOut(now);
+
+		/* Send keepalive if the time has come */
+		WalSndKeepaliveIfNecessary(now);
 
 		/*
 		 * We don't block if not caught up, unless there is unsent data
 		 * pending in which case we'd better block until the socket is
-		 * write-ready.  This test is only needed for the case where XLogSend
-		 * loaded a subset of the available data but then pq_flush_if_writable
-		 * flushed it all --- we should immediately try to send more.
+		 * write-ready.  This test is only needed for the case where the
+		 * send_data callback handled a subset of the available data but then
+		 * pq_flush_if_writable flushed it all --- we should immediately try
+		 * to send more.
 		 */
-		if ((caughtup && !streamingDoneSending) || pq_is_send_pending())
+		if ((WalSndCaughtUp && !streamingDoneSending) || pq_is_send_pending())
 		{
-			TimestampTz timeout;
-			long		sleeptime = 10000;		/* 10 s */
+			long		sleeptime;
 			int			wakeEvents;
 
 			wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_TIMEOUT |
 				WL_SOCKET_READABLE;
 
+			sleeptime = WalSndComputeSleeptime(now);
+
 			if (pq_is_send_pending())
 				wakeEvents |= WL_SOCKET_WRITEABLE;
 
-			/*
-			 * If wal_sender_timeout is active, sleep in smaller increments
-			 * to not go over the timeout too much. XXX: Why not just sleep
-			 * until the timeout has elapsed?
-			 */
-			if (wal_sender_timeout > 0)
-				sleeptime = 1 + (wal_sender_timeout / 10);
-
 			/* Sleep until something happens or we time out */
 			ImmediateInterruptOK = true;
 			CHECK_FOR_INTERRUPTS();
 			WaitLatchOrSocket(&MyWalSnd->latch, wakeEvents,
 							  MyProcPort->sock, sleeptime);
 			ImmediateInterruptOK = false;
-
-			/*
-			 * Check for replication timeout.  Note we ignore the corner case
-			 * possibility that the client replied just as we reached the
-			 * timeout ... he's supposed to reply *before* that.
-			 */
-			timeout = TimestampTzPlusMilliseconds(last_reply_timestamp,
-												  wal_sender_timeout);
-			if (wal_sender_timeout > 0 && GetCurrentTimestamp() >= timeout)
-			{
-				/*
-				 * Since typically expiration of replication timeout means
-				 * communication problem, we don't send the error message to
-				 * the standby.
-				 */
-				ereport(COMMERROR,
-						(errmsg("terminating walsender process due to replication timeout")));
-				goto send_failure;
-			}
 		}
 	}
 	return;
-
-send_failure:
-
-	/*
-	 * Get here on send failure.  Clean up and exit.
-	 *
-	 * Reset whereToSendOutput to prevent ereport from attempting to send any
-	 * more messages to the standby.
-	 */
-	if (whereToSendOutput == DestRemote)
-		whereToSendOutput = DestNone;
-
-	proc_exit(0);
-	abort();					/* keep the compiler quiet */
 }
 
 /* Initialize a per-walsender data structure for this walsender process */
@@ -1605,15 +2143,17 @@ retry:
 }
 
 /*
+ * Send out the WAL in its normal physical/stored form.
+ *
  * Read up to MAX_SEND_SIZE bytes of WAL that's been flushed to disk,
  * but not yet sent to the client, and buffer it in the libpq output
  * buffer.
  *
- * If there is no unsent WAL remaining, *caughtup is set to true, otherwise
- * *caughtup is set to false.
+ * If there is no unsent WAL remaining, WalSndCaughtUp is set to true,
+ * otherwise WalSndCaughtUp is set to false.
  */
 static void
-XLogSend(bool *caughtup)
+XLogSendPhysical(void)
 {
 	XLogRecPtr	SendRqstPtr;
 	XLogRecPtr	startptr;
@@ -1622,7 +2162,7 @@ XLogSend(bool *caughtup)
 
 	if (streamingDoneSending)
 	{
-		*caughtup = true;
+		WalSndCaughtUp = true;
 		return;
 	}
 
@@ -1739,7 +2279,7 @@ XLogSend(bool *caughtup)
 		pq_putmessage_noblock('c', NULL, 0);
 		streamingDoneSending = true;
 
-		*caughtup = true;
+		WalSndCaughtUp = true;
 
 		elog(DEBUG1, "walsender reached end of timeline at %X/%X (sent up to %X/%X)",
 			 (uint32) (sendTimeLineValidUpto >> 32), (uint32) sendTimeLineValidUpto,
@@ -1751,7 +2291,7 @@ XLogSend(bool *caughtup)
 	Assert(sentPtr <= SendRqstPtr);
 	if (SendRqstPtr <= sentPtr)
 	{
-		*caughtup = true;
+		WalSndCaughtUp = true;
 		return;
 	}
 
@@ -1775,15 +2315,15 @@ XLogSend(bool *caughtup)
 	{
 		endptr = SendRqstPtr;
 		if (sendTimeLineIsHistoric)
-			*caughtup = false;
+			WalSndCaughtUp = false;
 		else
-			*caughtup = true;
+			WalSndCaughtUp = true;
 	}
 	else
 	{
 		/* round down to page boundary. */
 		endptr -= (endptr % XLOG_BLCKSZ);
-		*caughtup = false;
+		WalSndCaughtUp = false;
 	}
 
 	nbytes = endptr - startptr;
@@ -1844,6 +2384,85 @@ XLogSend(bool *caughtup)
 }
 
 /*
+ * Stream out logically decoded data.
+ */
+static void
+XLogSendLogical(void)
+{
+	XLogRecord *record;
+	char	   *errm;
+
+	/*
+	 * Don't know whether we've caught up yet. We'll set it to true in
+	 * WalSndWaitForWal, if we're actually waiting. We also set to true if
+	 * XLogReadRecord() had to stop reading but WalSndWaitForWal didn't wait -
+	 * i.e. when we're shutting down.
+	 */
+	WalSndCaughtUp = false;
+
+	record = XLogReadRecord(logical_decoding_ctx->reader, logical_startptr, &errm);
+	logical_startptr = InvalidXLogRecPtr;
+
+	/* xlog record was invalid */
+	if (errm != NULL)
+		elog(ERROR, "%s", errm);
+
+	if (record != NULL)
+	{
+		LogicalDecodingProcessRecord(logical_decoding_ctx, record);
+
+		sentPtr = logical_decoding_ctx->reader->EndRecPtr;
+	}
+	else
+	{
+		/*
+		 * If the record we just wanted read is at or beyond the flushed point,
+		 * then we're caught up.
+		 */
+		if (logical_decoding_ctx->reader->EndRecPtr >= GetFlushRecPtr())
+			WalSndCaughtUp = true;
+	}
+
+	/* Update shared memory status */
+	{
+		/* use volatile pointer to prevent code rearrangement */
+		volatile WalSnd *walsnd = MyWalSnd;
+
+		SpinLockAcquire(&walsnd->mutex);
+		walsnd->sentPtr = sentPtr;
+		SpinLockRelease(&walsnd->mutex);
+	}
+}
+
+/*
+ * Shutdown if the sender is caught up.
+ *
+ * NB: This should only be called when the shutdown signal has been received
+ * from postmaster.
+ *
+ * Note that if we determine that there's still more data to send, this
+ * function will return control to the caller.
+ */
+static void
+WalSndDone(WalSndSendDataCallback send_data)
+{
+	/* ... let's just be real sure we're caught up ... */
+	send_data();
+
+	if (WalSndCaughtUp && sentPtr == MyWalSnd->flush &&
+		!pq_is_send_pending())
+	{
+		/* Inform the standby that XLOG streaming is done */
+		EndCommand("COPY 0", DestRemote);
+		pq_flush();
+
+		proc_exit(0);
+	}
+	if (!waiting_for_ping_response)
+		WalSndKeepalive(true);
+}
+
+/*
  * Returns the latest point in WAL that has been safely flushed to disk, and
  * can be sent to the standby. This should only be called when in recovery,
  * ie. we're streaming to a cascaded standby.
@@ -2239,6 +2858,39 @@ WalSndKeepalive(bool requestReply)
 }
 
 /*
+ * Send keepalive message if close enough to a shutdown due to
+ * wal_sender_timeout.
+ */
+static void
+WalSndKeepaliveIfNecessary(TimestampTz now)
+{
+	TimestampTz ping_time;
+
+	if (wal_sender_timeout <= 0)
+		return;
+
+	if (waiting_for_ping_response)
+		return;
+
+	/*
+	 * If half of wal_sender_timeout has lapsed without receiving any reply
+	 * from the standby, send a keep-alive message to the standby requesting
+	 * an immediate reply.
+	 */
+	ping_time = TimestampTzPlusMilliseconds(last_reply_timestamp,
+											wal_sender_timeout / 2);
+	if (now >= ping_time)
+	{
+		WalSndKeepalive(true);
+		waiting_for_ping_response = true;
+
+		/* Try to flush pending output to the client */
+		if (pq_flush_if_writable() != 0)
+			WalSndShutdown();
+	}
+}
+
+/*
  * This isn't currently used for anything. Monitoring tools might be
  * interested in the future, and we'll need something like this in the
  * future for synchronous replication.
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 3ecc4d3..89a7c9e 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -729,11 +729,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 				(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
 				 errmsg("remaining connection slots are reserved for non-replication superuser connections")));
 
-	/*
-	 * If walsender, we don't want to connect to any particular database. Just
-	 * finish the backend startup by processing any options from the startup
-	 * packet, and we're done.
-	 */
+	/* Check replication permissions needed for walsender processes. */
 	if (am_walsender)
 	{
 		Assert(!bootstrap);
@@ -742,7 +738,16 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 			ereport(FATAL,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 					 errmsg("must be superuser or replication role to start walsender")));
+	}
 
+	/*
+	 * If this is a plain walsender only supporting physical replication, we
+	 * don't want to connect to any particular database. Just finish the
+	 * backend startup by processing any options from the startup packet, and
+	 * we're done.
+	 */
+	if (am_walsender && !am_db_walsender)
+	{
 		/* process any options passed in the startup packet */
 		if (MyProcPort != NULL)
 			process_startup_options(MyProcPort, am_superuser);
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index 919805f..f93b8c9 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -1639,11 +1639,11 @@ BaseBackup(void)
 				progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
 		disconnect_and_exit(1);
 	}
-	if (PQntuples(res) != 1 || PQnfields(res) != 3)
+	if (PQntuples(res) != 1 || PQnfields(res) < 3)
 	{
 		fprintf(stderr,
-				_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-				progname, PQntuples(res), PQnfields(res), 1, 3);
+				_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+				progname, PQntuples(res), PQnfields(res));
 		disconnect_and_exit(1);
 	}
 	sysidentifier = pg_strdup(PQgetvalue(res, 0, 0));
diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c
index 0f191ce..7ae20d1 100644
--- a/src/bin/pg_basebackup/pg_receivexlog.c
+++ b/src/bin/pg_basebackup/pg_receivexlog.c
@@ -275,11 +275,11 @@ StreamLog(void)
 				progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
 		disconnect_and_exit(1);
 	}
-	if (PQntuples(res) != 1 || PQnfields(res) != 3)
+	if (PQntuples(res) != 1 || PQnfields(res) < 3)
 	{
 		fprintf(stderr,
-				_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-				progname, PQntuples(res), PQnfields(res), 1, 3);
+				_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+				progname, PQntuples(res), PQnfields(res));
 		disconnect_and_exit(1);
 	}
 	servertli = atoi(PQgetvalue(res, 0, 1));
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index ef73b4b..64730d9 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -563,11 +563,11 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 			PQclear(res);
 			return false;
 		}
-		if (PQnfields(res) != 3 || PQntuples(res) != 1)
+		if (PQntuples(res) != 1 || PQnfields(res) < 3)
 		{
 			fprintf(stderr,
-					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-					progname, PQntuples(res), PQnfields(res), 1, 3);
+					_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+					progname, PQntuples(res), PQnfields(res));
 			PQclear(res);
 			return false;
 		}
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
index b67cf63..cff2be6 100644
--- a/src/include/replication/walsender.h
+++ b/src/include/replication/walsender.h
@@ -19,6 +19,7 @@
 /* global state */
 extern bool am_walsender;
 extern bool am_cascading_walsender;
+extern bool am_db_walsender;
 extern bool wake_wal_senders;
 
 /* user-settable parameters */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index f960454..62a892b 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1909,6 +1909,7 @@ WalRcvData
 WalRcvState
 WalSnd
 WalSndCtlData
+WalSndSendDataCallback
 WalSndState
 WholeRowVarExprState
 WindowAgg
-- 
1.8.5.rc2.dirty

#127Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Andres Freund (#126)
Re: Changeset Extraction v7.9.1

Andres Freund escribi�:

fprintf(stderr,
-					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-					progname, PQntuples(res), PQnfields(res), 1, 3);
+					_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+					progname, PQntuples(res), PQnfields(res));

Please don't change this. The reason these messages use %d and an extra
printf argument is to avoid giving translators extra work when the
number of rows or fields is changed. In these cases I suggest this:

-					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-					progname, PQntuples(res), PQnfields(res), 1, 3);
+					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 3);

(Yes, I know the "expected 1 rows" output looks a bit silly. Since this
is an unexpected error message anyway, I don't think that's worth
fixing.)

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#128Andres Freund
andres@2ndquadrant.com
In reply to: Alvaro Herrera (#127)
Re: Changeset Extraction v7.9.1

On 2014-03-07 10:17:21 -0300, Alvaro Herrera wrote:

Andres Freund escribió:

fprintf(stderr,
-					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-					progname, PQntuples(res), PQnfields(res), 1, 3);
+					_("%s: could not identify system: got %d rows and %d fields, expected 1 row and 3 or more fields\n"),
+					progname, PQntuples(res), PQnfields(res));

Please don't change this. The reason these messages use %d and an extra
printf argument is to avoid giving translators extra work when the
number of rows or fields is changed. In these cases I suggest this:

-					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"),
-					progname, PQntuples(res), PQnfields(res), 1, 3);
+					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 3);

(Yes, I know the "expected 1 rows" output looks a bit silly. Since this
is an unexpected error message anyway, I don't think that's worth
fixing.)

I changed it to not use placeholders because I thought "or more" was
specific enough to be unlikely to be used in other places, but I don't
have a problem with continuing to use them.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#129Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#126)
Re: Changeset Extraction v7.9.1

On Fri, Mar 7, 2014 at 7:44 AM, Andres Freund <andres@2ndquadrant.com> wrote:

I've attached a new version of the walsender patch. It's been rebased
ontop of Heikki's latest commit to walsender.c. I've changed a fair bit
of stuff:
* The sleeptime is now computed to sleep until we either need to send a
keepalive or kill ourselves, as Heikki sugggested.
* Sleep time computation, sending pings, checking timeouts is now done
in separate functions.
* Comment and codestyle improvements.

Although they are shorter and simpler now, I have not managed to unify
the three loops however. They seem to be too different to unify them
inside one. I tried a common function with an 'wait_for' bitmask
argument, but that turned out to be fairly illegible. The checks in
WalSndWaitForWal() and WalSndLoop() just seem to be too different.

I'd be grateful if you (or somebody else!) could have a quick look at
body of the loops in WalSndWriteData(), WalSndWaitForWal() and
WalSndLoop(). Maybe I am just staring at it the wrong way.

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#130Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Robert Haas (#129)
Re: Changeset Extraction v7.9.1

Robert Haas escribi�:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Hmm, is the buildfarm exercising any of this?

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#131Robert Haas
robertmhaas@gmail.com
In reply to: Alvaro Herrera (#130)
Re: Changeset Extraction v7.9.1

On Mon, Mar 10, 2014 at 3:33 PM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Robert Haas escribió:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Hmm, is the buildfarm exercising any of this?

I think it isn't, apart from whether it builds. Apparently the
buildfarm only runs installcheck on contrib, not check. And the
test_decoding plugin only runs under installcheck, not check. Also,
it's not going to test walsender/walreceiver at all, but that's harder
to fix.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#132Andres Freund
andres@2ndquadrant.com
In reply to: Alvaro Herrera (#130)
Re: Changeset Extraction v7.9.1

Hi,

On 2014-03-10 16:33:33 -0300, Alvaro Herrera wrote:

Robert Haas escribió:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Hmm, is the buildfarm exercising any of this?

Not sufficiently yet, no. The logical decoding facilities themselves are
actually covered by tests in contrib/test_decoding, but due to the
issues mentioned in 20140303224325.GJ17253@awork2.anarazel.de they
aren't run.
The walsender interface isn't tested at all. Be it new or old
functionality. I have some hopes for Peter's client test patches
there...

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#133Josh Berkus
josh@agliodbs.com
In reply to: Andres Freund (#1)
Re: Changeset Extraction v7.9.1

On 03/10/2014 11:54 AM, Robert Haas wrote:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Wait, does this mean Changesets is committed? Or only part of it?

--
Josh Berkus
PostgreSQL Experts Inc.
http://pgexperts.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#134Andres Freund
andres@2ndquadrant.com
In reply to: Josh Berkus (#133)
Re: Changeset Extraction v7.9.1

On 2014-03-10 12:38:42 -0700, Josh Berkus wrote:

On 03/10/2014 11:54 AM, Robert Haas wrote:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Wait, does this mean Changesets is committed? Or only part of it?

The docs and pg_recvlogical aren't yet, everything else is. Working on
rebasing/copy-editing the former two right now.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#135Robert Haas
robertmhaas@gmail.com
In reply to: Josh Berkus (#133)
Re: Changeset Extraction v7.9.1

On Mon, Mar 10, 2014 at 3:38 PM, Josh Berkus <josh@agliodbs.com> wrote:

On 03/10/2014 11:54 AM, Robert Haas wrote:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Wait, does this mean Changesets is committed? Or only part of it?

The core of the feature was b89e151054a05f0f6d356ca52e3b725dd0505e53,
but that only allowed it through the SQL interface. The new commit,
8722017bbcbc95e311bbaa6d21cd028e296e5e35, makes it available via
walsender interface. There isn't a client for that interface yet, but
if you're wondering whether it's time to break out the champagne, I'm
thinking probably.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#136Josh Berkus
josh@agliodbs.com
In reply to: Andres Freund (#1)
Re: Changeset Extraction v7.9.1

On 03/10/2014 12:46 PM, Robert Haas wrote:

On Mon, Mar 10, 2014 at 3:38 PM, Josh Berkus <josh@agliodbs.com> wrote:

On 03/10/2014 11:54 AM, Robert Haas wrote:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Wait, does this mean Changesets is committed? Or only part of it?

The core of the feature was b89e151054a05f0f6d356ca52e3b725dd0505e53,
but that only allowed it through the SQL interface. The new commit,
8722017bbcbc95e311bbaa6d21cd028e296e5e35, makes it available via
walsender interface. There isn't a client for that interface yet, but
if you're wondering whether it's time to break out the champagne, I'm
thinking probably.

Yeah, that's my thoughts. Although I might wait for recvlogical. Will
put documentation wordsmithing on my todo list once Andres commits.

--
Josh Berkus
PostgreSQL Experts Inc.
http://pgexperts.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#137Robert Haas
robertmhaas@gmail.com
In reply to: Josh Berkus (#136)
Re: Changeset Extraction v7.9.1

On Mon, Mar 10, 2014 at 4:55 PM, Josh Berkus <josh@agliodbs.com> wrote:

On 03/10/2014 12:46 PM, Robert Haas wrote:

On Mon, Mar 10, 2014 at 3:38 PM, Josh Berkus <josh@agliodbs.com> wrote:

On 03/10/2014 11:54 AM, Robert Haas wrote:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Wait, does this mean Changesets is committed? Or only part of it?

The core of the feature was b89e151054a05f0f6d356ca52e3b725dd0505e53,
but that only allowed it through the SQL interface. The new commit,
8722017bbcbc95e311bbaa6d21cd028e296e5e35, makes it available via
walsender interface. There isn't a client for that interface yet, but
if you're wondering whether it's time to break out the champagne, I'm
thinking probably.

Yeah, that's my thoughts. Although I might wait for recvlogical. Will
put documentation wordsmithing on my todo list once Andres commits.

Is this your way of announcing that Andres is getting a commit bit, or
did you just mis-speak?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#138Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Robert Haas (#131)
Re: Changeset Extraction v7.9.1

Robert Haas escribi�:

On Mon, Mar 10, 2014 at 3:33 PM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Robert Haas escribi�:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Hmm, is the buildfarm exercising any of this?

I think it isn't, apart from whether it builds. Apparently the
buildfarm only runs installcheck on contrib, not check. And the
test_decoding plugin only runs under installcheck, not check. Also,
it's not going to test walsender/walreceiver at all, but that's harder
to fix.

So the buildfarm exercises pg_upgrade, to some extent, by way of a
custom module,
https://github.com/PGBuildFarm/client-code/blob/master/PGBuild/Modules/TestUpgrade.pm
As far as I can tell, test_decoding wants to do the same thing (i.e. get
make check to run). Is the best option to write a new TestLogical.pm
module for the buildfarm, or should we somehow think about how to
generalize the pg_upgrade trick so that animal caretakers can enable
runs of test_decoding by simply upgrading to a newer version of the
buildfarm script?

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#139Josh Berkus
josh@agliodbs.com
In reply to: Andres Freund (#1)
Re: Changeset Extraction v7.9.1

On 03/10/2014 02:08 PM, Robert Haas wrote:

On Mon, Mar 10, 2014 at 4:55 PM, Josh Berkus <josh@agliodbs.com> wrote:

Yeah, that's my thoughts. Although I might wait for recvlogical. Will
put documentation wordsmithing on my todo list once Andres commits.

Is this your way of announcing that Andres is getting a commit bit, or
did you just mis-speak?

Hah. No, I have no such knowledge. I was using "commit" as in the git
sense, as in "commits to his fork".

--
Josh Berkus
PostgreSQL Experts Inc.
http://pgexperts.com

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#140Andres Freund
andres@2ndquadrant.com
In reply to: Josh Berkus (#136)
5 attachment(s)
Re: Changeset Extraction v7.9.1

On 2014-03-10 13:55:53 -0700, Josh Berkus wrote:

On 03/10/2014 12:46 PM, Robert Haas wrote:

On Mon, Mar 10, 2014 at 3:38 PM, Josh Berkus <josh@agliodbs.com> wrote:

On 03/10/2014 11:54 AM, Robert Haas wrote:

I've committed this patch now with a few further tweaks, leaving this
issue unaddressed. It may well be something that needs improvement,
but I don't think it's a big enough issue to justify holding back a
commit.

Wait, does this mean Changesets is committed? Or only part of it?

The core of the feature was b89e151054a05f0f6d356ca52e3b725dd0505e53,
but that only allowed it through the SQL interface. The new commit,
8722017bbcbc95e311bbaa6d21cd028e296e5e35, makes it available via
walsender interface. There isn't a client for that interface yet, but
if you're wondering whether it's time to break out the champagne, I'm
thinking probably.

Yeah, that's my thoughts. Although I might wait for recvlogical. Will
put documentation wordsmithing on my todo list once Andres commits.

Heh, as Robert observed, no can do...

Attached are the collected remaining patches. The docs might need
further additions, but it seems better to add them now.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-Fix-typo-in-Assert-statement-causing-SetTransactionS.patchtext/x-patch; charset=us-asciiDownload
>From 8dffe024d861fd87373b962237f26caf403fe343 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 21:20:56 +0100
Subject: [PATCH 1/7] Fix typo in Assert() statement causing
 SetTransactionSnapshot() to fail.

Also fix comment that hasn't got the message about removing the need
for temporarily suspending historical snapshots.
---
 src/backend/utils/time/snapmgr.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 4146527..9802fa7 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -261,9 +261,11 @@ Snapshot
 GetCatalogSnapshot(Oid relid)
 {
 	/*
-	 * Return historic snapshot if we're doing logical decoding, but
-	 * return a non-historic, snapshot if we temporarily are doing up2date
-	 * lookups.
+	 * Return historic snapshot while we're doing logical decoding, so we can
+	 * see the appropriate state of the catalog.
+	 *
+	 * This is the primary reason for needing to reset the system caches after
+	 * finishing decoding.
 	 */
 	if (HistoricSnapshotActive())
 		return HistoricSnapshot;
@@ -352,7 +354,7 @@ SetTransactionSnapshot(Snapshot sourcesnap, TransactionId sourcexid)
 
 	Assert(RegisteredSnapshots == 0);
 	Assert(FirstXactSnapshot == NULL);
-	Assert(HistoricSnapshotActive());
+	Assert(!HistoricSnapshotActive());
 
 	/*
 	 * Even though we are not going to use the snapshot it computes, we must
-- 
1.8.5.rc2.dirty

0002-Add-pg_recvlogical-a-commandline-tool-to-receive-dat.patchtext/x-patch; charset=us-asciiDownload
>From 29e7ff274e156f6ab3b6d6f37b16210e3d67eb7c Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 00:15:39 +0100
Subject: [PATCH 2/7] Add pg_recvlogical, a commandline tool to receive data
 logical decoding data.

Andres Freund
---
 src/bin/pg_basebackup/.gitignore       |   1 +
 src/bin/pg_basebackup/Makefile         |  11 +-
 src/bin/pg_basebackup/nls.mk           |   2 +-
 src/bin/pg_basebackup/pg_recvlogical.c | 875 +++++++++++++++++++++++++++++++++
 src/bin/pg_basebackup/receivelog.c     | 139 +-----
 src/bin/pg_basebackup/receivelog.h     |   2 +
 src/bin/pg_basebackup/streamutil.c     | 123 ++++-
 src/bin/pg_basebackup/streamutil.h     |  10 +
 8 files changed, 1037 insertions(+), 126 deletions(-)
 create mode 100644 src/bin/pg_basebackup/pg_recvlogical.c

diff --git a/src/bin/pg_basebackup/.gitignore b/src/bin/pg_basebackup/.gitignore
index 1334a1f..7abea15 100644
--- a/src/bin/pg_basebackup/.gitignore
+++ b/src/bin/pg_basebackup/.gitignore
@@ -1,2 +1,3 @@
 /pg_basebackup
 /pg_receivexlog
+/pg_recvlogical
diff --git a/src/bin/pg_basebackup/Makefile b/src/bin/pg_basebackup/Makefile
index 17c91af..346560e 100644
--- a/src/bin/pg_basebackup/Makefile
+++ b/src/bin/pg_basebackup/Makefile
@@ -20,7 +20,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
 
 OBJS=receivelog.o streamutil.o $(WIN32RES)
 
-all: pg_basebackup pg_receivexlog
+all: pg_basebackup pg_receivexlog pg_recvlogical
 
 pg_basebackup: pg_basebackup.o $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_basebackup.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
@@ -28,9 +28,13 @@ pg_basebackup: pg_basebackup.o $(OBJS) | submake-libpq submake-libpgport
 pg_receivexlog: pg_receivexlog.o $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_receivexlog.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
+pg_recvlogical: pg_recvlogical.o $(OBJS) | submake-libpq submake-libpgport
+	$(CC) $(CFLAGS) pg_recvlogical.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+
 install: all installdirs
 	$(INSTALL_PROGRAM) pg_basebackup$(X) '$(DESTDIR)$(bindir)/pg_basebackup$(X)'
 	$(INSTALL_PROGRAM) pg_receivexlog$(X) '$(DESTDIR)$(bindir)/pg_receivexlog$(X)'
+	$(INSTALL_PROGRAM) pg_recvlogical$(X) '$(DESTDIR)$(bindir)/pg_recvlogical$(X)'
 
 installdirs:
 	$(MKDIR_P) '$(DESTDIR)$(bindir)'
@@ -38,6 +42,9 @@ installdirs:
 uninstall:
 	rm -f '$(DESTDIR)$(bindir)/pg_basebackup$(X)'
 	rm -f '$(DESTDIR)$(bindir)/pg_receivexlog$(X)'
+	rm -f '$(DESTDIR)$(bindir)/pg_recvlogical$(X)'
 
 clean distclean maintainer-clean:
-	rm -f pg_basebackup$(X) pg_receivexlog$(X) $(OBJS) pg_basebackup.o pg_receivexlog.o
+	rm -f pg_basebackup$(X) pg_receivexlog$(X) pg_recvlogical$(X) \
+		pg_basebackup.o pg_receivexlog.o pg_recvlogical.o \
+		$(OBJS)
diff --git a/src/bin/pg_basebackup/nls.mk b/src/bin/pg_basebackup/nls.mk
index e1c96dd..29df4bc 100644
--- a/src/bin/pg_basebackup/nls.mk
+++ b/src/bin/pg_basebackup/nls.mk
@@ -1,4 +1,4 @@
 # src/bin/pg_basebackup/nls.mk
 CATALOG_NAME     = pg_basebackup
 AVAIL_LANGUAGES  = cs de es fr it ja pl pt_BR ru zh_CN
-GETTEXT_FILES    = pg_basebackup.c pg_receivexlog.c receivelog.c streamutil.c ../../common/fe_memutils.c
+GETTEXT_FILES    = pg_basebackup.c pg_receivexlog.c pg_recvlogical.c receivelog.c streamutil.c ../../common/fe_memutils.c
diff --git a/src/bin/pg_basebackup/pg_recvlogical.c b/src/bin/pg_basebackup/pg_recvlogical.c
new file mode 100644
index 0000000..e733e19
--- /dev/null
+++ b/src/bin/pg_basebackup/pg_recvlogical.c
@@ -0,0 +1,875 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_recvlogical.c - receive data from a logical decoding slot in a streaming fashion
+ *					  and write it to to a local file.
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		  src/bin/pg_basebackup/pg_recvlogical.c
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include "streamutil.h"
+
+#include "getopt_long.h"
+
+#include "libpq-fe.h"
+#include "libpq/pqsignal.h"
+
+#include "access/xlog_internal.h"
+#include "common/fe_memutils.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Time to sleep between reconnection attempts */
+#define RECONNECT_SLEEP_TIME 5
+
+/* Global Options */
+static char    *outfile = NULL;
+static int		verbose = 0;
+static int		noloop = 0;
+static int		standby_message_timeout = 10 * 1000;		/* 10 sec = default */
+static XLogRecPtr startpos = InvalidXLogRecPtr;
+static bool		do_create_slot = false;
+static bool		do_start_slot = false;
+static bool		do_drop_slot = false;
+
+/* filled pairwise with option, value. value may be NULL */
+static char	  **options;
+static size_t	noptions = 0;
+static const char *plugin = "test_decoding";
+
+/* Global State */
+static int		outfd = -1;
+static volatile bool time_to_abort = false;
+
+static void usage(void);
+static void StreamLog();
+static void disconnect_and_exit(int code);
+
+static void
+usage(void)
+{
+	printf(_("%s receives PostgreSQL logical change stream.\n\n"),
+		   progname);
+	printf(_("Usage:\n"));
+	printf(_("  %s [OPTION]...\n"), progname);
+	printf(_("\nOptions:\n"));
+	printf(_("  -f, --file=FILE        receive log into this file. - for stdout\n"));
+	printf(_("  -n, --no-loop          do not loop on connection lost\n"));
+	printf(_("  -v, --verbose          output verbose messages\n"));
+	printf(_("  -V, --version          output version information, then exit\n"));
+	printf(_("  -?, --help             show this help, then exit\n"));
+	printf(_("\nConnection options:\n"));
+	printf(_("  -d, --dbname=DBNAME    database to connect to\n"));
+	printf(_("  -h, --host=HOSTNAME    database server host or socket directory\n"));
+	printf(_("  -p, --port=PORT        database server port number\n"));
+	printf(_("  -U, --username=NAME    connect as specified database user\n"));
+	printf(_("  -w, --no-password      never prompt for password\n"));
+	printf(_("  -W, --password         force password prompt (should happen automatically)\n"));
+	printf(_("\nReplication options:\n"));
+	printf(_("  -o, --option=NAME[=VALUE]\n"
+			 "                         Specify option NAME with optional value VAL, to be passed\n"
+			 "                         to the output plugin\n"));
+	printf(_("  -P, --plugin=PLUGIN    use output plugin PLUGIN (defaults to test_decoding)\n"));
+	printf(_("  -s, --status-interval=INTERVAL\n"
+			 "                         time between status packets sent to server (in seconds)\n"));
+	printf(_("  -S, --slot=SLOT        use existing replication slot SLOT instead of starting a new one\n"));
+	printf(_("  -I, --startpos=PTR     Where in an existing slot should the streaming start"));
+	printf(_("\nAction to be performed:\n"));
+	printf(_("      --create           create a new replication slot (for the slotname see --slot)\n"));
+	printf(_("      --start            start streaming in a replication slot (for the slotname see --slot)\n"));
+	printf(_("      --drop             drop the replication slot (for the slotname see --slot)\n"));
+	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
+}
+
+/*
+ * Send a Standby Status Update message to server.
+ */
+static bool
+sendFeedback(PGconn *conn, XLogRecPtr blockpos, int64 now, bool force, bool replyRequested)
+{
+	char		replybuf[1 + 8 + 8 + 8 + 8 + 1];
+	int			len = 0;
+
+	/*
+	 * we normally don't want to send superflous feedbacks, but if
+	 * it's because of a timeout we need to, otherwise
+	 * replication_timeout will kill us.
+	 */
+	if (blockpos == startpos && !force)
+		return true;
+
+	if (verbose)
+		fprintf(stderr,
+				_("%s: confirming flush up to %X/%X (slot %s)\n"),
+				progname, (uint32) (blockpos >> 32), (uint32) blockpos,
+				replication_slot);
+
+	replybuf[len] = 'r';
+	len += 1;
+	fe_sendint64(blockpos, &replybuf[len]);		/* write */
+	len += 8;
+	fe_sendint64(blockpos, &replybuf[len]);		/* flush */
+	len += 8;
+	fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
+	len += 8;
+	fe_sendint64(now, &replybuf[len]);		/* sendTime */
+	len += 8;
+	replybuf[len] = replyRequested ? 1 : 0;		/* replyRequested */
+	len += 1;
+
+	startpos = blockpos;
+
+	if (PQputCopyData(conn, replybuf, len) <= 0 || PQflush(conn))
+	{
+		fprintf(stderr, _("%s: could not send feedback packet: %s"),
+				progname, PQerrorMessage(conn));
+		return false;
+	}
+
+	return true;
+}
+
+static void
+disconnect_and_exit(int code)
+{
+	if (conn != NULL)
+		PQfinish(conn);
+
+	exit(code);
+}
+
+
+/*
+ * Start the log streaming
+ */
+static void
+StreamLog(void)
+{
+	PGresult   *res;
+	char		query[512];
+	char	   *copybuf = NULL;
+	int64		last_status = -1;
+	XLogRecPtr	logoff = InvalidXLogRecPtr;
+	int			written;
+	int			i;
+
+	/*
+	 * Connect in replication mode to the server
+	 */
+	if (!conn)
+		conn = GetConnection();
+	if (!conn)
+		/* Error message already written in GetConnection() */
+		return;
+
+	/*
+	 * Start the replication
+	 */
+	if (verbose)
+		fprintf(stderr,
+				_("%s: starting log streaming at %X/%X (slot %s)\n"),
+				progname, (uint32) (startpos >> 32), (uint32) startpos,
+				replication_slot);
+
+	/* Initiate the replication stream at specified location */
+	written = snprintf(query, sizeof(query), "START_REPLICATION SLOT \"%s\" LOGICAL %X/%X",
+			 replication_slot, (uint32) (startpos >> 32), (uint32) startpos);
+
+	/*
+	 * add options to string, if present
+	 * Oh, if we just had stringinfo in src/common...
+	 */
+	if (noptions)
+		written += snprintf(query + written, sizeof(query) - written, " (");
+
+	for (i = 0; i < noptions; i++)
+	{
+		/* separator */
+		if (i > 0)
+			written += snprintf(query + written, sizeof(query) - written, ", ");
+
+		/* write option name */
+		written += snprintf(query + written, sizeof(query) - written, "\"%s\"",
+							options[(i * 2)]);
+
+		if (written >= sizeof(query) - 1)
+		{
+			fprintf(stderr, _("%s: option string too long\n"), progname);
+			exit(1); /* no point in retrying, fatal error */
+		}
+
+		/* write option name if specified */
+		if (options[(i * 2) + 1] != NULL)
+		{
+			written += snprintf(query + written, sizeof(query) - written, " '%s'",
+								options[(i * 2) + 1]);
+
+			if (written >= sizeof(query) - 1)
+			{
+				fprintf(stderr, _("%s: option string too long\n"), progname);
+				exit(1); /* no point in retrying, fatal error */
+			}
+		}
+	}
+
+	if (noptions)
+	{
+		written += snprintf(query + written, sizeof(query) - written, ")");
+		if (written >= sizeof(query) - 1)
+		{
+			fprintf(stderr, _("%s: option string too long\n"), progname);
+			exit(1); /* no point in retrying, fatal error */
+		}
+	}
+
+	res = PQexec(conn, query);
+	if (PQresultStatus(res) != PGRES_COPY_BOTH)
+	{
+		fprintf(stderr, _("%s: could not send replication command \"%s\": %s\n"),
+				progname, query, PQresultErrorMessage(res));
+		PQclear(res);
+		goto error;
+	}
+	PQclear(res);
+
+	if (verbose)
+		fprintf(stderr,
+				_("%s: initiated streaming\n"),
+				progname);
+
+	while (!time_to_abort)
+	{
+		int			r;
+		int			bytes_left;
+		int			bytes_written;
+		int64		now;
+		int			hdr_len;
+
+		if (copybuf != NULL)
+		{
+			PQfreemem(copybuf);
+			copybuf = NULL;
+		}
+
+		/*
+		 * Potentially send a status message to the master
+		 */
+		now = feGetCurrentTimestamp();
+		if (standby_message_timeout > 0 &&
+			feTimestampDifferenceExceeds(last_status, now,
+										 standby_message_timeout))
+		{
+			/* Time to send feedback! */
+			if (!sendFeedback(conn, logoff, now, true, false))
+				goto error;
+
+			last_status = now;
+		}
+
+		r = PQgetCopyData(conn, &copybuf, 1);
+		if (r == 0)
+		{
+			/*
+			 * In async mode, and no data available. We block on reading but
+			 * not more than the specified timeout, so that we can send a
+			 * response back to the client.
+			 */
+			fd_set		input_mask;
+			struct timeval timeout;
+			struct timeval *timeoutptr;
+
+			FD_ZERO(&input_mask);
+			FD_SET(PQsocket(conn), &input_mask);
+			if (standby_message_timeout)
+			{
+				int64		targettime;
+				long		secs;
+				int			usecs;
+
+				targettime = last_status + (standby_message_timeout - 1) *
+					((int64) 1000);
+				feTimestampDifference(now,
+									  targettime,
+									  &secs,
+									  &usecs);
+				if (secs <= 0)
+					timeout.tv_sec = 1; /* Always sleep at least 1 sec */
+				else
+					timeout.tv_sec = secs;
+				timeout.tv_usec = usecs;
+				timeoutptr = &timeout;
+			}
+			else
+				timeoutptr = NULL;
+
+			r = select(PQsocket(conn) + 1, &input_mask, NULL, NULL, timeoutptr);
+			if (r == 0 || (r < 0 && errno == EINTR))
+			{
+				/*
+				 * Got a timeout or signal. Continue the loop and either
+				 * deliver a status packet to the server or just go back into
+				 * blocking.
+				 */
+				continue;
+			}
+			else if (r < 0)
+			{
+				fprintf(stderr, _("%s: select() failed: %s\n"),
+						progname, strerror(errno));
+				goto error;
+			}
+			/* Else there is actually data on the socket */
+			if (PQconsumeInput(conn) == 0)
+			{
+				fprintf(stderr,
+						_("%s: could not receive data from WAL stream: %s"),
+						progname, PQerrorMessage(conn));
+				goto error;
+			}
+			continue;
+		}
+		if (r == -1)
+			/* End of copy stream */
+			break;
+		if (r == -2)
+		{
+			fprintf(stderr, _("%s: could not read COPY data: %s"),
+					progname, PQerrorMessage(conn));
+			goto error;
+		}
+
+		/* Check the message type. */
+		if (copybuf[0] == 'k')
+		{
+			int			pos;
+			bool		replyRequested;
+			XLogRecPtr	walEnd;
+
+			/*
+			 * Parse the keepalive message, enclosed in the CopyData message.
+			 * We just check if the server requested a reply, and ignore the
+			 * rest.
+			 */
+			pos = 1;			/* skip msgtype 'k' */
+			walEnd = fe_recvint64(&copybuf[pos]);
+			logoff = Max(walEnd, logoff);
+
+			pos += 8;			/* read walEnd */
+
+			pos += 8;			/* skip sendTime */
+
+			if (r < pos + 1)
+			{
+				fprintf(stderr, _("%s: streaming header too small: %d\n"),
+						progname, r);
+				goto error;
+			}
+			replyRequested = copybuf[pos];
+
+			/* If the server requested an immediate reply, send one. */
+			if (replyRequested)
+			{
+				now = feGetCurrentTimestamp();
+				if (!sendFeedback(conn, logoff, now, true, false))
+					goto error;
+				last_status = now;
+			}
+			continue;
+		}
+		else if (copybuf[0] != 'w')
+		{
+			fprintf(stderr, _("%s: unrecognized streaming header: \"%c\"\n"),
+					progname, copybuf[0]);
+			goto error;
+		}
+
+
+		/*
+		 * Read the header of the XLogData message, enclosed in the CopyData
+		 * message. We only need the WAL location field (dataStart), the rest
+		 * of the header is ignored.
+		 */
+		hdr_len = 1;			/* msgtype 'w' */
+		hdr_len += 8;			/* dataStart */
+		hdr_len += 8;			/* walEnd */
+		hdr_len += 8;			/* sendTime */
+		if (r < hdr_len + 1)
+		{
+			fprintf(stderr, _("%s: streaming header too small: %d\n"),
+					progname, r);
+			goto error;
+		}
+
+		/* Extract WAL location for this block */
+		{
+			XLogRecPtr	temp = fe_recvint64(&copybuf[1]);
+
+			logoff = Max(temp, logoff);
+		}
+
+		if (outfd == -1 && strcmp(outfile, "-") == 0)
+		{
+			outfd = fileno(stdout);
+		}
+		else if (outfd == -1)
+		{
+			outfd = open(outfile, O_CREAT | O_APPEND | O_WRONLY | PG_BINARY,
+						 S_IRUSR | S_IWUSR);
+			if (outfd == -1)
+			{
+				fprintf(stderr,
+						_("%s: could not open log file \"%s\": %s\n"),
+						progname, outfile, strerror(errno));
+				goto error;
+			}
+		}
+
+		bytes_left = r - hdr_len;
+		bytes_written = 0;
+
+
+		while (bytes_left)
+		{
+			int			ret;
+
+			ret = write(outfd,
+						copybuf + hdr_len + bytes_written,
+						bytes_left);
+
+			if (ret < 0)
+			{
+				fprintf(stderr,
+				  _("%s: could not write %u bytes to log file \"%s\": %s\n"),
+						progname, bytes_left, outfile,
+						strerror(errno));
+				goto error;
+			}
+
+			/* Write was successful, advance our position */
+			bytes_written += ret;
+			bytes_left -= ret;
+		}
+
+		if (write(outfd, "\n", 1) != 1)
+		{
+			fprintf(stderr,
+				  _("%s: could not write %u bytes to log file \"%s\": %s\n"),
+					progname, 1, outfile,
+					strerror(errno));
+			goto error;
+		}
+	}
+
+	res = PQgetResult(conn);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
+	{
+		fprintf(stderr,
+				_("%s: unexpected termination of replication stream: %s"),
+				progname, PQresultErrorMessage(res));
+		goto error;
+	}
+	PQclear(res);
+
+	if (copybuf != NULL)
+		PQfreemem(copybuf);
+
+	if (outfd != -1 && strcmp(outfile, "-") != 0 && close(outfd) != 0)
+		fprintf(stderr, _("%s: could not close file \"%s\": %s\n"),
+				progname, outfile, strerror(errno));
+	outfd = -1;
+error:
+	PQfinish(conn);
+	conn = NULL;
+}
+
+/*
+ * When sigint is called, just tell the system to exit at the next possible
+ * moment.
+ */
+#ifndef WIN32
+
+static void
+sigint_handler(int signum)
+{
+	time_to_abort = true;
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+	PGresult   *res;
+	static struct option long_options[] = {
+/* general options */
+		{"file", required_argument, NULL, 'f'},
+		{"no-loop", no_argument, NULL, 'n'},
+		{"verbose", no_argument, NULL, 'v'},
+		{"version", no_argument, NULL, 'V'},
+		{"help", no_argument, NULL, '?'},
+/* connnection options */
+		{"dbname", required_argument, NULL, 'd'},
+		{"host", required_argument, NULL, 'h'},
+		{"port", required_argument, NULL, 'p'},
+		{"username", required_argument, NULL, 'U'},
+		{"no-password", no_argument, NULL, 'w'},
+		{"password", no_argument, NULL, 'W'},
+/* replication options */
+		{"option", required_argument, NULL, 'o'},
+		{"plugin", required_argument, NULL, 'P'},
+		{"status-interval", required_argument, NULL, 's'},
+		{"slot", required_argument, NULL, 'S'},
+		{"startpos", required_argument, NULL, 'I'},
+/* action */
+		{"create", no_argument, NULL, 1},
+		{"start", no_argument, NULL, 2},
+		{"drop", no_argument, NULL, 3},
+		{NULL, 0, NULL, 0}
+	};
+	int			c;
+	int			option_index;
+	uint32		hi,
+				lo;
+
+	progname = get_progname(argv[0]);
+	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_recvlogical"));
+
+	if (argc > 1)
+	{
+		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
+		{
+			usage();
+			exit(0);
+		}
+		else if (strcmp(argv[1], "-V") == 0 ||
+				 strcmp(argv[1], "--version") == 0)
+		{
+			puts("pg_recvlogical (PostgreSQL) " PG_VERSION);
+			exit(0);
+		}
+	}
+
+	while ((c = getopt_long(argc, argv, "f:nvd:h:o:p:U:wWP:s:S:",
+							long_options, &option_index)) != -1)
+	{
+		switch (c)
+		{
+/* general options */
+			case 'f':
+				outfile = pg_strdup(optarg);
+				break;
+			case 'n':
+				noloop = 1;
+				break;
+			case 'v':
+				verbose++;
+				break;
+/* connnection options */
+			case 'd':
+				dbname = pg_strdup(optarg);
+				break;
+			case 'h':
+				dbhost = pg_strdup(optarg);
+				break;
+			case 'p':
+				if (atoi(optarg) <= 0)
+				{
+					fprintf(stderr, _("%s: invalid port number \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				dbport = pg_strdup(optarg);
+				break;
+			case 'U':
+				dbuser = pg_strdup(optarg);
+				break;
+			case 'w':
+				dbgetpassword = -1;
+				break;
+			case 'W':
+				dbgetpassword = 1;
+				break;
+/* replication options */
+			case 'o':
+				{
+					char *data = pg_strdup(optarg);
+					char *val = strchr(data, '=');
+
+					if (val != NULL)
+					{
+						/* remove =; separate data from val */
+						*val = '\0';
+						val++;
+					}
+
+					noptions += 1;
+					options = pg_realloc(options, sizeof(char*) * noptions * 2);
+
+					options[(noptions - 1) * 2] = data;
+					options[(noptions - 1) * 2 + 1] = val;
+				}
+
+				break;
+			case 'P':
+				plugin = pg_strdup(optarg);
+				break;
+			case 's':
+				standby_message_timeout = atoi(optarg) * 1000;
+				if (standby_message_timeout < 0)
+				{
+					fprintf(stderr, _("%s: invalid status interval \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				break;
+			case 'S':
+				replication_slot = pg_strdup(optarg);
+				break;
+			case 'I':
+				if (sscanf(optarg, "%X/%X", &hi, &lo) != 2)
+				{
+					fprintf(stderr,
+							_("%s: could not parse start position \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				startpos = ((uint64) hi) << 32 | lo;
+				break;
+/* action */
+			case 1:
+				do_create_slot = true;
+				break;
+			case 2:
+				do_start_slot = true;
+				break;
+			case 3:
+				do_drop_slot = true;
+				break;
+
+			default:
+
+				/*
+				 * getopt_long already emitted a complaint
+				 */
+				fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+						progname);
+				exit(1);
+		}
+	}
+
+	/*
+	 * Any non-option arguments?
+	 */
+	if (optind < argc)
+	{
+		fprintf(stderr,
+				_("%s: too many command-line arguments (first is \"%s\")\n"),
+				progname, argv[optind]);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	/*
+	 * Required arguments
+	 */
+	if (replication_slot == NULL)
+	{
+		fprintf(stderr, _("%s: no slot specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (do_start_slot && outfile == NULL)
+	{
+		fprintf(stderr, _("%s: no target file specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (!do_drop_slot && dbname == NULL)
+	{
+		fprintf(stderr, _("%s: no database specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (!do_drop_slot && !do_create_slot && !do_start_slot)
+	{
+		fprintf(stderr, _("%s: at least one action needs to be specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (do_drop_slot && (do_create_slot || do_start_slot))
+	{
+		fprintf(stderr, _("%s: --stop cannot be combined with --init or --start\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (startpos && (do_create_slot || do_drop_slot))
+	{
+		fprintf(stderr, _("%s: --startpos cannot be combined with --init or --stop\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+#ifndef WIN32
+	pqsignal(SIGINT, sigint_handler);
+#endif
+
+	/*
+	 * don't really need this but it actually helps to get more precise error
+	 * messages about authentication, required GUCs and such without starting
+	 * to loop around connection attempts lateron.
+	 */
+	{
+		conn = GetConnection();
+		if (!conn)
+			/* Error message already written in GetConnection() */
+			exit(1);
+
+		/*
+		 * Run IDENTIFY_SYSTEM so we can get the timeline and current xlog
+		 * position.
+		 */
+		res = PQexec(conn, "IDENTIFY_SYSTEM");
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 1 || PQnfields(res) < 4)
+		{
+			fprintf(stderr,
+					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 4);
+			disconnect_and_exit(1);
+		}
+		PQclear(res);
+	}
+
+
+	/*
+	 * stop a replication slot
+	 */
+	if (do_drop_slot)
+	{
+		char		query[256];
+
+		if (verbose)
+			fprintf(stderr,
+					_("%s: freeing replication slot \"%s\"\n"),
+					progname, replication_slot);
+
+		snprintf(query, sizeof(query), "DROP_REPLICATION_SLOT \"%s\"",
+				 replication_slot);
+		res = PQexec(conn, query);
+		if (PQresultStatus(res) != PGRES_COMMAND_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, query, PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 0 || PQnfields(res) != 0)
+		{
+			fprintf(stderr,
+					_("%s: could not stop logical rep: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 0, 0);
+			disconnect_and_exit(1);
+		}
+
+		PQclear(res);
+		disconnect_and_exit(0);
+	}
+
+	/*
+	 * init a replication slot
+	 */
+	if (do_create_slot)
+	{
+		char		query[256];
+
+		if (verbose)
+			fprintf(stderr,
+					_("%s: initializing replication slot \"%s\"\n"),
+					progname, replication_slot);
+
+		snprintf(query, sizeof(query), "CREATE_REPLICATION_SLOT \"%s\" LOGICAL \"%s\"",
+				 replication_slot, plugin);
+
+		res = PQexec(conn, query);
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, query, PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 1 || PQnfields(res) != 4)
+		{
+			fprintf(stderr,
+					_("%s: could not init logical rep: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 4);
+			disconnect_and_exit(1);
+		}
+
+		if (sscanf(PQgetvalue(res, 0, 1), "%X/%X", &hi, &lo) != 2)
+		{
+			fprintf(stderr,
+					_("%s: could not parse log location \"%s\"\n"),
+					progname, PQgetvalue(res, 0, 1));
+			disconnect_and_exit(1);
+		}
+		startpos = ((uint64) hi) << 32 | lo;
+
+		replication_slot = strdup(PQgetvalue(res, 0, 0));
+		PQclear(res);
+	}
+
+
+	if (!do_start_slot)
+		disconnect_and_exit(0);
+
+	while (true)
+	{
+		StreamLog();
+		if (time_to_abort)
+		{
+			/*
+			 * We've been Ctrl-C'ed. That's not an error, so exit without an
+			 * errorcode.
+			 */
+			disconnect_and_exit(0);
+		}
+		else if (noloop)
+		{
+			fprintf(stderr, _("%s: disconnected.\n"), progname);
+			exit(1);
+		}
+		else
+		{
+			fprintf(stderr,
+			/* translator: check source for value for %d */
+					_("%s: disconnected. Waiting %d seconds to try again.\n"),
+					progname, RECONNECT_SLEEP_TIME);
+			pg_usleep(RECONNECT_SLEEP_TIME * 1000000);
+		}
+	}
+}
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index febe3d1..5d7a8ec 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -11,21 +11,18 @@
  *		  src/bin/pg_basebackup/receivelog.c
  *-------------------------------------------------------------------------
  */
+
 #include "postgres_fe.h"
 
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-/* for ntohl/htonl */
-#include <netinet/in.h>
-#include <arpa/inet.h>
+/* local includes */
+#include "receivelog.h"
+#include "streamutil.h"
 
 #include "libpq-fe.h"
 #include "access/xlog_internal.h"
 
-#include "receivelog.h"
-#include "streamutil.h"
+#include <sys/stat.h>
+#include <unistd.h>
 
 
 /* fd and filename for currently open WAL file */
@@ -195,63 +192,6 @@ close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos)
 
 
 /*
- * Local version of GetCurrentTimestamp(), since we are not linked with
- * backend code. The protocol always uses integer timestamps, regardless of
- * server setting.
- */
-static int64
-localGetCurrentTimestamp(void)
-{
-	int64		result;
-	struct timeval tp;
-
-	gettimeofday(&tp, NULL);
-
-	result = (int64) tp.tv_sec -
-		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-
-	result = (result * USECS_PER_SEC) + tp.tv_usec;
-
-	return result;
-}
-
-/*
- * Local version of TimestampDifference(), since we are not linked with
- * backend code.
- */
-static void
-localTimestampDifference(int64 start_time, int64 stop_time,
-						 long *secs, int *microsecs)
-{
-	int64		diff = stop_time - start_time;
-
-	if (diff <= 0)
-	{
-		*secs = 0;
-		*microsecs = 0;
-	}
-	else
-	{
-		*secs = (long) (diff / USECS_PER_SEC);
-		*microsecs = (int) (diff % USECS_PER_SEC);
-	}
-}
-
-/*
- * Local version of TimestampDifferenceExceeds(), since we are not
- * linked with backend code.
- */
-static bool
-localTimestampDifferenceExceeds(int64 start_time,
-								int64 stop_time,
-								int msec)
-{
-	int64		diff = stop_time - start_time;
-
-	return (diff >= msec * INT64CONST(1000));
-}
-
-/*
  * Check if a timeline history file exists.
  */
 static bool
@@ -371,47 +311,6 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
 }
 
 /*
- * Converts an int64 to network byte order.
- */
-static void
-sendint64(int64 i, char *buf)
-{
-	uint32		n32;
-
-	/* High order half first, since we're doing MSB-first */
-	n32 = (uint32) (i >> 32);
-	n32 = htonl(n32);
-	memcpy(&buf[0], &n32, 4);
-
-	/* Now the low order half */
-	n32 = (uint32) i;
-	n32 = htonl(n32);
-	memcpy(&buf[4], &n32, 4);
-}
-
-/*
- * Converts an int64 from network byte order to native format.
- */
-static int64
-recvint64(char *buf)
-{
-	int64		result;
-	uint32		h32;
-	uint32		l32;
-
-	memcpy(&h32, buf, 4);
-	memcpy(&l32, buf + 4, 4);
-	h32 = ntohl(h32);
-	l32 = ntohl(l32);
-
-	result = h32;
-	result <<= 32;
-	result |= l32;
-
-	return result;
-}
-
-/*
  * Send a Standby Status Update message to server.
  */
 static bool
@@ -422,16 +321,16 @@ sendFeedback(PGconn *conn, XLogRecPtr blockpos, int64 now, bool replyRequested)
 
 	replybuf[len] = 'r';
 	len += 1;
-	sendint64(blockpos, &replybuf[len]);		/* write */
+	fe_sendint64(blockpos, &replybuf[len]);		/* write */
 	len += 8;
 	if (reportFlushPosition)
-		sendint64(lastFlushPosition, &replybuf[len]);		/* flush */
+		fe_sendint64(lastFlushPosition, &replybuf[len]);		/* flush */
 	else
-		sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
+		fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
 	len += 8;
-	sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
+	fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
 	len += 8;
-	sendint64(now, &replybuf[len]);		/* sendTime */
+	fe_sendint64(now, &replybuf[len]);		/* sendTime */
 	len += 8;
 	replybuf[len] = replyRequested ? 1 : 0;		/* replyRequested */
 	len += 1;
@@ -864,9 +763,9 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 		/*
 		 * Potentially send a status message to the master
 		 */
-		now = localGetCurrentTimestamp();
+		now = feGetCurrentTimestamp();
 		if (still_sending && standby_message_timeout > 0 &&
-			localTimestampDifferenceExceeds(last_status, now,
+			feTimestampDifferenceExceeds(last_status, now,
 											standby_message_timeout))
 		{
 			/* Time to send feedback! */
@@ -895,10 +794,10 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 				int			usecs;
 
 				targettime = last_status + (standby_message_timeout - 1) * ((int64) 1000);
-				localTimestampDifference(now,
-										 targettime,
-										 &secs,
-										 &usecs);
+				feTimestampDifference(now,
+									  targettime,
+									  &secs,
+									  &usecs);
 				if (secs <= 0)
 					timeout.tv_sec = 1; /* Always sleep at least 1 sec */
 				else
@@ -1002,7 +901,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 			/* If the server requested an immediate reply, send one. */
 			if (replyRequested && still_sending)
 			{
-				now = localGetCurrentTimestamp();
+				now = feGetCurrentTimestamp();
 				if (!sendFeedback(conn, blockpos, now, false))
 					goto error;
 				last_status = now;
@@ -1032,7 +931,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 						progname, r);
 				goto error;
 			}
-			blockpos = recvint64(&copybuf[1]);
+			blockpos = fe_recvint64(&copybuf[1]);
 
 			/* Extract WAL location for this block */
 			xlogoff = blockpos % XLOG_SEG_SIZE;
diff --git a/src/bin/pg_basebackup/receivelog.h b/src/bin/pg_basebackup/receivelog.h
index 7c983cd..f4789a5 100644
--- a/src/bin/pg_basebackup/receivelog.h
+++ b/src/bin/pg_basebackup/receivelog.h
@@ -1,3 +1,5 @@
+#include "libpq-fe.h"
+
 #include "access/xlogdefs.h"
 
 /*
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 041076f..441abbf 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -11,11 +11,28 @@
  *-------------------------------------------------------------------------
  */
 
-#include "postgres_fe.h"
+/*
+ * We have to use postgres.h not postgres_fe.h here, because there's
+ * backend-only stuff in the datetime include files we need.  But we need a
+ * frontend-ish environment otherwise. Hence this ugly hack.
+ */
+#define FRONTEND 1
+#include "postgres.h"
+
 #include "streamutil.h"
 
+#include "common/fe_memutils.h"
+#include "utils/datetime.h"
+
 #include <stdio.h>
 #include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* for ntohl/htonl */
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 const char *progname;
 char	   *connection_string = NULL;
@@ -23,6 +40,7 @@ char	   *dbhost = NULL;
 char	   *dbuser = NULL;
 char	   *dbport = NULL;
 char	   *replication_slot = NULL;
+char	   *dbname = NULL;
 int			dbgetpassword = 0;	/* 0=auto, -1=never, 1=always */
 static char *dbpassword = NULL;
 PGconn	   *conn = NULL;
@@ -87,10 +105,10 @@ GetConnection(void)
 	}
 
 	keywords[i] = "dbname";
-	values[i] = "replication";
+	values[i] = dbname == NULL ? "replication" : dbname;
 	i++;
 	keywords[i] = "replication";
-	values[i] = "true";
+	values[i] = dbname == NULL ? "true" : "database";
 	i++;
 	keywords[i] = "fallback_application_name";
 	values[i] = progname;
@@ -212,3 +230,102 @@ GetConnection(void)
 
 	return tmpconn;
 }
+
+
+/*
+ * Frontend version of GetCurrentTimestamp(), since we are not linked with
+ * backend code. The protocol always uses integer timestamps, regardless of
+ * server setting.
+ */
+int64
+feGetCurrentTimestamp(void)
+{
+	int64		result;
+	struct timeval tp;
+
+	gettimeofday(&tp, NULL);
+
+	result = (int64) tp.tv_sec -
+		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
+
+	result = (result * USECS_PER_SEC) + tp.tv_usec;
+
+	return result;
+}
+
+/*
+ * Frontend version of TimestampDifference(), since we are not linked with
+ * backend code.
+ */
+void
+feTimestampDifference(int64 start_time, int64 stop_time,
+						 long *secs, int *microsecs)
+{
+	int64		diff = stop_time - start_time;
+
+	if (diff <= 0)
+	{
+		*secs = 0;
+		*microsecs = 0;
+	}
+	else
+	{
+		*secs = (long) (diff / USECS_PER_SEC);
+		*microsecs = (int) (diff % USECS_PER_SEC);
+	}
+}
+
+/*
+ * Frontend version of TimestampDifferenceExceeds(), since we are not
+ * linked with backend code.
+ */
+bool
+feTimestampDifferenceExceeds(int64 start_time,
+								int64 stop_time,
+								int msec)
+{
+	int64		diff = stop_time - start_time;
+
+	return (diff >= msec * INT64CONST(1000));
+}
+
+/*
+ * Converts an int64 to network byte order.
+ */
+void
+fe_sendint64(int64 i, char *buf)
+{
+	uint32		n32;
+
+	/* High order half first, since we're doing MSB-first */
+	n32 = (uint32) (i >> 32);
+	n32 = htonl(n32);
+	memcpy(&buf[0], &n32, 4);
+
+	/* Now the low order half */
+	n32 = (uint32) i;
+	n32 = htonl(n32);
+	memcpy(&buf[4], &n32, 4);
+}
+
+/*
+ * Converts an int64 from network byte order to native format.
+ */
+int64
+fe_recvint64(char *buf)
+{
+	int64		result;
+	uint32		h32;
+	uint32		l32;
+
+	memcpy(&h32, buf, 4);
+	memcpy(&l32, buf + 4, 4);
+	h32 = ntohl(h32);
+	l32 = ntohl(l32);
+
+	result = h32;
+	result <<= 32;
+	result |= l32;
+
+	return result;
+}
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index 7c7d022..d0f3799 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -5,6 +5,7 @@ extern char *connection_string;
 extern char *dbhost;
 extern char *dbuser;
 extern char *dbport;
+extern char *dbname;
 extern int	dbgetpassword;
 extern char *replication_slot;
 
@@ -12,3 +13,12 @@ extern char *replication_slot;
 extern PGconn *conn;
 
 extern PGconn *GetConnection(void);
+
+extern int64 feGetCurrentTimestamp(void);
+extern void feTimestampDifference(int64 start_time, int64 stop_time,
+									 long *secs, int *microsecs);
+
+extern bool feTimestampDifferenceExceeds(int64 start_time, int64 stop_time,
+											int msec);
+extern void fe_sendint64(int64 i, char *buf);
+extern int64 fe_recvint64(char *buf);
-- 
1.8.5.rc2.dirty

0003-Documentation-for-logical-decoding.patchtext/x-patch; charset=us-asciiDownload
>From 317d0f7bc73d904fdf58264ff5e39a43e57ea7df Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 00:15:39 +0100
Subject: [PATCH 3/7] Documentation for logical decoding.

Craig Ringer, Andres Freund, Christian Kruse
---
 doc/src/sgml/catalogs.sgml           |  27 +-
 doc/src/sgml/filelist.sgml           |   1 +
 doc/src/sgml/func.sgml               | 102 +++++-
 doc/src/sgml/high-availability.sgml  |   6 +-
 doc/src/sgml/logicaldecoding.sgml    | 607 +++++++++++++++++++++++++++++++++++
 doc/src/sgml/postgres.sgml           |   1 +
 doc/src/sgml/protocol.sgml           |  69 +++-
 doc/src/sgml/ref/allfiles.sgml       |   1 +
 doc/src/sgml/ref/alter_table.sgml    |   2 +-
 doc/src/sgml/ref/create_table.sgml   |  15 +-
 doc/src/sgml/ref/pg_recvlogical.sgml | 305 ++++++++++++++++++
 doc/src/sgml/reference.sgml          |   1 +
 12 files changed, 1120 insertions(+), 17 deletions(-)
 create mode 100644 doc/src/sgml/logicaldecoding.sgml
 create mode 100644 doc/src/sgml/ref/pg_recvlogical.sgml

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 908f947..a12ee56 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -5177,7 +5177,7 @@
 
   <para>
    For more on replication slots,
-   see <xref linkend="streaming-replication-slots">.
+   see <xref linkend="streaming-replication-slots"> and <xref linkend="logicaldecoding">.
   </para>
 
   <table>
@@ -5210,6 +5210,13 @@
      </row>
 
      <row>
+      <entry><structfield>plugin</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>The basename of the shared object containing the output plugin this logical slot is using, or null for physical slots.</entry>
+     </row>
+
+     <row>
       <entry><structfield>datoid</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry>
@@ -5243,6 +5250,24 @@
      </row>
 
      <row>
+      <entry><structfield>xmin</structfield></entry>
+      <entry><type>xid</type></entry>
+      <entry></entry>
+      <entry>The oldest transaction that this slot needs the database to
+      retain.  <literal>VACUUM</literal> cannot remove catalog tuples deleted
+      by any later transaction.
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>catalog_xmin</structfield></entry>
+      <entry><type>xid</type></entry>
+      <entry></entry>
+      <entry>The <literal>xmin</literal>, or oldest transaction ID, that this
+      slot forces to be retained in the system catalogs. </entry>
+     </row>
+
+     <row>
       <entry><structfield>restart_lsn</structfield></entry>
       <entry><type>pg_lsn</type></entry>
       <entry></entry>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 0e863ee..6c8e254 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -91,6 +91,7 @@
 <!ENTITY nls        SYSTEM "nls.sgml">
 <!ENTITY plhandler  SYSTEM "plhandler.sgml">
 <!ENTITY fdwhandler SYSTEM "fdwhandler.sgml">
+<!ENTITY logicaldecoding SYSTEM "logicaldecoding.sgml">
 <!ENTITY protocol   SYSTEM "protocol.sgml">
 <!ENTITY sources    SYSTEM "sources.sgml">
 <!ENTITY storage    SYSTEM "storage.sgml">
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 080da43..0336de8 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -16377,8 +16377,9 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
 
    <para>
     PostgreSQL exposes a number of functions for controlling and interacting
-    with replication features. See <xref linkend="streaming-replication">
-    and <xref linkend="streaming-replication-slots">.
+    with replication features. See <xref linkend="streaming-replication">,
+    <xref linkend="streaming-replication-slots">
+    and <xref linkend="logicaldecoding">.
    </para>
 
    <para>
@@ -16437,9 +16438,106 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
         command <literal>DROP_REPLICATION_SLOT</>.
        </entry>
       </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_create_logical_replication_slot</primary>
+        </indexterm>
+        <literal><function>pg_create_logical_replication_slot(<parameter>slotname</parameter> <type>name</type>, <parameter>plugin</parameter> <type>name</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>slotname</parameter> <type>name</type>, <parameter>xlog_position</parameter> <type>pg_lsn</type>)
+       </entry>
+       <entry>
+        Creates a new logical (decoding) replication slot named
+        <parameter>slotname</parameter> using the output plugin
+        <parameter>plugin</parameter>. Output plugins are listed amongst the
+        extensions in <literal>pg_catalog.pg_available_extensions</literal>,
+        but there is no specific listing of only output plugins. Same as
+        walsender protocol command <literal>CREATE REPLICATION SLOT ... LOGICAL</literal>.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_get_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_get_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>pg_lsn</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Returns changes in the slot <parameter>slotname</parameter>, starting
+        from the point at which since changes have been consumed last. Changes
+        are extracted upto the current end of the WAL, or if nonnull only if
+        their transactions have committed
+        before <parameter>upto_lsn</parameter>, or if nonnull
+        until <parameter>upto_nchanges</parameter> rows have been
+        collected. Note that the <parameter>upto_nchanges</parameter> limit is
+        only enforced everytime a transaction commits. Changes will not be
+        consumed.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_peek_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_peek_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>text</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Behaves just like
+        the <function>pg_logical_slot_get_changes()</function> function,
+        except that changes are not consumed, i.e. will be returned again on
+        future calls.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_get_binary_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_get_binary_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>pg_lsn</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>bytea</type>)
+       </entry>
+       <entry>
+        Behaves just like
+        the <function>pg_logical_slot_get_changes()</function> function,
+        except that changes are returned as <type>bytea</type>.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_peek_binary_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_peek_binary_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>pg_lsn</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>bytea</type>)
+       </entry>
+       <entry>
+        Behaves just like
+        the <function>pg_logical_slot_get_changes()</function> function,
+        except that changes are returned as <type>bytea</type> and that
+        changes are not consumed, i.e. will be returned again on future calls.
+       </entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
+
   </sect2>
 
   <sect2 id="functions-admin-dbobject">
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index ecb51c4..deac2a7 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -888,12 +888,12 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
    </para>
    <para>
     In lieu of using replication slots, it is possible to prevent the removal
-    of old WAL segments using <xref linkend="guc-wal-keep-segments">, or by
+    of old WAL segments using <xref linkend="guc-wal-keep-segments"> or by
     storing the segments in an archive using
     <xref linkend="guc-archive-command">.
     However, these methods often result in retaining more WAL segments than
-    required, whereas replication slots retain only the number of segments
-    known to be needed.  An advantage of these methods is that they bound
+    required whereas replication slots retain only the number of segments
+    known to be needed.  An advantage of these methods is that they are bound
     the space requirement for <literal>pg_xlog</>; there is currently no way
     to do this using replication slots.
    </para>
diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml
new file mode 100644
index 0000000..f4d5910
--- /dev/null
+++ b/doc/src/sgml/logicaldecoding.sgml
@@ -0,0 +1,607 @@
+<!-- doc/src/sgml/logicaldecoding.sgml -->
+ <chapter id="logicaldecoding">
+  <title>Logical Decoding</title>
+  <indexterm zone="logicaldecoding">
+   <primary>Logical Decoding</primary>
+  </indexterm>
+  <indexterm zone="logicaldecoding">
+   <primary>Logical Replication</primary>
+  </indexterm>
+  <indexterm zone="logicaldecoding">
+   <primary>Changeset Extraction</primary>
+  </indexterm>
+  <para>
+   PostgreSQL provides infrastructure to stream the modifications performed
+   via SQL to external consumers which can be used to implement replication
+   solutions, perform auditing, and similar tasks.
+  </para>
+
+  <para>
+   Changes are sent out in streams where each stream outputs each change
+   exactly once. On the sender's side, each changestream is identified by a so
+   called logical replication slot.
+  </para>
+
+  <para>
+   The format in which those changes are streamed is determined by the output
+   plugin used. While an example plugin is provided, additional plugins can be
+   written to extend the choice of available formats without modifying any
+   core code.
+   Every output plugin has access to each individual new row produced
+   by <command>INSERT</command>, and the new row version created
+   by <command>UPDATE</command>. Which data is available for rows affected
+   by <command>DELETE</command> and for the old row version in
+   an <command>UPDATE</command> depends on the relation's
+   configured <link linkend="SQL-CREATETABLE-REPLICA-IDENTITY"><literal>REPLICA
+   IDENTITY</literal></link>.
+  </para>
+
+  <para>
+   Changes can be consumed either using the streaming replication protocol
+   (see <xref linkend="protocol-replication"> and
+   <xref linkend="logicaldecoding-walsender">), or by calling functions
+   via SQL (see <xref linkend="logicaldecoding-sql">). It is also possible
+   to write additional methods of consuming the output of a replication slot
+   without modifying core code
+   (see <xref linkend="logicaldecoding-writer">).
+  </para>
+
+  <sect1 id="logicaldecoding-example">
+   <title>Logical Decoding Example</title>
+   <para>
+    The following example shows usage of the SQL interface.
+   </para>
+   <para>
+    Before you can use logical decoding
+    <literal>postgresql.conf</literal> must be changed to ensure the following
+    parameters are set to at least:
+    <programlisting>
+wal_level = logical
+max_replication_slots = 1
+max_wal_senders = 1
+    </programlisting>
+    Then connect to the target database (in the example
+    below, <literal>postgres</literal>) as a superuser.
+   </para>
+   <programlisting>
+postgres=# -- max_replication_slots must be nonzero and wal_level must be logical
+postgres=# SHOW max_replication_slots;
+ max_replication_slots
+-----------------------
+ 1
+(1 row)
+
+postgres=# SHOW wal_level;
+ wal_level
+-----------
+ logical
+(1 row)
+
+postgres=# SELECT * FROM pg_replication_slots;
+ slot_name | plugin | slot_type | datoid | database | active | xmin | catalog_xmin | restart_lsn
+-----------+--------+-----------+--------+----------+--------+------+--------------+-------------
+(0 rows)
+
+postgres=# -- Create a slot named 'regression_slot' using the output plugin 'test_decoding'
+postgres=# SELECT * FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
+    slotname     | xlog_position
+-----------------+---------------
+ regression_slot | 0/16B1970
+(1 row)
+
+postgres=# SELECT * FROM pg_replication_slots;
+    slot_name    |    plugin     | slot_type | datoid | database | active |  xmin  | catalog_xmin | restart_lsn
+-----------------+---------------+-----------+--------+----------+--------+--------+--------------+-------------
+ regression_slot | test_decoding | logical   |  12052 | postgres | f      |        |          684 | 0/16A4408
+(1 row)
+
+postgres=# -- There are no changes to see yet
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location | xid | data
+----------+-----+------
+(0 rows)
+
+postgres=# CREATE TABLE data(id serial primary key, data text);
+CREATE TABLE
+
+postgres=# -- DDL isn't replicated, so all you'll see is the transaction
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location  | xid |    data
+-----------+-----+------------
+ 0/16D5D48 | 688 | BEGIN 688
+ 0/16E0380 | 688 | COMMIT 688
+(2 rows)
+
+postgres=# -- Once changes are read, they're consumed and not emitted
+postgres=# -- in a subsequent call:
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location | xid | data
+----------+-----+------
+(0 rows)
+
+postgres=# BEGIN;
+postgres=# INSERT INTO data(data) VALUES('1');
+postgres=# INSERT INTO data(data) VALUES('2');
+postgres=# COMMIT;
+
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E0478 | 689 | BEGIN 689
+ 0/16E0478 | 689 | table public.data: INSERT: id[int4]:1 data[text]:'1'
+ 0/16E0580 | 689 | table public.data: INSERT: id[int4]:2 data[text]:'2'
+ 0/16E0650 | 689 | COMMIT 689
+(4 rows)
+
+postgres=# INSERT INTO data(data) VALUES('3');
+
+postgres=# -- You can also peek ahead in the change stream without consuming changes
+postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E09C0 | 690 | BEGIN 690
+ 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3'
+ 0/16E0B90 | 690 | COMMIT 690
+(3 rows)
+
+postgres=# -- You can also peek ahead in the change stream without consuming changes
+postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E09C0 | 690 | BEGIN 690
+ 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3'
+ 0/16E0B90 | 690 | COMMIT 690
+(3 rows)
+
+postgres=# -- options can be passed to output plugin, to influence the formatting
+postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL, 'include-timestamp', 'on');
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E09C0 | 690 | BEGIN 690
+ 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3'
+ 0/16E0B90 | 690 | COMMIT 690 (at 2014-02-27 16:41:51.863092+01)
+(3 rows)
+
+postgres=# -- Remember to destroy a slot you no longer need to stop it consuming
+postgres=# -- server resources:
+postgres=# SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot
+-----------------------
+
+(1 row)
+    </programlisting>
+   <para>
+    The following example shows usage of the walsender interface using
+    the <link linkend="app-pgrecvlogical"><command>pg_recvlogical</command></link>
+    shell command. It requires the replication configurations to be allowed
+    (see <xref linkend="streaming-replication-authentication">)
+    and <varname>max_wal_senders</varname> to be set sufficiently high for
+    another connection.
+   </para>
+   <programlisting>
+# pg_recvlogical -d testdb --slot test --create
+# pg_recvlogical -d testdb --slot test --start -f -
+CTRL-Z
+# psql -c "INSERT INTO data(data) VALUES('4');"
+# fg
+BEGIN 693
+table public.data: INSERT: id[int4]:4 data[text]:'4'
+COMMIT 693
+CTRL-C
+# pg_recvlogical -d testdb --slot test --drop
+   </programlisting>
+  </sect1>
+  <sect1 id="logicaldecoding-explanation">
+   <title>Logical Decoding Concepts</title>
+   <sect2>
+    <indexterm>
+     <primary>Logical Decoding</primary>
+    </indexterm>
+    <title>Logical Decoding</title>
+    <para>
+     Logical decoding is the the process of extracting all persistent changes
+     to a database's tables into a coherent, easy to understand format which
+     can be interpreted without detailed knowledge of the database's internal
+     state.
+    </para>
+    <para>
+     In <productname>PostgreSQL</productname> logical decoding is implemented
+     by decoding the <link linkend="wal">WAL's</link> contents, which describe
+     changes on a storage level, into an application-specific form such as a
+     stream of tuples or SQL statements.
+    </para>
+   </sect2>
+
+   <sect2>
+    <indexterm>
+     <primary>Logical Replication Slot</primary>
+    </indexterm>
+    <indexterm>
+     <primary>Replication Slot</primary>
+    </indexterm>
+    <title>Replication Slots</title>
+    <para>
+     In the context of logical replication a slot represents a stream of
+     changes which can be replayed to a client in the order they were made on
+     the origin server. Each slot streams a sequence of changes from a single
+     database, sending each change exactly once (unless peeking forward in the
+     stream).
+    </para>
+    <note>
+     <para>PostgreSQL also has streaming replication slots
+     (see <xref linkend="streaming-replication">), but they are used somewhat
+     differently there.
+     </para>
+    </note>
+    <para>
+     Replication slots have an identifier which is unique across all databases
+     in a <productname>PostgreSQL</productname> cluster. Slots persist
+     independently of the connection using them and are crash-safe.  They can
+     be allocated in primary servers and hot-standby servers (streaming
+     replicas or archive-replaying hot standbys), so it's possible to
+     replicate changes over physical replication and read a logical change
+     stream from that physical replica server.
+    </para>
+    <para>
+     Multiple independent slots may exist for a single database. Each slot has
+     its own state, allowing different consumers to receive changes from
+     different points in the database change stream. For most applications a
+     separate slot is required for each consumer.
+    </para>
+    <para>
+     A logical replication slot knows nothing about the state of the
+     receiver(s).  It's even possible to have multiple different receivers using
+     the same slot at different times; they'll just get the changes following
+     on from when the last receiver stopped consuming them. Only one receiver
+     may consume changes from a slot at any given time.
+    </para>
+    <note>
+     <para>
+      Replication slots persist across crashes and know nothing about the state of
+      their consumer(s). They will prevent removal of required resources even
+      when there is no connection using them. This consumes storage because
+      neither required WAL nor required rows from the system catalogs can be
+      removed by VACUUM as long as they are required by a replication slot, so
+      if a slot is no longer required it should be dropped.
+     </para>
+     <para>
+      Slots may be created manually, or using a client like a replication
+      tool. Keep this in mind when you retire a client that uses a replication
+      slot, like a logical replica - you may need to give it a specific
+      command to remove its replication slot, or drop the slot yourself, even
+      if you did not initially create the slot by hand.
+     </para>
+    </note>
+   </sect2>
+   <sect2>
+    <title>Output Plugins</title>
+    <para>
+     Output plugins transform the data from postgres' internal representation
+     into the format the consumer of a replication slot desires. Additional
+     output plugins can be written without modifying core postgres code.
+    </para>
+   </sect2>
+   <sect2>
+    <title>Exported Snapshots</title>
+    <para>
+     When a new replication slot is created over the walsender interface a
+     snapshot is exported
+     (see <xref linkend="functions-snapshot-synchronization">) which will show
+     exactly the state of the database after which all changes will be
+     included in the changestream. This can be used to create a new replica by
+     using <link linkend="sql-set-transaction"><literal>SET TRANSACTION
+     SNAPSHOT</literal></link> to read the state of the database at the moment
+     the slot was created. This transaction can then be used to dump the
+     database's state at that point in time which afterwards can be updated
+     using the slot's contents without loosing any changes.
+    </para>
+   </sect2>
+  </sect1>
+  <sect1 id="logicaldecoding-walsender">
+   <title>Streaming Replication Protocol Interface</title>
+   <para>
+    The <literal>CREATE_REPLICATION_SLOT SLOT slotname LOGICAL
+    options</literal>, <literal>DROP_REPLICATION_SLOT SLOT slotname</literal>
+    and <literal>START_REPLICATION SLOT slotname LOGICAL options</literal>
+    commands can be used to create, drop and stream changes from a replication
+    slot respectively. These commands are only available over a replication
+    connection; they won't work on the SQL
+    level. See <xref linkend="protocol-replication">.
+   </para>
+   <para>
+    The <command>pg_recvlogical</command> command
+    (see <xref linkend="app-pgrecvlogical">) can be used to control logical
+    decoding over a walsender connection.
+   </para>
+  </sect1>
+  <sect1 id="logicaldecoding-sql">
+   <title>Logical Decoding <acronym>SQL</acronym> Interface</title>
+   <para>
+     See <xref linkend="functions-replication"> for detailed documentation on
+     the SQL-level API for interacting with logical decoding.
+   </para>
+   <para>
+    Synchronous replication (see <xref linkend="synchronous-replication">) is
+    only supported on replication slots used over the walsender interface. The
+    function interface and additional, non-core interfaces do not support
+    synchronous replication.
+   </para>
+  </sect1>
+  <sect1 id="logicaldecoding-catalogs">
+   <title>System catalogs related to logical decoding</title>
+   <para>
+    The <link linkend="catalog-pg-replication-slots"><structname>pg_replication_slots</structname></link>
+    view and the
+    <link linkend="monitoring-stats-views-table"><structname>pg_stat_replication</structname></link>
+    view provide information about the current state of replication slots and
+    walsender connections respectively. These views apply to both physical and
+    logical replication.
+   </para>
+  </sect1>
+  <sect1 id="logicaldecoding-output-plugin">
+   <title>Logical Decoding Output Plugins</title>
+   <para>
+    An example output plugin can be found in the
+    <link linkend="test-decoding">
+     <filename>contrib/test_decoding</filename>
+    </link>
+    subdirectory of the PostgreSQL source tree.
+   </para>
+   <sect2 id="logicaldecoding-output-init">
+    <title>Initialization Function</title>
+    <indexterm zone="logicaldecoding">
+     <primary>_PG_output_plugin_init</primary>
+    </indexterm>
+    <para>
+     An output plugin is loaded by dynamically loading a shared library with
+     the output plugin's name as the library basename. The normal library
+     search path is used to locate the library. To provide the required output
+     plugin callbacks and to indicate that the library is actually an output
+     plugin it needs to provide a function named
+     <function>_PG_output_plugin_init</function>. This function is passed a
+     struct that needs to be filled with the callback function pointers for
+     individual actions.
+     <programlisting>
+typedef struct OutputPluginCallbacks
+{
+    LogicalDecodeStartupCB startup_cb;
+    LogicalDecodeBeginCB begin_cb;
+    LogicalDecodeChangeCB change_cb;
+    LogicalDecodeCommitCB commit_cb;
+    LogicalDecodeShutdownCB shutdown_cb;
+} OutputPluginCallbacks;
+typedef void (*LogicalOutputPluginInit)(struct OutputPluginCallbacks *cb);
+     </programlisting>
+     The <function>begin_cb</function>, <function>change_cb</function>
+     and <function>commit_cb</function> callbacks are required,
+     while <function>startup_cb</function>
+     and <function>shutdown_cb</function> are optional.
+    </para>
+   </sect2>
+
+   <sect2 id="logicaldecoding-capabilities">
+    <title>Capabilities</title>
+    <para>
+     To decode, format and output changes, output plugins can use most of the
+     backend's normal infrastructure, including calling output functions. Read
+     only access to relations is permitted as long as only relations are
+     accessed that either have been created by <command>initdb</command> in
+     the <literal>pg_catalog</literal> schema, or have are marked as user
+     provided catalog tables using
+     <programlisting>
+ALTER TABLE user_catalog_table SET (user_catalog_table = true);
+CREATE TABLE another_catalog_table(data text) WITH (user_catalog_table = true);
+     </programlisting>
+     Any actions leading to xid assignment are prohibited. That, among others,
+     includes writing to tables, performing DDL changes and
+     calling <literal>txid_current()</literal>.
+    </para>
+   </sect2>
+
+   <sect2 id="logicaldecoding-output-plugin-callbacks">
+    <title>Output Plugin Callbacks</title>
+    <para>
+     An output plugin gets notified about changes that are happening via
+     various callbacks it needs to provide.
+    </para>
+    <para>
+     Concurrent transactions are decoded in commit order and only changes
+     belonging to a specific transaction are decoded inbetween
+     the <literal>begin</literal> and <literal>commit</literal>
+     callbacks. Transactions that were rolled back explicitly or implicitly
+     never get
+     decoded. Successfull <link linkend="SQL-SAVEPOINT">SAVEPOINTs</link> are
+     folded into the transaction containing them in the order they were
+     exectuded within that transaction.
+    </para>
+    <note>
+     <para>
+      Only transactions that have already safely been flushed to disk will be
+      decoded. That can lead to a COMMIT not immediately being decoded in a
+      directly following <literal>pg_logical_slot_get_changes()</literal>
+      when <varname>synchronous_commit</varname> is set
+      to <literal>off</literal>.
+     </para>
+    </note>
+    <sect3 id="logicaldecoding-output-plugin-startup">
+     <title>Startup Callback</title>
+     <para>
+      The optional <function>startup_cb</function> callback is called whenever
+      an replication slot is created or asked to stream changes, independent
+      of the number of changes that are ready to be put out.
+      <programlisting>
+typedef void (*LogicalDecodeStartupCB) (
+    struct LogicalDecodingContext *ctx,
+    OutputPluginOptions *options,
+    bool is_init
+);
+      </programlisting>
+      The <literal>is_init</literal> paramter will be true when the
+      replication slot is being created and false
+      otherwise. <parameter>options</parameter> points to a struct of options
+      that output plugins can set:
+      <programlisting>
+typedef struct OutputPluginOptions
+{
+    OutputPluginOutputType output_type;
+} OutputPluginOptions;
+      </programlisting>
+      <literal>output_type</literal> has to either be set to
+      <literal>OUTPUT_PLUGIN_TEXTUAL_OUTPUT</literal>
+      or <literal>OUTPUT_PLUGIN_BINARY_OUTPUT</literal>.
+     </para>
+     <para>
+      The startup callback should validate the options present in
+      <literal>ctx-&gt;output_plugin_options</literal>. If the output plugin
+      needs to have a state, it can
+      use <literal>ctx-&gt;output_plugin_private</literal> to store it.
+     </para>
+    </sect3>
+    <sect3 id="logicaldecoding-output-plugin-shutdown">
+     <title>Shutdown Callback</title>
+     <para>
+      The optional <function>shutdown_cb</function> callback is called
+      whenever a formerly active replication slot is not used anymore and can
+      be used to deallocate resources private to the output plugin. The slot
+      isn't necessarily being dropped, streaming is just being stopped.
+      <programlisting>
+typedef void (*LogicalDecodeShutdownCB) (
+    struct LogicalDecodingContext *ctx
+);
+      </programlisting>
+     </para>
+   </sect3>
+    <sect3 id="logicaldecoding-output-plugin-begin">
+     <title>Transaction Begin Callback</title>
+     <para>
+      The required <function>begin_cb</function> callback is called whenever a
+      start of a commited transaction has been decoded. Aborted transactions
+      and their contents never get decoded.
+      <programlisting>
+typedef void (*LogicalDecodeBeginCB) (
+    struct LogicalDecodingContext *,
+    ReorderBufferTXN *txn
+);
+      </programlisting>
+      The <parameter>txn</parameter> parameter contains meta information about
+      the transaction, like the timestamp at which it has been committed and
+      its XID.
+     </para>
+   </sect3>
+    <sect3 id="logicaldecoding-output-plugin-commit">
+     <title>Transaction End Callback</title>
+     <para>
+      The required <function>commit_cb</function> callback is called whenever
+      a transaction commit has been
+      decoded. The <function>change_cb</function> callbacks for all modified
+      rows will have been called before this, if there have been any modified
+      rows.
+      <programlisting>
+typedef void (*LogicalDecodeCommitCB) (
+    struct LogicalDecodingContext *,
+    ReorderBufferTXN *txn
+);
+      </programlisting>
+     </para>
+    </sect3>
+    <sect3 id="logicaldecoding-output-plugin-change">
+     <title>Callback called for each individual change in a
+     transaction</title>
+     <para>
+      The required <function>change_cb</function> callback is called for every
+      individual row modification inside a transaction, may it be
+      an <command>INSERT</command>, <command>UPDATE</command>
+      or <command>DELETE</command>. Even if the original command modified
+      several rows at once the callback will be called indvidually for each
+      row.
+      <programlisting>
+typedef void (*LogicalDecodeChangeCB) (
+    struct LogicalDecodingContext *ctx,
+    ReorderBufferTXN *txn,
+    Relation relation,
+    ReorderBufferChange *change
+);
+      </programlisting>
+      The <parameter>ctx</parameter> and <parameter>txn</parameter> parameters
+      have the same contents as for the <function>begin_cb</function>
+      and <function>commit_cb</function> callbacks, but additionally the
+      relation descriptor <parameter>relation</parameter> points to the
+      relation the row belongs to and a struct
+      <parameter>change</parameter> describing the row modification are passed
+      in.
+     </para>
+     <note>
+      <para>
+       Only changes in user defined tables that are not unlogged
+       (see <xref linkend="SQL-CREATETABLE-UNLOGGED">) and not temporary
+       (see <xref linkend="SQL-CREATETABLE-TEMPORARY">) can be extracted using
+       logical decoding.
+      </para>
+     </note>
+    </sect3>
+   </sect2>
+   <sect2 id="logicaldecoding-output-plugin-output">
+    <title>Functions for producing output from an output plugin</title>
+    <para>
+     To actually produce output, output plugins can write data to
+     the <literal>StringInfo</literal> output buffer
+     in <literal>ctx-&gt;out</literal> when inside
+     the <function>begin_cb</function>, <function>commit_cb</function>
+     or <function>change_cb</function> callbacks. Before writing to the output
+     buffer <function>OutputPluginPrepareWrite(ctx, last_write)</function> has
+     to be called, and after finishing writing to the
+     buffer <function>OutputPluginWrite(ctx, last_write)</function> has to be
+     called to perform the write. The <parameter>last_write</parameter>
+     indicates whether a particular write was the callback's last write.
+    </para>
+    <para>
+     The following example shows how to output data to the consumer of an
+     output plugin:
+     <programlisting>
+OutputPluginPrepareWrite(ctx, true);
+appendStringInfo(ctx->out, "BEGIN %u", txn->xid);
+OutputPluginWrite(ctx, true);
+     </programlisting>
+    </para>
+   </sect2>
+  </sect1>
+  <sect1 id="logicaldecoding-writer">
+   <title>Logical Decoding Output Writers</title>
+   <para>
+    It is possible to add more output methods in addition to the SQL and
+    replication protocol variants for consuming logical replication data. For
+    details look at the implementation of the SQL interface functions
+    in <filename>src/backend/replication/logical/logicalfuncs.c</filename>.
+    Essentially three functions need to be provided, one to read WAL, one to
+    prepare writing output, and one to write the output
+    (see <xref linkend="logicaldecoding-output-plugin-output">).
+   </para>
+  </sect1>
+  <sect1 id="logicaldecoding-synchronous">
+   <title>Synchronous replication support for Logical Decoding</title>
+   <para>
+    The Logical Decoding support in <productname>PostgreSQL</productname> may
+    be used to to build <link linkend="synchronous-replication">synchronous
+    replication</link> solutions with the same user interface as synchronous
+    replication for <link linkend="streaming-replication">streaming
+    replication</link> if the walsender interface
+    (see <xref linkend="logicaldecoding-walsender">) is used to stream out
+    data. Clients have to send <literal>Standby status update (F)</literal>
+    (see <xref linkend="protocol-replication">) messages, just like streaming
+    replication clients do.
+   </para>
+   <note>
+    <para>
+     A synchronous replica receiving changes via logical decoding will work in
+     the scope of a single database. Since, in contrast to
+     that, <parameter>synchronous_standby_names</parameter> currently is
+     server wide, this means that if more than one database in a cluster
+     require the use of synchronous replication it won't work properly if a
+     replica using logical replication is contained
+     in <parameter>synchronous_standby_names</parameter>. Essentially using a
+     logical replica as a synchronous replica requires that only one database
+     in a cluster is actively used.
+     </para>
+   </note>
+  </sect1>
+ </chapter>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index b47bf52..9bde108 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -219,6 +219,7 @@
 
   &spi;
   &bgworker;
+  &logicaldecoding;
 
  </part>
 
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index cb2dfb2..b13304a 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1309,16 +1309,30 @@ the simple query protocol can be used in walsender mode.
 Passing <literal>database</> as the value instructs walsender to connect to
 the database specified in the <literal>dbname</> parameter, which will allow
 the connection to be used for logical replication from that database.
+</para>
+<para>
+ For the purpose of testing replication commands, you can make a replication
+ connection via <application>psql</application> or any other <literal>libpq</literal>-using
+ tool with a connection string including the <literal>replication</literal> option,
+ e.g.:
+ <programlisting>
+  psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
+ </programlisting>
+ However it is often more useful to use
+ <application>pg_receivexlog</application> (for physical replication) or
+ <application>pg_recvlogical</application> (for logical replication).
+</para>
 
+<para>
 The commands accepted in walsender mode are:
-
 <variablelist>
   <varlistentry>
     <term>IDENTIFY_SYSTEM</term>
     <listitem>
      <para>
-      Requests the server to identify itself. Server replies with a result
-      set of a single row, containing four fields:
+      Requests the server to identify itself. Does not require a database name
+      to be specified for the connection. Server replies with a result set of a
+      single row, containing four fields:
      </para>
 
      <para>
@@ -1381,7 +1395,8 @@ The commands accepted in walsender mode are:
     <listitem>
      <para>
       Requests the server to send over the timeline history file for timeline
-      <replaceable class="parameter">tli</replaceable>.  Server replies with a
+      <replaceable class="parameter">tli</replaceable>. Does not require a database
+      name to be specified for the connection. Server replies with a
       result set of a single row, containing two fields:
      </para>
 
@@ -1764,17 +1779,55 @@ The commands accepted in walsender mode are:
      </para>
     </listitem>
   </varlistentry>
+  <varlistentry>
+    <term><literal>START_REPLICATION</literal> <literal>SLOT</literal> <replaceable class="parameter">slotname</> <literal>LOGICAL</literal> <replaceable class="parameter">XXX/XXX</></term>
+    <listitem>
+     <para>
+      Instructs server to start streaming WAL for logical replication, starting
+      at WAL position <replaceable class="parameter">XXX/XXX</>. The server can
+      reply with an error, e.g. if the requested section of WAL has already
+      been recycled. On success, server responds with a CopyBothResponse
+      message, and then starts to stream WAL to the frontend.
+     </para>
+     <para>
+      The output plugin associated with the selected slot is used
+      to process the output for streaming.
+     </para>
+     <variablelist>
+      <varlistentry>
+       <term><literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
+       <listitem>
+         <para>
+          The name of the slot to stream changes from. This parameter is required,
+          and must correspond to an existing logical replication slot created
+          with <literal>CREATE_REPLICATION_SLOT</literal> in
+          <literal>LOGICAL</literal> mode.
+         </para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><replaceable class="parameter">XXX/XXX</></term>
+       <listitem>
+        <para>
+         The WAL position to begin streaming at.
+        </para>
+       </listitem>
+      </varlistentry>
+     </variablelist>
+    </listitem>
+  </varlistentry>
 
   <varlistentry>
-    <term><literal>DROP_REPLICATION_SLOT</literal> <replaceable class="parameter">slotname</></term>
+    <term><literal>DROP_REPLICATION_SLOT</literal> <literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
     <listitem>
      <para>
-      Drops a replication slot, freeing any reserved server-side resources. If
-      the slot is currently in use by an active connection, this command fails.
+      Drops a physical or logical replication slot, freeing any reserved server-side
+      resources. If the slot is currently in use by an active connection this command
+      fails.
      </para>
      <variablelist>
       <varlistentry>
-       <term><replaceable class="parameter">slotname</></term>
+       <term><literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
        <listitem>
          <para>
           The name of the slot to drop.
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index ce7a5e3..1b0962c 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -183,6 +183,7 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY pgDumpall          SYSTEM "pg_dumpall.sgml">
 <!ENTITY pgIsready          SYSTEM "pg_isready.sgml">
 <!ENTITY pgReceivexlog      SYSTEM "pg_receivexlog.sgml">
+<!ENTITY pgRecvlogical      SYSTEM "pg_recvlogical.sgml">
 <!ENTITY pgResetxlog        SYSTEM "pg_resetxlog.sgml">
 <!ENTITY pgRestore          SYSTEM "pg_restore.sgml">
 <!ENTITY postgres           SYSTEM "postgres-ref.sgml">
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 2b02e66..4847d66 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -580,7 +580,7 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-REPLICA-IDENTITY">
     <term><literal>REPLICA IDENTITY</literal></term>
     <listitem>
      <para>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index fc7ad09..2a985b8 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -137,7 +137,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
 
   <variablelist>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-TEMPORARY">
     <term><literal>TEMPORARY</> or <literal>TEMP</></term>
     <listitem>
      <para>
@@ -171,7 +171,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-UNLOGGED">
     <term><literal>UNLOGGED</></term>
     <listitem>
      <para>
@@ -1051,6 +1051,17 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>user_catalog_table</literal> (<type>boolean</type>)</term>
+    <listitem>
+     <para>
+      Declare a table as an additional catalog table, e.g. for the purpose of
+      logical replication. See
+      <xref linkend="logicaldecoding-capabilities"> for details.
+     </para>
+    </listitem>
+   </varlistentry>
+
    </variablelist>
 
   </refsect2>
diff --git a/doc/src/sgml/ref/pg_recvlogical.sgml b/doc/src/sgml/ref/pg_recvlogical.sgml
new file mode 100644
index 0000000..df22bba
--- /dev/null
+++ b/doc/src/sgml/ref/pg_recvlogical.sgml
@@ -0,0 +1,305 @@
+<!--
+doc/src/sgml/ref/pg_recvlogical.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="app-pgrecvlogical">
+ <refmeta>
+  <refentrytitle><application>pg_recvlogical</application></refentrytitle>
+  <manvolnum>1</manvolnum>
+  <refmiscinfo>Application</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>pg_recvlogical</refname>
+  <refpurpose>Control logical decoding (see <xref linkend="logicaldecoding">)
+   streams over a walsender connection.</refpurpose>
+ </refnamediv>
+
+ <indexterm zone="app-pgrecvlogical">
+  <primary>pg_recvlogical</primary>
+ </indexterm>
+
+ <refsynopsisdiv>
+  <cmdsynopsis>
+   <command>pg_recvlogical</command>
+   <arg rep="repeat" choice="opt"><option>option</option></arg>
+  </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="R1-APP-PGRECVLOGICAL-1">
+  <title>Description</title>
+  <para>
+   <command>pg_recvlogical</command> controls logical decoding replication
+   slots and streams data from such replication slots.
+  </para>
+  <para>
+   It creates a replication-mode connection, so it is subject to the same
+   constraints as <link
+   linkend="app-pgreceivexlog"><application>pg_receivexlog</application></link>,
+   plus those for logical replication (see <xref
+   linkend="logicaldecoding">).
+  </para>
+
+ </refsect1>
+
+ <refsect1>
+  <title>Options</title>
+
+   <para>
+    <application>pg_recvlogical</application> runs in one of three modes, which
+    control its primary action:
+
+    <variablelist>
+
+     <varlistentry>
+      <term><option>--create</option></term>
+      <listitem>
+       <para>
+        Create a new logical replication slot with the name specified in
+        <option>--slot</option>, using the output plugin
+        <option>--plugin</option>, then exit. The slot is created for the
+        database given in <option>--dbname</option>.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--start</option></term>
+      <listitem>
+       <para>
+        Begin streaming changes from the logical replication slot with the name
+        specified in <option>--slot</option>, continuing until terminated with a
+        signal. If the server side change stream ends with a server
+        shutdown / disconnect, retry in a loop unless <option>--no-loop</option>
+        is specified. The stream format is determined by the output plugin
+        specified when the slot was created.
+       </para>
+       <para>
+        You must connect to the same <option>--dbname</option> as the slot was
+        created with to stream changes from a logical replication slot.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--drop</option></term>
+      <listitem>
+       <para>
+        Drop the replication slot with the name specified
+        in <option>--slot</option>, then exit.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
+
+   </para>
+
+   <para>
+    <application>pg_recvlogical</application> supports all the usual
+    <literal>libpq</literal>-based options. These are explained in detail in
+    the documentation for
+    <link linkend="APP-PSQL"><application>psql</application></link> and for
+    <link linkend="libpq"><literal>libpq</literal></link>.
+
+    <variablelist>
+
+      <varlistentry>
+       <term><option>-U <replaceable>user</replaceable></option></term>
+       <term><option>--username <replaceable>user</replaceable></option></term>
+       <listitem>
+        <para>
+         Username to connect as. Must have a suitable <literal>pg_hba.conf</literal>
+         entry allowing <literal>replication</literal> connections. Defaults to
+         current operating system user name.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-d <replaceable>database</replaceable></option></term>
+       <term><option>--dbname <replaceable>database</replaceable></option></term>
+       <listitem>
+        <para>
+         The database to connect to in <literal>replication</literal> mode; see
+         mode descriptions for details. May be
+         a <link linkend="LIBPQ-CONNSTRING">libpq connstring</link>
+         instead. Defaults to user name.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-h <replaceable>hostname-or-ip</replaceable></option></term>
+       <term><option>--host <replaceable>hostname-or-ip</replaceable></option></term>
+       <listitem>
+        <para>
+         Host or socket to connect
+         to. See <link linkend="APP-PSQL"><application>psql</application></link>
+         and <link linkend="libpq"><literal>libpq</literal></link>
+         documentation.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-p <replaceable>port</replaceable></option></term>
+       <term><option>--port <replaceable>port</replaceable></option></term>
+       <listitem>
+        <para>
+         Port number to connect to. See
+         <link linkend="R1-APP-PSQL-3"><application>psql</application></link>
+         for an explanation of default port choices when this is not
+         specified.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-w</option></term>
+       <term><option>--no-password</option></term>
+       <listitem>
+        <para>
+         Prevent prompting for a password. Will exit with an error code if a
+         password is required but not available.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-W</option></term>
+       <term><option>--password</option></term>
+       <listitem>
+        <para>
+         Provide a password for this connection. Please use the pgservice file
+         (see <xref linkend="libpq-pgservice">) or an environment variable
+         instead of this option.
+        </para>
+       </listitem>
+      </varlistentry>
+
+     </variablelist>
+
+   </para>
+
+   <para>
+    The following command-line options control the location and format of the
+    output and other replication behaviour:
+
+    <variablelist>
+
+     <varlistentry>
+      <term><option>-f <replaceable>filename</replaceable></option></term>
+      <term><option>--file=<replaceable>filename</replaceable></option></term>
+      <listitem>
+       <para>
+        Write received and decoded transaction data into this
+        file. Use <literal>-</> for stdout.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
+     <varlistentry>
+      <term><option>-n</option></term>
+      <term><option>--no-loop</option></term>
+      <listitem>
+       <para>
+        When the connection to the server is lost, do not retry in a loop, just exit.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-P <replaceable>plugin</replaceable></option></term>
+      <term><option>--plugin=<replaceable>plugin</replaceable></option></term>
+      <listitem>
+       <para>
+        When creating a slot, use the logical decoding output
+        plugin. See <xref linkend="logicaldecoding">. This option has no
+        effect if the slot already exists.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-s <replaceable>interval_seconds</replaceable></option></term>
+      <term><option>--status-interval=<replaceable>interval_seconds</replaceable></option></term>
+      <listitem>
+       <para>
+        This option has the same effect as the option of the same name in <link
+        linkend="app-pgreceivexlog"><application>pg_receivexlog</application></link>.
+        See the description there.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-S <replaceable>slot_name</replaceable></option></term>
+      <term><option>--slot=<replaceable>slot_name</replaceable></option></term>
+      <listitem>
+       <para>
+        In <option>--start</option> mode, use the existing logical replication slot named
+        <replaceable>slot_name</replaceable>. In <option>--create</option> mode, create the
+        slot with this name. In <option>--drop</option> mode, delete the slot with this name.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-I <replaceable>lsn</replaceable></option></term>
+      <term><option>--startpos=<replaceable>lsn</replaceable></option></term>
+      <listitem>
+       <para>
+        In <option>--start</option> mode, start replication from the given
+        LSN.  For details on the effect of this, see the documentation
+        in <xref linkend="logicaldecoding">
+        and <xref linkend="protocol-replication">. Ignored in other modes.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
+
+   </para>
+
+   <para>
+
+    The following additional options are available:
+
+    <variablelist>
+
+     <varlistentry>
+       <term><option>-v</></term>
+       <term><option>--verbose</></term>
+       <listitem>
+       <para>
+        Output verbose (detailed) error messages suitable for debugging and fault diagnosis.
+       </para>
+       </listitem>
+     </varlistentry>
+
+     <varlistentry>
+       <term><option>-V</></term>
+       <term><option>--version</></term>
+       <listitem>
+       <para>
+        Print the <application>pg_recvlogical</application> version and exit.
+       </para>
+       </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-?</></term>
+      <term><option>--help</></term>
+       <listitem>
+        <para>
+         Show help about <application>pg_recvlogical</application> command line
+         arguments, and exit.
+        </para>
+       </listitem>
+      </varlistentry>
+
+    </variablelist>
+   </para>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 87e8e9e..a6575f5 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -231,6 +231,7 @@
    &pgDumpall;
    &pgIsready;
    &pgReceivexlog;
+   &pgRecvlogical;
    &pgRestore;
    &psqlRef;
    &reindexdb;
-- 
1.8.5.rc2.dirty

0004-Adapt-test_decoding-s-documentation-to-last-minute-l.patchtext/x-patch; charset=us-asciiDownload
>From 2be6826b1ac2799adc3b5356e09fca19c06165af Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Mon, 10 Mar 2014 18:40:27 +0100
Subject: [PATCH 4/7] Adapt test_decoding's documentation to last-minute
 logical decoding API changes.

---
 doc/src/sgml/test-decoding.sgml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/src/sgml/test-decoding.sgml b/doc/src/sgml/test-decoding.sgml
index 0fe3d0a..250c0d8 100644
--- a/doc/src/sgml/test-decoding.sgml
+++ b/doc/src/sgml/test-decoding.sgml
@@ -24,7 +24,7 @@
   interface, might be:
 
   <programlisting>
-postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', 'now', 'include-xids', '0');
+postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');
  location  | xid |                       data
 -----------+-----+--------------------------------------------------
  0/16D30F8 | 691 | BEGIN
-- 
1.8.5.rc2.dirty

0005-Minor-test-decoding-comment-improvements.patchtext/x-patch; charset=us-asciiDownload
>From cba7890e9f0b3afc91f4db1542d8b0c760bfe416 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 12 Mar 2014 11:53:12 +0100
Subject: [PATCH 5/7] Minor test decoding comment improvements.

As noticed by Peter Eisentraut.
---
 contrib/test_decoding/test_decoding.c     | 2 +-
 src/backend/replication/logical/logical.c | 9 ++++++---
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding/test_decoding.c
index e356c7c..31aa012 100644
--- a/contrib/test_decoding/test_decoding.c
+++ b/contrib/test_decoding/test_decoding.c
@@ -33,6 +33,7 @@
 
 PG_MODULE_MAGIC;
 
+/* These must be available to pg_dlsym() */
 extern void		_PG_init(void);
 extern void		_PG_output_plugin_init(OutputPluginCallbacks *cb);
 
@@ -43,7 +44,6 @@ typedef struct
 	bool		include_timestamp;
 } TestDecodingData;
 
-/* These must be available to pg_dlsym() */
 static void pg_decode_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 							  bool is_init);
 static void pg_decode_shutdown(LogicalDecodingContext *ctx);
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index 13a22d4..04e407a 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -12,14 +12,17 @@
  *    together provide logical decoding, primarily by providing so
  *    called LogicalDecodingContexts. The goal is to encapsulate most of the
  *    internal complexity for consumers of logical decoding, so they can
- *    create and consume a changestream with a low amount of code.
+ *    create and consume a changestream with a low amount of code. Builtin
+ *    consumers are the walsender and SQL SRF interface, but it's possible to
+ *    add further ones without changing core code, e.g. to consume changes in
+ *    a bgworker.
  *
  *    The idea is that a consumer provides three callbacks, one to read WAL,
  *    one to prepare a data write, and a final one for actually writing since
  *    their implementation depends on the type of consumer.  Check
- *    logicalfunc.c for an example implementations of a fairly simple consumer
+ *    logicalfuncs.c for an example implementation of a fairly simple consumer
  *    and a implementation of a WAL reading callback that's suitable for
- *    simpler consumers.
+ *    simple consumers.
  *-------------------------------------------------------------------------
  */
 
-- 
1.8.5.rc2.dirty

#141Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#140)
Re: Changeset Extraction v7.9.1

On Wed, Mar 12, 2014 at 2:06 PM, Andres Freund <andres@2ndquadrant.com> wrote:

Attached are the collected remaining patches. The docs might need
further additions, but it seems better to add them now.

A few questions about pg_recvlogical:

- There doesn't seem to be any provision for this tool to ever switch
from one output file to the next. That seems like a practical need.
One idea would be to have it respond to SIGHUP by reopening the
originally-named output file. Another would be to switch, after so
many bytes, to filename.1, then filename.2, etc.

- It confirms the write and flush positions, but doesn't appear to
actually flush anywhere.

- While I quite agree with your desire for stringinfo in src/common,
couldn't you use the roughly-equivalent PQExpBuffer facilities in
libpq instead?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#142Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#141)
Re: Changeset Extraction v7.9.1

On 2014-03-17 06:55:28 -0400, Robert Haas wrote:

On Wed, Mar 12, 2014 at 2:06 PM, Andres Freund <andres@2ndquadrant.com> wrote:

Attached are the collected remaining patches. The docs might need
further additions, but it seems better to add them now.

A few questions about pg_recvlogical:

- There doesn't seem to be any provision for this tool to ever switch
from one output file to the next. That seems like a practical need.
One idea would be to have it respond to SIGHUP by reopening the
originally-named output file. Another would be to switch, after so
many bytes, to filename.1, then filename.2, etc.

Hm. So far I haven't had the need, but you're right, it would be
useful. I don't like the .<n> notion, but SIGHUP would be fine with
me. I'll add that.

- It confirms the write and flush positions, but doesn't appear to
actually flush anywhere.

Yea. The reason it reports the flush position is that it allows to test
sync rep. I don't think other usecases will appreciate frequent
fsyncs... Maybe make it optional?

- While I quite agree with your desire for stringinfo in src/common,
couldn't you use the roughly-equivalent PQExpBuffer facilities in
libpq instead?

Yes.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#143Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#142)
Re: Changeset Extraction v7.9.1

On Mon, Mar 17, 2014 at 7:27 AM, Andres Freund <andres@2ndquadrant.com> wrote:

- There doesn't seem to be any provision for this tool to ever switch
from one output file to the next. That seems like a practical need.
One idea would be to have it respond to SIGHUP by reopening the
originally-named output file. Another would be to switch, after so
many bytes, to filename.1, then filename.2, etc.

Hm. So far I haven't had the need, but you're right, it would be
useful. I don't like the .<n> notion, but SIGHUP would be fine with
me. I'll add that.

Cool.

- It confirms the write and flush positions, but doesn't appear to
actually flush anywhere.

Yea. The reason it reports the flush position is that it allows to test
sync rep. I don't think other usecases will appreciate frequent
fsyncs... Maybe make it optional?

Well, as I'm sure you recognize, if you're actually trying to build a
replication solution with this tool, you can't let the database throw
away the state required to suck changes out of the database unless
you've got those changes safely stored away somewhere else. Now, of
course, if you don't acknowledge to the database that the stuff is on
disk, you're going to get data file bloat and excess WAL retention,
unlucky you. But acknowledging that you've got the changes when
they're not actually on disk doesn't actually provide the guarantees
you went to so much trouble to build in to the mechanism. So the
no-flush version really can ONLY ever be useful for testing, AFAICS,
or if you really don't care that much whether it can survive a server
crash.

Perhaps there could be a switch for an fsync interval, or something
like that. The default could be, say, to fsync every 10 seconds. And
if you want to change it, then go ahead; 0 disables. Writing to
standard output would be documented as unreliable. Other ideas
welcome.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#144Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#143)
Re: Changeset Extraction v7.9.1

On 2014-03-17 08:00:22 -0400, Robert Haas wrote:

Yea. The reason it reports the flush position is that it allows to test
sync rep. I don't think other usecases will appreciate frequent
fsyncs... Maybe make it optional?

Well, as I'm sure you recognize, if you're actually trying to build a
replication solution with this tool, you can't let the database throw
away the state required to suck changes out of the database unless
you've got those changes safely stored away somewhere else.

Hm. I don't think a replication tool will use pg_recvlogical, do you
really forsee that? The main use cases for it that I can see are
testing/development of output plugins and logging/auditing.

That's not to say safe writing method isn't interesting tho.

Perhaps there could be a switch for an fsync interval, or something
like that. The default could be, say, to fsync every 10 seconds. And
if you want to change it, then go ahead; 0 disables. Writing to
standard output would be documented as unreliable. Other ideas
welcome.

Hm. That'll be a bit nasty. fsync() is async signal safe, but it's still
forbidden to be called from a signal on windows IIRC. I guess we can
couple it with the standby_message_timeout stuff.

Unless you have a better idea?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#145Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#143)
Re: Changeset Extraction v7.9.1

On 2014-03-17 08:00:22 -0400, Robert Haas wrote:

On Mon, Mar 17, 2014 at 7:27 AM, Andres Freund <andres@2ndquadrant.com> wrote:

- There doesn't seem to be any provision for this tool to ever switch
from one output file to the next. That seems like a practical need.
One idea would be to have it respond to SIGHUP by reopening the
originally-named output file. Another would be to switch, after so
many bytes, to filename.1, then filename.2, etc.

Hm. So far I haven't had the need, but you're right, it would be
useful. I don't like the .<n> notion, but SIGHUP would be fine with
me. I'll add that.

Cool.

So, I've implemented this, but it won't work on windows afaics. There's
no SIGHUP on windows, and the signal emulation code used in the backend
is backend only...
I'll be happy enough to declare this a known limitation for
now. Arguments to the contrary, best complemented with a solution?

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#146Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#144)
Re: Changeset Extraction v7.9.1

On Mon, Mar 17, 2014 at 8:29 AM, Andres Freund <andres@2ndquadrant.com> wrote:

Perhaps there could be a switch for an fsync interval, or something
like that. The default could be, say, to fsync every 10 seconds. And
if you want to change it, then go ahead; 0 disables. Writing to
standard output would be documented as unreliable. Other ideas
welcome.

Hm. That'll be a bit nasty. fsync() is async signal safe, but it's still
forbidden to be called from a signal on windows IIRC. I guess we can
couple it with the standby_message_timeout stuff.

Eh... I don't see any need to involve signals. I'd just check after
each write() whether enough time has passed, or something like that.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#147Robert Haas
robertmhaas@gmail.com
In reply to: Andres Freund (#145)
Re: Changeset Extraction v7.9.1

On Mon, Mar 17, 2014 at 8:58 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-03-17 08:00:22 -0400, Robert Haas wrote:

On Mon, Mar 17, 2014 at 7:27 AM, Andres Freund <andres@2ndquadrant.com> wrote:

- There doesn't seem to be any provision for this tool to ever switch
from one output file to the next. That seems like a practical need.
One idea would be to have it respond to SIGHUP by reopening the
originally-named output file. Another would be to switch, after so
many bytes, to filename.1, then filename.2, etc.

Hm. So far I haven't had the need, but you're right, it would be
useful. I don't like the .<n> notion, but SIGHUP would be fine with
me. I'll add that.

Cool.

So, I've implemented this, but it won't work on windows afaics. There's
no SIGHUP on windows, and the signal emulation code used in the backend
is backend only...
I'll be happy enough to declare this a known limitation for
now. Arguments to the contrary, best complemented with a solution?

Blarg. I don't really like that, but I admit I don't have a better
idea, unless it's to go back to the suffix idea, with something like
--file-size-limit=XXX to trigger the switch.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#148Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#146)
Re: Changeset Extraction v7.9.1

On 2014-03-17 09:13:38 -0400, Robert Haas wrote:

On Mon, Mar 17, 2014 at 8:29 AM, Andres Freund <andres@2ndquadrant.com> wrote:

Perhaps there could be a switch for an fsync interval, or something
like that. The default could be, say, to fsync every 10 seconds. And
if you want to change it, then go ahead; 0 disables. Writing to
standard output would be documented as unreliable. Other ideas
welcome.

Hm. That'll be a bit nasty. fsync() is async signal safe, but it's still
forbidden to be called from a signal on windows IIRC. I guess we can
couple it with the standby_message_timeout stuff.

Eh... I don't see any need to involve signals. I'd just check after
each write() whether enough time has passed, or something like that.

What if no new writes are needed? Because e.g. there's either no write
activity on the primary or all writes are in another database or
somesuch?
I think checking in sendFeedback() is the best bet...

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#149Andres Freund
andres@2ndquadrant.com
In reply to: Robert Haas (#147)
Re: Changeset Extraction v7.9.1

On 2014-03-17 09:14:51 -0400, Robert Haas wrote:

On Mon, Mar 17, 2014 at 8:58 AM, Andres Freund <andres@2ndquadrant.com> wrote:

On 2014-03-17 08:00:22 -0400, Robert Haas wrote:

On Mon, Mar 17, 2014 at 7:27 AM, Andres Freund <andres@2ndquadrant.com> wrote:

- There doesn't seem to be any provision for this tool to ever switch
from one output file to the next. That seems like a practical need.
One idea would be to have it respond to SIGHUP by reopening the
originally-named output file. Another would be to switch, after so
many bytes, to filename.1, then filename.2, etc.

Hm. So far I haven't had the need, but you're right, it would be
useful. I don't like the .<n> notion, but SIGHUP would be fine with
me. I'll add that.

Cool.

So, I've implemented this, but it won't work on windows afaics. There's
no SIGHUP on windows, and the signal emulation code used in the backend
is backend only...
I'll be happy enough to declare this a known limitation for
now. Arguments to the contrary, best complemented with a solution?

Blarg. I don't really like that, but I admit I don't have a better
idea, unless it's to go back to the suffix idea, with something like
--file-size-limit=XXX to trigger the switch.

I think the SIGHUP support can be a useful independently from
--file-size-limit, so adding it seems like a good idea anyway. I think
anything more advanced than the SIGHUP stuff is for another day.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#150Andres Freund
andres@2ndquadrant.com
In reply to: Andres Freund (#148)
2 attachment(s)
Re: Changeset Extraction v7.9.1

Hi,

On 2014-03-17 14:16:38 +0100, Andres Freund wrote:

On 2014-03-17 09:13:38 -0400, Robert Haas wrote:

On Mon, Mar 17, 2014 at 8:29 AM, Andres Freund <andres@2ndquadrant.com> wrote:

Perhaps there could be a switch for an fsync interval, or something
like that. The default could be, say, to fsync every 10 seconds. And
if you want to change it, then go ahead; 0 disables. Writing to
standard output would be documented as unreliable. Other ideas
welcome.

Hm. That'll be a bit nasty. fsync() is async signal safe, but it's still
forbidden to be called from a signal on windows IIRC. I guess we can
couple it with the standby_message_timeout stuff.

Eh... I don't see any need to involve signals. I'd just check after
each write() whether enough time has passed, or something like that.

What if no new writes are needed? Because e.g. there's either no write
activity on the primary or all writes are in another database or
somesuch?
I think checking in sendFeedback() is the best bet...

So, I've tried to implement the things you asked for. Changes:
* reopen config files on SIGHUP to allow for rotating files
* use PQEexpBuffer instead of handrolling stuff
* fsync the output file if either --fsync-interval seconds passed, or
the server asks for feedback.
* report back a correct flush position.
* updated documentation

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

0001-Add-pg_recvlogical-a-commandline-tool-to-receive-dat.patchtext/x-patch; charset=us-asciiDownload
>From 9c07a2f60d34c96b702ccf0cc76b8bf2739b9c65 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 00:15:39 +0100
Subject: [PATCH 1/2] Add pg_recvlogical, a commandline tool to receive data
 logical decoding data.

Andres Freund
---
 src/bin/pg_basebackup/.gitignore       |   1 +
 src/bin/pg_basebackup/Makefile         |  11 +-
 src/bin/pg_basebackup/nls.mk           |   2 +-
 src/bin/pg_basebackup/pg_recvlogical.c | 978 +++++++++++++++++++++++++++++++++
 src/bin/pg_basebackup/receivelog.c     | 137 +----
 src/bin/pg_basebackup/receivelog.h     |   2 +
 src/bin/pg_basebackup/streamutil.c     | 119 +++-
 src/bin/pg_basebackup/streamutil.h     |  10 +
 8 files changed, 1135 insertions(+), 125 deletions(-)
 create mode 100644 src/bin/pg_basebackup/pg_recvlogical.c

diff --git a/src/bin/pg_basebackup/.gitignore b/src/bin/pg_basebackup/.gitignore
index 1334a1f..7abea15 100644
--- a/src/bin/pg_basebackup/.gitignore
+++ b/src/bin/pg_basebackup/.gitignore
@@ -1,2 +1,3 @@
 /pg_basebackup
 /pg_receivexlog
+/pg_recvlogical
diff --git a/src/bin/pg_basebackup/Makefile b/src/bin/pg_basebackup/Makefile
index 17c91af..346560e 100644
--- a/src/bin/pg_basebackup/Makefile
+++ b/src/bin/pg_basebackup/Makefile
@@ -20,7 +20,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
 
 OBJS=receivelog.o streamutil.o $(WIN32RES)
 
-all: pg_basebackup pg_receivexlog
+all: pg_basebackup pg_receivexlog pg_recvlogical
 
 pg_basebackup: pg_basebackup.o $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_basebackup.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
@@ -28,9 +28,13 @@ pg_basebackup: pg_basebackup.o $(OBJS) | submake-libpq submake-libpgport
 pg_receivexlog: pg_receivexlog.o $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_receivexlog.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
+pg_recvlogical: pg_recvlogical.o $(OBJS) | submake-libpq submake-libpgport
+	$(CC) $(CFLAGS) pg_recvlogical.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+
 install: all installdirs
 	$(INSTALL_PROGRAM) pg_basebackup$(X) '$(DESTDIR)$(bindir)/pg_basebackup$(X)'
 	$(INSTALL_PROGRAM) pg_receivexlog$(X) '$(DESTDIR)$(bindir)/pg_receivexlog$(X)'
+	$(INSTALL_PROGRAM) pg_recvlogical$(X) '$(DESTDIR)$(bindir)/pg_recvlogical$(X)'
 
 installdirs:
 	$(MKDIR_P) '$(DESTDIR)$(bindir)'
@@ -38,6 +42,9 @@ installdirs:
 uninstall:
 	rm -f '$(DESTDIR)$(bindir)/pg_basebackup$(X)'
 	rm -f '$(DESTDIR)$(bindir)/pg_receivexlog$(X)'
+	rm -f '$(DESTDIR)$(bindir)/pg_recvlogical$(X)'
 
 clean distclean maintainer-clean:
-	rm -f pg_basebackup$(X) pg_receivexlog$(X) $(OBJS) pg_basebackup.o pg_receivexlog.o
+	rm -f pg_basebackup$(X) pg_receivexlog$(X) pg_recvlogical$(X) \
+		pg_basebackup.o pg_receivexlog.o pg_recvlogical.o \
+		$(OBJS)
diff --git a/src/bin/pg_basebackup/nls.mk b/src/bin/pg_basebackup/nls.mk
index e1c96dd..29df4bc 100644
--- a/src/bin/pg_basebackup/nls.mk
+++ b/src/bin/pg_basebackup/nls.mk
@@ -1,4 +1,4 @@
 # src/bin/pg_basebackup/nls.mk
 CATALOG_NAME     = pg_basebackup
 AVAIL_LANGUAGES  = cs de es fr it ja pl pt_BR ru zh_CN
-GETTEXT_FILES    = pg_basebackup.c pg_receivexlog.c receivelog.c streamutil.c ../../common/fe_memutils.c
+GETTEXT_FILES    = pg_basebackup.c pg_receivexlog.c pg_recvlogical.c receivelog.c streamutil.c ../../common/fe_memutils.c
diff --git a/src/bin/pg_basebackup/pg_recvlogical.c b/src/bin/pg_basebackup/pg_recvlogical.c
new file mode 100644
index 0000000..af5825e
--- /dev/null
+++ b/src/bin/pg_basebackup/pg_recvlogical.c
@@ -0,0 +1,978 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_recvlogical.c - receive data from a logical decoding slot in a streaming fashion
+ *					  and write it to to a local file.
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		  src/bin/pg_basebackup/pg_recvlogical.c
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* local includes */
+#include "streamutil.h"
+
+#include "access/xlog_internal.h"
+#include "common/fe_memutils.h"
+#include "getopt_long.h"
+#include "libpq-fe.h"
+#include "libpq/pqsignal.h"
+#include "pqexpbuffer.h"
+
+
+/* Time to sleep between reconnection attempts */
+#define RECONNECT_SLEEP_TIME 5
+
+/* Global Options */
+static char    *outfile = NULL;
+static int		verbose = 0;
+static int		noloop = 0;
+static int		standby_message_timeout = 10 * 1000;		/* 10 sec = default */
+static int		fsync_interval = 10 * 1000;		/* 10 sec = default */
+static XLogRecPtr startpos = InvalidXLogRecPtr;
+static bool		do_create_slot = false;
+static bool		do_start_slot = false;
+static bool		do_drop_slot = false;
+
+/* filled pairwise with option, value. value may be NULL */
+static char	  **options;
+static size_t	noptions = 0;
+static const char *plugin = "test_decoding";
+
+/* Global State */
+static int		outfd = -1;
+static volatile sig_atomic_t time_to_abort = false;
+static volatile sig_atomic_t output_reopen = false;
+static int64	output_last_fsync = -1;
+static bool		output_unsynced = false;
+static XLogRecPtr output_written_lsn = InvalidXLogRecPtr;
+static XLogRecPtr output_fsync_lsn = InvalidXLogRecPtr;
+
+static void usage(void);
+static void StreamLog();
+static void disconnect_and_exit(int code);
+
+static void
+usage(void)
+{
+	printf(_("%s receives PostgreSQL logical change stream.\n\n"),
+		   progname);
+	printf(_("Usage:\n"));
+	printf(_("  %s [OPTION]...\n"), progname);
+	printf(_("\nOptions:\n"));
+	printf(_("  -f, --file=FILE        receive log into this file. - for stdout\n"));
+	printf(_("  -n, --no-loop          do not loop on connection lost\n"));
+	printf(_("  -v, --verbose          output verbose messages\n"));
+	printf(_("  -V, --version          output version information, then exit\n"));
+	printf(_("  -?, --help             show this help, then exit\n"));
+	printf(_("\nConnection options:\n"));
+	printf(_("  -d, --dbname=DBNAME    database to connect to\n"));
+	printf(_("  -h, --host=HOSTNAME    database server host or socket directory\n"));
+	printf(_("  -p, --port=PORT        database server port number\n"));
+	printf(_("  -U, --username=NAME    connect as specified database user\n"));
+	printf(_("  -w, --no-password      never prompt for password\n"));
+	printf(_("  -W, --password         force password prompt (should happen automatically)\n"));
+	printf(_("\nReplication options:\n"));
+	printf(_("  -F  --fsync-interval=INTERVAL\n"
+			 "                         frequency of syncs to the output file (in seconds, defaults to 10)\n"));
+	printf(_("  -o, --option=NAME[=VALUE]\n"
+			 "                         Specify option NAME with optional value VAL, to be passed\n"
+			 "                         to the output plugin\n"));
+	printf(_("  -P, --plugin=PLUGIN    use output plugin PLUGIN (defaults to test_decoding)\n"));
+	printf(_("  -s, --status-interval=INTERVAL\n"
+			 "                         time between status packets sent to server (in seconds, defaults to 10)\n"));
+	printf(_("  -S, --slot=SLOT        use existing replication slot SLOT instead of starting a new one\n"));
+	printf(_("  -I, --startpos=PTR     Where in an existing slot should the streaming start\n"));
+	printf(_("\nAction to be performed:\n"));
+	printf(_("      --create           create a new replication slot (for the slotname see --slot)\n"));
+	printf(_("      --start            start streaming in a replication slot (for the slotname see --slot)\n"));
+	printf(_("      --drop             drop the replication slot (for the slotname see --slot)\n"));
+	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
+}
+
+/*
+ * Send a Standby Status Update message to server.
+ */
+static bool
+sendFeedback(PGconn *conn, int64 now, bool force, bool replyRequested)
+{
+	static XLogRecPtr last_written_lsn = InvalidXLogRecPtr;
+	static XLogRecPtr last_fsync_lsn = InvalidXLogRecPtr;
+
+	char		replybuf[1 + 8 + 8 + 8 + 8 + 1];
+	int			len = 0;
+
+	/*
+	 * we normally don't want to send superflous feedbacks, but if it's
+	 * because of a timeout we need to, otherwise replication_timeout will
+	 * kill us.
+	 */
+	if (!force &&
+		last_written_lsn == output_written_lsn &&
+		last_fsync_lsn != output_fsync_lsn)
+		return true;
+
+	if (verbose)
+		fprintf(stderr,
+				_("%s: confirming write up to %X/%X, flush to %X/%X (slot %s)\n"),
+				progname,
+				(uint32) (output_written_lsn >> 32), (uint32) output_written_lsn,
+				(uint32) (output_fsync_lsn >> 32), (uint32) output_fsync_lsn,
+				replication_slot);
+
+	replybuf[len] = 'r';
+	len += 1;
+	fe_sendint64(output_written_lsn, &replybuf[len]);		/* write */
+	len += 8;
+	fe_sendint64(output_fsync_lsn, &replybuf[len]);		/* flush */
+	len += 8;
+	fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
+	len += 8;
+	fe_sendint64(now, &replybuf[len]);			/* sendTime */
+	len += 8;
+	replybuf[len] = replyRequested ? 1 : 0;		/* replyRequested */
+	len += 1;
+
+	startpos = output_written_lsn;
+	last_written_lsn = output_written_lsn;
+	last_fsync_lsn = output_fsync_lsn;
+
+	if (PQputCopyData(conn, replybuf, len) <= 0 || PQflush(conn))
+	{
+		fprintf(stderr, _("%s: could not send feedback packet: %s"),
+				progname, PQerrorMessage(conn));
+		return false;
+	}
+
+	return true;
+}
+
+static void
+disconnect_and_exit(int code)
+{
+	if (conn != NULL)
+		PQfinish(conn);
+
+	exit(code);
+}
+
+static bool
+OutputFsync(int64 now)
+{
+	output_last_fsync = now;
+
+	output_fsync_lsn = output_written_lsn;
+
+	if (fsync_interval <= 0)
+		return true;
+
+	if (!output_unsynced)
+		return true;
+
+	output_unsynced = false;
+
+	/* Accept EINVAL, in case output is writing to a pipe or similar. */
+	if (fsync(outfd) != 0 && errno != EINVAL)
+	{
+		fprintf(stderr,
+				_("%s: could not fsync log file \"%s\": %s\n"),
+				progname, outfile, strerror(errno));
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * Start the log streaming
+ */
+static void
+StreamLog(void)
+{
+	PGresult   *res;
+	char	   *copybuf = NULL;
+	int64		last_status = -1;
+	int			i;
+	PQExpBuffer query;
+
+	output_written_lsn = InvalidXLogRecPtr;
+	output_fsync_lsn = InvalidXLogRecPtr;
+
+	query = createPQExpBuffer();
+
+	/*
+	 * Connect in replication mode to the server
+	 */
+	if (!conn)
+		conn = GetConnection();
+	if (!conn)
+		/* Error message already written in GetConnection() */
+		return;
+
+	/*
+	 * Start the replication
+	 */
+	if (verbose)
+		fprintf(stderr,
+				_("%s: starting log streaming at %X/%X (slot %s)\n"),
+				progname, (uint32) (startpos >> 32), (uint32) startpos,
+				replication_slot);
+
+	/* Initiate the replication stream at specified location */
+	appendPQExpBuffer(query, "START_REPLICATION SLOT \"%s\" LOGICAL %X/%X",
+					  replication_slot, (uint32) (startpos >> 32), (uint32) startpos);
+
+	/* print options if there are any */
+	if (noptions)
+		appendPQExpBufferStr(query, " (");
+
+	for (i = 0; i < noptions; i++)
+	{
+		/* separator */
+		if (i > 0)
+			appendPQExpBufferStr(query, ", ");
+
+		/* write option name */
+		appendPQExpBuffer(query, "\"%s\"", options[(i * 2)]);
+
+		/* write option value if specified */
+		if (options[(i * 2) + 1] != NULL)
+			appendPQExpBuffer(query, " '%s'", options[(i * 2) + 1]);
+	}
+
+	if (noptions)
+		appendPQExpBufferChar(query, ')');
+
+	res = PQexec(conn, query->data);
+	if (PQresultStatus(res) != PGRES_COPY_BOTH)
+	{
+		fprintf(stderr, _("%s: could not send replication command \"%s\": %s\n"),
+				progname, query->data, PQresultErrorMessage(res));
+		PQclear(res);
+		goto error;
+	}
+	PQclear(res);
+	resetPQExpBuffer(query);
+
+	if (verbose)
+		fprintf(stderr,
+				_("%s: initiated streaming\n"),
+				progname);
+
+	while (!time_to_abort)
+	{
+		int			r;
+		int			bytes_left;
+		int			bytes_written;
+		int64		now;
+		int			hdr_len;
+
+		if (copybuf != NULL)
+		{
+			PQfreemem(copybuf);
+			copybuf = NULL;
+		}
+
+		/*
+		 * Potentially send a status message to the master
+		 */
+		now = feGetCurrentTimestamp();
+
+		if (outfd != -1 &&
+			feTimestampDifferenceExceeds(output_last_fsync, now,
+										 fsync_interval))
+		{
+			if (!OutputFsync(now))
+				goto error;
+		}
+
+		if (standby_message_timeout > 0 &&
+			feTimestampDifferenceExceeds(last_status, now,
+										 standby_message_timeout))
+		{
+			/* Time to send feedback! */
+			if (!sendFeedback(conn, now, true, false))
+				goto error;
+
+			last_status = now;
+		}
+
+		r = PQgetCopyData(conn, &copybuf, 1);
+		if (r == 0)
+		{
+			/*
+			 * In async mode, and no data available. We block on reading but
+			 * not more than the specified timeout, so that we can send a
+			 * response back to the client.
+			 */
+			fd_set		input_mask;
+			int64		message_target = 0;
+			int64		fsync_target = 0;
+			struct timeval timeout;
+			struct timeval *timeoutptr;
+
+			FD_ZERO(&input_mask);
+			FD_SET(PQsocket(conn), &input_mask);
+
+			/* Compute when we need to wakeup to send a keepalive message. */
+			if (standby_message_timeout)
+				message_target = last_status + (standby_message_timeout - 1) *
+					((int64) 1000);
+
+			/* Compute when we need to wakeup to fsync the output file. */
+			if (fsync_interval > 0 && output_unsynced)
+				fsync_target = output_last_fsync + (fsync_interval - 1) *
+					((int64) 1000);
+
+			/* Now compute when to wakeup. */
+			if (message_target > 0 || fsync_target > 0)
+			{
+				int64		targettime;
+				long		secs;
+				int			usecs;
+
+				targettime = message_target;
+
+				if (fsync_target > 0 && fsync_target < targettime)
+					targettime = fsync_target;
+
+				feTimestampDifference(now,
+									  targettime,
+									  &secs,
+									  &usecs);
+				if (secs <= 0)
+					timeout.tv_sec = 1; /* Always sleep at least 1 sec */
+				else
+					timeout.tv_sec = secs;
+				timeout.tv_usec = usecs;
+				timeoutptr = &timeout;
+			}
+
+			r = select(PQsocket(conn) + 1, &input_mask, NULL, NULL, timeoutptr);
+			if (r == 0 || (r < 0 && errno == EINTR))
+			{
+				/*
+				 * Got a timeout or signal. Continue the loop and either
+				 * deliver a status packet to the server or just go back into
+				 * blocking.
+				 */
+				continue;
+			}
+			else if (r < 0)
+			{
+				fprintf(stderr, _("%s: select() failed: %s\n"),
+						progname, strerror(errno));
+				goto error;
+			}
+
+			/* Else there is actually data on the socket */
+			if (PQconsumeInput(conn) == 0)
+			{
+				fprintf(stderr,
+						_("%s: could not receive data from WAL stream: %s"),
+						progname, PQerrorMessage(conn));
+				goto error;
+			}
+			continue;
+		}
+
+		/* End of copy stream */
+		if (r == -1)
+			break;
+
+		/* Failure while reading the copy stream */
+		if (r == -2)
+		{
+			fprintf(stderr, _("%s: could not read COPY data: %s"),
+					progname, PQerrorMessage(conn));
+			goto error;
+		}
+
+		/* Check the message type. */
+		if (copybuf[0] == 'k')
+		{
+			int			pos;
+			bool		replyRequested;
+			XLogRecPtr	walEnd;
+
+			/*
+			 * Parse the keepalive message, enclosed in the CopyData message.
+			 * We just check if the server requested a reply, and ignore the
+			 * rest.
+			 */
+			pos = 1;			/* skip msgtype 'k' */
+			walEnd = fe_recvint64(&copybuf[pos]);
+			output_written_lsn = Max(walEnd, output_written_lsn);
+
+			pos += 8;			/* read walEnd */
+
+			pos += 8;			/* skip sendTime */
+
+			if (r < pos + 1)
+			{
+				fprintf(stderr, _("%s: streaming header too small: %d\n"),
+						progname, r);
+				goto error;
+			}
+			replyRequested = copybuf[pos];
+
+			/* If the server requested an immediate reply, send one. */
+			if (replyRequested)
+			{
+				/* fsync data, so we send a recent flush pointer */
+				if (!OutputFsync(now))
+					goto error;
+
+				now = feGetCurrentTimestamp();
+				if (!sendFeedback(conn, now, true, false))
+					goto error;
+				last_status = now;
+			}
+			continue;
+		}
+		else if (copybuf[0] != 'w')
+		{
+			fprintf(stderr, _("%s: unrecognized streaming header: \"%c\"\n"),
+					progname, copybuf[0]);
+			goto error;
+		}
+
+
+		/*
+		 * Read the header of the XLogData message, enclosed in the CopyData
+		 * message. We only need the WAL location field (dataStart), the rest
+		 * of the header is ignored.
+		 */
+		hdr_len = 1;			/* msgtype 'w' */
+		hdr_len += 8;			/* dataStart */
+		hdr_len += 8;			/* walEnd */
+		hdr_len += 8;			/* sendTime */
+		if (r < hdr_len + 1)
+		{
+			fprintf(stderr, _("%s: streaming header too small: %d\n"),
+					progname, r);
+			goto error;
+		}
+
+		/* Extract WAL location for this block */
+		{
+			XLogRecPtr	temp = fe_recvint64(&copybuf[1]);
+
+			output_written_lsn = Max(temp, output_written_lsn);
+		}
+
+		/* redirect output to stdout */
+		if (outfd == -1 && strcmp(outfile, "-") == 0)
+		{
+			outfd = fileno(stdout);
+		}
+
+		/* got SIGHUP, close output file */
+		if (outfd != -1 && output_reopen)
+		{
+			now = feGetCurrentTimestamp();
+			if (!OutputFsync(now))
+				goto error;
+			close(outfd);
+			outfd = -1;
+			output_reopen = false;
+		}
+
+		if (outfd == -1)
+		{
+
+			outfd = open(outfile, O_CREAT | O_APPEND | O_WRONLY | PG_BINARY,
+						 S_IRUSR | S_IWUSR);
+			if (outfd == -1)
+			{
+				fprintf(stderr,
+						_("%s: could not open log file \"%s\": %s\n"),
+						progname, outfile, strerror(errno));
+				goto error;
+			}
+		}
+
+		bytes_left = r - hdr_len;
+		bytes_written = 0;
+
+		/* signal that a fsync is needed */
+		output_unsynced = true;
+
+		while (bytes_left)
+		{
+			int			ret;
+
+			ret = write(outfd,
+						copybuf + hdr_len + bytes_written,
+						bytes_left);
+
+			if (ret < 0)
+			{
+				fprintf(stderr,
+				  _("%s: could not write %u bytes to log file \"%s\": %s\n"),
+						progname, bytes_left, outfile,
+						strerror(errno));
+				goto error;
+			}
+
+			/* Write was successful, advance our position */
+			bytes_written += ret;
+			bytes_left -= ret;
+		}
+
+		if (write(outfd, "\n", 1) != 1)
+		{
+			fprintf(stderr,
+				  _("%s: could not write %u bytes to log file \"%s\": %s\n"),
+					progname, 1, outfile,
+					strerror(errno));
+			goto error;
+		}
+	}
+
+	res = PQgetResult(conn);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
+	{
+		fprintf(stderr,
+				_("%s: unexpected termination of replication stream: %s"),
+				progname, PQresultErrorMessage(res));
+		goto error;
+	}
+	PQclear(res);
+
+	if (copybuf != NULL)
+		PQfreemem(copybuf);
+
+	if (outfd != -1 && strcmp(outfile, "-") != 0)
+	{
+		int64 t = feGetCurrentTimestamp();
+
+		/* no need to jump to error on failure here, we're finishing anyway */
+		OutputFsync(t);
+
+		if (close(outfd) != 0)
+			fprintf(stderr, _("%s: could not close file \"%s\": %s\n"),
+					progname, outfile, strerror(errno));
+	}
+	outfd = -1;
+error:
+	destroyPQExpBuffer(query);
+	PQfinish(conn);
+	conn = NULL;
+}
+
+/*
+ * Unfortunately we can't do sensible signal handling on windows...
+ */
+#ifndef WIN32
+
+/*
+ * When sigint is called, just tell the system to exit at the next possible
+ * moment.
+ */
+static void
+sigint_handler(int signum)
+{
+	time_to_abort = true;
+}
+
+/*
+ * Trigger the output file to be reopened.
+ */
+static void
+sighup_handler(int signum)
+{
+	output_reopen = true;
+}
+#endif
+
+
+int
+main(int argc, char **argv)
+{
+	PGresult   *res;
+	static struct option long_options[] = {
+/* general options */
+		{"file", required_argument, NULL, 'f'},
+		{"no-loop", no_argument, NULL, 'n'},
+		{"verbose", no_argument, NULL, 'v'},
+		{"version", no_argument, NULL, 'V'},
+		{"help", no_argument, NULL, '?'},
+/* connnection options */
+		{"dbname", required_argument, NULL, 'd'},
+		{"host", required_argument, NULL, 'h'},
+		{"port", required_argument, NULL, 'p'},
+		{"username", required_argument, NULL, 'U'},
+		{"no-password", no_argument, NULL, 'w'},
+		{"password", no_argument, NULL, 'W'},
+/* replication options */
+		{"option", required_argument, NULL, 'o'},
+		{"plugin", required_argument, NULL, 'P'},
+		{"status-interval", required_argument, NULL, 's'},
+		{"fsync-interval", required_argument, NULL, 'F'},
+		{"slot", required_argument, NULL, 'S'},
+		{"startpos", required_argument, NULL, 'I'},
+/* action */
+		{"create", no_argument, NULL, 1},
+		{"start", no_argument, NULL, 2},
+		{"drop", no_argument, NULL, 3},
+		{NULL, 0, NULL, 0}
+	};
+	int			c;
+	int			option_index;
+	uint32		hi,
+				lo;
+
+	progname = get_progname(argv[0]);
+	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_recvlogical"));
+
+	if (argc > 1)
+	{
+		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
+		{
+			usage();
+			exit(0);
+		}
+		else if (strcmp(argv[1], "-V") == 0 ||
+				 strcmp(argv[1], "--version") == 0)
+		{
+			puts("pg_recvlogical (PostgreSQL) " PG_VERSION);
+			exit(0);
+		}
+	}
+
+	while ((c = getopt_long(argc, argv, "f:F:nvd:h:o:p:U:wWP:s:S:",
+							long_options, &option_index)) != -1)
+	{
+		switch (c)
+		{
+/* general options */
+			case 'f':
+				outfile = pg_strdup(optarg);
+				break;
+			case 'n':
+				noloop = 1;
+				break;
+			case 'v':
+				verbose++;
+				break;
+/* connnection options */
+			case 'd':
+				dbname = pg_strdup(optarg);
+				break;
+			case 'h':
+				dbhost = pg_strdup(optarg);
+				break;
+			case 'p':
+				if (atoi(optarg) <= 0)
+				{
+					fprintf(stderr, _("%s: invalid port number \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				dbport = pg_strdup(optarg);
+				break;
+			case 'U':
+				dbuser = pg_strdup(optarg);
+				break;
+			case 'w':
+				dbgetpassword = -1;
+				break;
+			case 'W':
+				dbgetpassword = 1;
+				break;
+/* replication options */
+			case 'o':
+				{
+					char *data = pg_strdup(optarg);
+					char *val = strchr(data, '=');
+
+					if (val != NULL)
+					{
+						/* remove =; separate data from val */
+						*val = '\0';
+						val++;
+					}
+
+					noptions += 1;
+					options = pg_realloc(options, sizeof(char*) * noptions * 2);
+
+					options[(noptions - 1) * 2] = data;
+					options[(noptions - 1) * 2 + 1] = val;
+				}
+
+				break;
+			case 'P':
+				plugin = pg_strdup(optarg);
+				break;
+			case 's':
+				standby_message_timeout = atoi(optarg) * 1000;
+				if (standby_message_timeout < 0)
+				{
+					fprintf(stderr, _("%s: invalid status interval \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				break;
+			case 'F':
+				fsync_interval = atoi(optarg) * 1000;
+				if (fsync_interval < 0)
+				{
+					fprintf(stderr, _("%s: invalid fsync interval \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				break;
+			case 'S':
+				replication_slot = pg_strdup(optarg);
+				break;
+			case 'I':
+				if (sscanf(optarg, "%X/%X", &hi, &lo) != 2)
+				{
+					fprintf(stderr,
+							_("%s: could not parse start position \"%s\"\n"),
+							progname, optarg);
+					exit(1);
+				}
+				startpos = ((uint64) hi) << 32 | lo;
+				break;
+/* action */
+			case 1:
+				do_create_slot = true;
+				break;
+			case 2:
+				do_start_slot = true;
+				break;
+			case 3:
+				do_drop_slot = true;
+				break;
+
+			default:
+
+				/*
+				 * getopt_long already emitted a complaint
+				 */
+				fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+						progname);
+				exit(1);
+		}
+	}
+
+	/*
+	 * Any non-option arguments?
+	 */
+	if (optind < argc)
+	{
+		fprintf(stderr,
+				_("%s: too many command-line arguments (first is \"%s\")\n"),
+				progname, argv[optind]);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	/*
+	 * Required arguments
+	 */
+	if (replication_slot == NULL)
+	{
+		fprintf(stderr, _("%s: no slot specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (do_start_slot && outfile == NULL)
+	{
+		fprintf(stderr, _("%s: no target file specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (!do_drop_slot && dbname == NULL)
+	{
+		fprintf(stderr, _("%s: no database specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (!do_drop_slot && !do_create_slot && !do_start_slot)
+	{
+		fprintf(stderr, _("%s: at least one action needs to be specified\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (do_drop_slot && (do_create_slot || do_start_slot))
+	{
+		fprintf(stderr, _("%s: --stop cannot be combined with --init or --start\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+	if (startpos && (do_create_slot || do_drop_slot))
+	{
+		fprintf(stderr, _("%s: --startpos cannot be combined with --init or --stop\n"), progname);
+		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+				progname);
+		exit(1);
+	}
+
+#ifndef WIN32
+	pqsignal(SIGINT, sigint_handler);
+	pqsignal(SIGHUP, sighup_handler);
+#endif
+
+	/*
+	 * don't really need this but it actually helps to get more precise error
+	 * messages about authentication, required GUCs and such without starting
+	 * to loop around connection attempts lateron.
+	 */
+	{
+		conn = GetConnection();
+		if (!conn)
+			/* Error message already written in GetConnection() */
+			exit(1);
+
+		/*
+		 * Run IDENTIFY_SYSTEM so we can get the timeline and current xlog
+		 * position.
+		 */
+		res = PQexec(conn, "IDENTIFY_SYSTEM");
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 1 || PQnfields(res) < 4)
+		{
+			fprintf(stderr,
+					_("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 4);
+			disconnect_and_exit(1);
+		}
+		PQclear(res);
+	}
+
+
+	/*
+	 * stop a replication slot
+	 */
+	if (do_drop_slot)
+	{
+		char		query[256];
+
+		if (verbose)
+			fprintf(stderr,
+					_("%s: freeing replication slot \"%s\"\n"),
+					progname, replication_slot);
+
+		snprintf(query, sizeof(query), "DROP_REPLICATION_SLOT \"%s\"",
+				 replication_slot);
+		res = PQexec(conn, query);
+		if (PQresultStatus(res) != PGRES_COMMAND_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, query, PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 0 || PQnfields(res) != 0)
+		{
+			fprintf(stderr,
+					_("%s: could not stop logical rep: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 0, 0);
+			disconnect_and_exit(1);
+		}
+
+		PQclear(res);
+		disconnect_and_exit(0);
+	}
+
+	/*
+	 * init a replication slot
+	 */
+	if (do_create_slot)
+	{
+		char		query[256];
+
+		if (verbose)
+			fprintf(stderr,
+					_("%s: initializing replication slot \"%s\"\n"),
+					progname, replication_slot);
+
+		snprintf(query, sizeof(query), "CREATE_REPLICATION_SLOT \"%s\" LOGICAL \"%s\"",
+				 replication_slot, plugin);
+
+		res = PQexec(conn, query);
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+					progname, query, PQerrorMessage(conn));
+			disconnect_and_exit(1);
+		}
+
+		if (PQntuples(res) != 1 || PQnfields(res) != 4)
+		{
+			fprintf(stderr,
+					_("%s: could not init logical rep: got %d rows and %d fields, expected %d rows and %d fields\n"),
+					progname, PQntuples(res), PQnfields(res), 1, 4);
+			disconnect_and_exit(1);
+		}
+
+		if (sscanf(PQgetvalue(res, 0, 1), "%X/%X", &hi, &lo) != 2)
+		{
+			fprintf(stderr,
+					_("%s: could not parse log location \"%s\"\n"),
+					progname, PQgetvalue(res, 0, 1));
+			disconnect_and_exit(1);
+		}
+		startpos = ((uint64) hi) << 32 | lo;
+
+		replication_slot = strdup(PQgetvalue(res, 0, 0));
+		PQclear(res);
+	}
+
+
+	if (!do_start_slot)
+		disconnect_and_exit(0);
+
+	while (true)
+	{
+		StreamLog();
+		if (time_to_abort)
+		{
+			/*
+			 * We've been Ctrl-C'ed. That's not an error, so exit without an
+			 * errorcode.
+			 */
+			disconnect_and_exit(0);
+		}
+		else if (noloop)
+		{
+			fprintf(stderr, _("%s: disconnected.\n"), progname);
+			exit(1);
+		}
+		else
+		{
+			fprintf(stderr,
+			/* translator: check source for value for %d */
+					_("%s: disconnected. Waiting %d seconds to try again.\n"),
+					progname, RECONNECT_SLEEP_TIME);
+			pg_usleep(RECONNECT_SLEEP_TIME * 1000000);
+		}
+	}
+}
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index febe3d1..55f3d7f 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -11,22 +11,19 @@
  *		  src/bin/pg_basebackup/receivelog.c
  *-------------------------------------------------------------------------
  */
+
 #include "postgres_fe.h"
 
 #include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
 #include <unistd.h>
-/* for ntohl/htonl */
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "libpq-fe.h"
-#include "access/xlog_internal.h"
 
+/* local includes */
 #include "receivelog.h"
 #include "streamutil.h"
 
+#include "libpq-fe.h"
+#include "access/xlog_internal.h"
+
 
 /* fd and filename for currently open WAL file */
 static int	walfile = -1;
@@ -195,63 +192,6 @@ close_walfile(char *basedir, char *partial_suffix, XLogRecPtr pos)
 
 
 /*
- * Local version of GetCurrentTimestamp(), since we are not linked with
- * backend code. The protocol always uses integer timestamps, regardless of
- * server setting.
- */
-static int64
-localGetCurrentTimestamp(void)
-{
-	int64		result;
-	struct timeval tp;
-
-	gettimeofday(&tp, NULL);
-
-	result = (int64) tp.tv_sec -
-		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
-
-	result = (result * USECS_PER_SEC) + tp.tv_usec;
-
-	return result;
-}
-
-/*
- * Local version of TimestampDifference(), since we are not linked with
- * backend code.
- */
-static void
-localTimestampDifference(int64 start_time, int64 stop_time,
-						 long *secs, int *microsecs)
-{
-	int64		diff = stop_time - start_time;
-
-	if (diff <= 0)
-	{
-		*secs = 0;
-		*microsecs = 0;
-	}
-	else
-	{
-		*secs = (long) (diff / USECS_PER_SEC);
-		*microsecs = (int) (diff % USECS_PER_SEC);
-	}
-}
-
-/*
- * Local version of TimestampDifferenceExceeds(), since we are not
- * linked with backend code.
- */
-static bool
-localTimestampDifferenceExceeds(int64 start_time,
-								int64 stop_time,
-								int msec)
-{
-	int64		diff = stop_time - start_time;
-
-	return (diff >= msec * INT64CONST(1000));
-}
-
-/*
  * Check if a timeline history file exists.
  */
 static bool
@@ -371,47 +311,6 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co
 }
 
 /*
- * Converts an int64 to network byte order.
- */
-static void
-sendint64(int64 i, char *buf)
-{
-	uint32		n32;
-
-	/* High order half first, since we're doing MSB-first */
-	n32 = (uint32) (i >> 32);
-	n32 = htonl(n32);
-	memcpy(&buf[0], &n32, 4);
-
-	/* Now the low order half */
-	n32 = (uint32) i;
-	n32 = htonl(n32);
-	memcpy(&buf[4], &n32, 4);
-}
-
-/*
- * Converts an int64 from network byte order to native format.
- */
-static int64
-recvint64(char *buf)
-{
-	int64		result;
-	uint32		h32;
-	uint32		l32;
-
-	memcpy(&h32, buf, 4);
-	memcpy(&l32, buf + 4, 4);
-	h32 = ntohl(h32);
-	l32 = ntohl(l32);
-
-	result = h32;
-	result <<= 32;
-	result |= l32;
-
-	return result;
-}
-
-/*
  * Send a Standby Status Update message to server.
  */
 static bool
@@ -422,16 +321,16 @@ sendFeedback(PGconn *conn, XLogRecPtr blockpos, int64 now, bool replyRequested)
 
 	replybuf[len] = 'r';
 	len += 1;
-	sendint64(blockpos, &replybuf[len]);		/* write */
+	fe_sendint64(blockpos, &replybuf[len]);		/* write */
 	len += 8;
 	if (reportFlushPosition)
-		sendint64(lastFlushPosition, &replybuf[len]);		/* flush */
+		fe_sendint64(lastFlushPosition, &replybuf[len]);		/* flush */
 	else
-		sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
+		fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* flush */
 	len += 8;
-	sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
+	fe_sendint64(InvalidXLogRecPtr, &replybuf[len]);		/* apply */
 	len += 8;
-	sendint64(now, &replybuf[len]);		/* sendTime */
+	fe_sendint64(now, &replybuf[len]);		/* sendTime */
 	len += 8;
 	replybuf[len] = replyRequested ? 1 : 0;		/* replyRequested */
 	len += 1;
@@ -864,9 +763,9 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 		/*
 		 * Potentially send a status message to the master
 		 */
-		now = localGetCurrentTimestamp();
+		now = feGetCurrentTimestamp();
 		if (still_sending && standby_message_timeout > 0 &&
-			localTimestampDifferenceExceeds(last_status, now,
+			feTimestampDifferenceExceeds(last_status, now,
 											standby_message_timeout))
 		{
 			/* Time to send feedback! */
@@ -895,10 +794,10 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 				int			usecs;
 
 				targettime = last_status + (standby_message_timeout - 1) * ((int64) 1000);
-				localTimestampDifference(now,
-										 targettime,
-										 &secs,
-										 &usecs);
+				feTimestampDifference(now,
+									  targettime,
+									  &secs,
+									  &usecs);
 				if (secs <= 0)
 					timeout.tv_sec = 1; /* Always sleep at least 1 sec */
 				else
@@ -1002,7 +901,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 			/* If the server requested an immediate reply, send one. */
 			if (replyRequested && still_sending)
 			{
-				now = localGetCurrentTimestamp();
+				now = feGetCurrentTimestamp();
 				if (!sendFeedback(conn, blockpos, now, false))
 					goto error;
 				last_status = now;
@@ -1032,7 +931,7 @@ HandleCopyStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline,
 						progname, r);
 				goto error;
 			}
-			blockpos = recvint64(&copybuf[1]);
+			blockpos = fe_recvint64(&copybuf[1]);
 
 			/* Extract WAL location for this block */
 			xlogoff = blockpos % XLOG_SEG_SIZE;
diff --git a/src/bin/pg_basebackup/receivelog.h b/src/bin/pg_basebackup/receivelog.h
index 7c983cd..f4789a5 100644
--- a/src/bin/pg_basebackup/receivelog.h
+++ b/src/bin/pg_basebackup/receivelog.h
@@ -1,3 +1,5 @@
+#include "libpq-fe.h"
+
 #include "access/xlogdefs.h"
 
 /*
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 041076f..e440dc4 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -12,10 +12,23 @@
  */
 
 #include "postgres_fe.h"
-#include "streamutil.h"
 
 #include <stdio.h>
 #include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* for ntohl/htonl */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/* local includes */
+#include "receivelog.h"
+#include "streamutil.h"
+
+#include "common/fe_memutils.h"
+#include "datatype/timestamp.h"
 
 const char *progname;
 char	   *connection_string = NULL;
@@ -23,6 +36,7 @@ char	   *dbhost = NULL;
 char	   *dbuser = NULL;
 char	   *dbport = NULL;
 char	   *replication_slot = NULL;
+char	   *dbname = NULL;
 int			dbgetpassword = 0;	/* 0=auto, -1=never, 1=always */
 static char *dbpassword = NULL;
 PGconn	   *conn = NULL;
@@ -87,10 +101,10 @@ GetConnection(void)
 	}
 
 	keywords[i] = "dbname";
-	values[i] = "replication";
+	values[i] = dbname == NULL ? "replication" : dbname;
 	i++;
 	keywords[i] = "replication";
-	values[i] = "true";
+	values[i] = dbname == NULL ? "true" : "database";
 	i++;
 	keywords[i] = "fallback_application_name";
 	values[i] = progname;
@@ -212,3 +226,102 @@ GetConnection(void)
 
 	return tmpconn;
 }
+
+
+/*
+ * Frontend version of GetCurrentTimestamp(), since we are not linked with
+ * backend code. The protocol always uses integer timestamps, regardless of
+ * server setting.
+ */
+int64
+feGetCurrentTimestamp(void)
+{
+	int64		result;
+	struct timeval tp;
+
+	gettimeofday(&tp, NULL);
+
+	result = (int64) tp.tv_sec -
+		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
+
+	result = (result * USECS_PER_SEC) + tp.tv_usec;
+
+	return result;
+}
+
+/*
+ * Frontend version of TimestampDifference(), since we are not linked with
+ * backend code.
+ */
+void
+feTimestampDifference(int64 start_time, int64 stop_time,
+						 long *secs, int *microsecs)
+{
+	int64		diff = stop_time - start_time;
+
+	if (diff <= 0)
+	{
+		*secs = 0;
+		*microsecs = 0;
+	}
+	else
+	{
+		*secs = (long) (diff / USECS_PER_SEC);
+		*microsecs = (int) (diff % USECS_PER_SEC);
+	}
+}
+
+/*
+ * Frontend version of TimestampDifferenceExceeds(), since we are not
+ * linked with backend code.
+ */
+bool
+feTimestampDifferenceExceeds(int64 start_time,
+								int64 stop_time,
+								int msec)
+{
+	int64		diff = stop_time - start_time;
+
+	return (diff >= msec * INT64CONST(1000));
+}
+
+/*
+ * Converts an int64 to network byte order.
+ */
+void
+fe_sendint64(int64 i, char *buf)
+{
+	uint32		n32;
+
+	/* High order half first, since we're doing MSB-first */
+	n32 = (uint32) (i >> 32);
+	n32 = htonl(n32);
+	memcpy(&buf[0], &n32, 4);
+
+	/* Now the low order half */
+	n32 = (uint32) i;
+	n32 = htonl(n32);
+	memcpy(&buf[4], &n32, 4);
+}
+
+/*
+ * Converts an int64 from network byte order to native format.
+ */
+int64
+fe_recvint64(char *buf)
+{
+	int64		result;
+	uint32		h32;
+	uint32		l32;
+
+	memcpy(&h32, buf, 4);
+	memcpy(&l32, buf + 4, 4);
+	h32 = ntohl(h32);
+	l32 = ntohl(l32);
+
+	result = h32;
+	result <<= 32;
+	result |= l32;
+
+	return result;
+}
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index 7c7d022..d0f3799 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -5,6 +5,7 @@ extern char *connection_string;
 extern char *dbhost;
 extern char *dbuser;
 extern char *dbport;
+extern char *dbname;
 extern int	dbgetpassword;
 extern char *replication_slot;
 
@@ -12,3 +13,12 @@ extern char *replication_slot;
 extern PGconn *conn;
 
 extern PGconn *GetConnection(void);
+
+extern int64 feGetCurrentTimestamp(void);
+extern void feTimestampDifference(int64 start_time, int64 stop_time,
+									 long *secs, int *microsecs);
+
+extern bool feTimestampDifferenceExceeds(int64 start_time, int64 stop_time,
+											int msec);
+extern void fe_sendint64(int64 i, char *buf);
+extern int64 fe_recvint64(char *buf);
-- 
1.8.3.251.g1462b67

0002-Documentation-for-logical-decoding.patchtext/x-patch; charset=us-asciiDownload
>From 8504bd46682c2e2a1f052babe2810f22321f3c66 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 5 Mar 2014 00:15:39 +0100
Subject: [PATCH 2/2] Documentation for logical decoding.

Craig Ringer, Andres Freund, Christian Kruse
---
 doc/src/sgml/catalogs.sgml           |  27 +-
 doc/src/sgml/filelist.sgml           |   1 +
 doc/src/sgml/func.sgml               | 102 +++++-
 doc/src/sgml/high-availability.sgml  |   6 +-
 doc/src/sgml/logicaldecoding.sgml    | 607 +++++++++++++++++++++++++++++++++++
 doc/src/sgml/postgres.sgml           |   1 +
 doc/src/sgml/protocol.sgml           |  69 +++-
 doc/src/sgml/ref/allfiles.sgml       |   1 +
 doc/src/sgml/ref/alter_table.sgml    |   2 +-
 doc/src/sgml/ref/create_table.sgml   |  15 +-
 doc/src/sgml/ref/pg_recvlogical.sgml | 338 +++++++++++++++++++
 doc/src/sgml/reference.sgml          |   1 +
 12 files changed, 1153 insertions(+), 17 deletions(-)
 create mode 100644 doc/src/sgml/logicaldecoding.sgml
 create mode 100644 doc/src/sgml/ref/pg_recvlogical.sgml

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 908f947..a12ee56 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -5177,7 +5177,7 @@
 
   <para>
    For more on replication slots,
-   see <xref linkend="streaming-replication-slots">.
+   see <xref linkend="streaming-replication-slots"> and <xref linkend="logicaldecoding">.
   </para>
 
   <table>
@@ -5210,6 +5210,13 @@
      </row>
 
      <row>
+      <entry><structfield>plugin</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>The basename of the shared object containing the output plugin this logical slot is using, or null for physical slots.</entry>
+     </row>
+
+     <row>
       <entry><structfield>datoid</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry>
@@ -5243,6 +5250,24 @@
      </row>
 
      <row>
+      <entry><structfield>xmin</structfield></entry>
+      <entry><type>xid</type></entry>
+      <entry></entry>
+      <entry>The oldest transaction that this slot needs the database to
+      retain.  <literal>VACUUM</literal> cannot remove catalog tuples deleted
+      by any later transaction.
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>catalog_xmin</structfield></entry>
+      <entry><type>xid</type></entry>
+      <entry></entry>
+      <entry>The <literal>xmin</literal>, or oldest transaction ID, that this
+      slot forces to be retained in the system catalogs. </entry>
+     </row>
+
+     <row>
       <entry><structfield>restart_lsn</structfield></entry>
       <entry><type>pg_lsn</type></entry>
       <entry></entry>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 0e863ee..6c8e254 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -91,6 +91,7 @@
 <!ENTITY nls        SYSTEM "nls.sgml">
 <!ENTITY plhandler  SYSTEM "plhandler.sgml">
 <!ENTITY fdwhandler SYSTEM "fdwhandler.sgml">
+<!ENTITY logicaldecoding SYSTEM "logicaldecoding.sgml">
 <!ENTITY protocol   SYSTEM "protocol.sgml">
 <!ENTITY sources    SYSTEM "sources.sgml">
 <!ENTITY storage    SYSTEM "storage.sgml">
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 080da43..0336de8 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -16377,8 +16377,9 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
 
    <para>
     PostgreSQL exposes a number of functions for controlling and interacting
-    with replication features. See <xref linkend="streaming-replication">
-    and <xref linkend="streaming-replication-slots">.
+    with replication features. See <xref linkend="streaming-replication">,
+    <xref linkend="streaming-replication-slots">
+    and <xref linkend="logicaldecoding">.
    </para>
 
    <para>
@@ -16437,9 +16438,106 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
         command <literal>DROP_REPLICATION_SLOT</>.
        </entry>
       </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_create_logical_replication_slot</primary>
+        </indexterm>
+        <literal><function>pg_create_logical_replication_slot(<parameter>slotname</parameter> <type>name</type>, <parameter>plugin</parameter> <type>name</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>slotname</parameter> <type>name</type>, <parameter>xlog_position</parameter> <type>pg_lsn</type>)
+       </entry>
+       <entry>
+        Creates a new logical (decoding) replication slot named
+        <parameter>slotname</parameter> using the output plugin
+        <parameter>plugin</parameter>. Output plugins are listed amongst the
+        extensions in <literal>pg_catalog.pg_available_extensions</literal>,
+        but there is no specific listing of only output plugins. Same as
+        walsender protocol command <literal>CREATE REPLICATION SLOT ... LOGICAL</literal>.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_get_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_get_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>pg_lsn</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Returns changes in the slot <parameter>slotname</parameter>, starting
+        from the point at which since changes have been consumed last. Changes
+        are extracted upto the current end of the WAL, or if nonnull only if
+        their transactions have committed
+        before <parameter>upto_lsn</parameter>, or if nonnull
+        until <parameter>upto_nchanges</parameter> rows have been
+        collected. Note that the <parameter>upto_nchanges</parameter> limit is
+        only enforced everytime a transaction commits. Changes will not be
+        consumed.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_peek_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_peek_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>text</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>text</type>)
+       </entry>
+       <entry>
+        Behaves just like
+        the <function>pg_logical_slot_get_changes()</function> function,
+        except that changes are not consumed, i.e. will be returned again on
+        future calls.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_get_binary_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_get_binary_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>pg_lsn</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>bytea</type>)
+       </entry>
+       <entry>
+        Behaves just like
+        the <function>pg_logical_slot_get_changes()</function> function,
+        except that changes are returned as <type>bytea</type>.
+       </entry>
+      </row>
+
+      <row>
+       <entry>
+        <indexterm>
+         <primary>pg_logical_slot_peek_binary_changes</primary>
+        </indexterm>
+        <literal><function>pg_logical_slot_peek_binary_changes(<parameter>slotname</parameter> <type>name</type>, <parameter>upto_lsn</parameter> <type>pg_lsn</type>, <parameter>upto_nchanges</parameter> <type>int</type>, VARIADIC <parameter>options</parameter> <type>text[]</type>)</function></literal>
+       </entry>
+       <entry>
+        (<parameter>location</parameter> <type>pg_lsn</type>, <parameter>xid</parameter> <type>xid</type>, <parameter>data</parameter> <type>bytea</type>)
+       </entry>
+       <entry>
+        Behaves just like
+        the <function>pg_logical_slot_get_changes()</function> function,
+        except that changes are returned as <type>bytea</type> and that
+        changes are not consumed, i.e. will be returned again on future calls.
+       </entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
+
   </sect2>
 
   <sect2 id="functions-admin-dbobject">
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index ecb51c4..deac2a7 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -888,12 +888,12 @@ primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
    </para>
    <para>
     In lieu of using replication slots, it is possible to prevent the removal
-    of old WAL segments using <xref linkend="guc-wal-keep-segments">, or by
+    of old WAL segments using <xref linkend="guc-wal-keep-segments"> or by
     storing the segments in an archive using
     <xref linkend="guc-archive-command">.
     However, these methods often result in retaining more WAL segments than
-    required, whereas replication slots retain only the number of segments
-    known to be needed.  An advantage of these methods is that they bound
+    required whereas replication slots retain only the number of segments
+    known to be needed.  An advantage of these methods is that they are bound
     the space requirement for <literal>pg_xlog</>; there is currently no way
     to do this using replication slots.
    </para>
diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml
new file mode 100644
index 0000000..f4d5910
--- /dev/null
+++ b/doc/src/sgml/logicaldecoding.sgml
@@ -0,0 +1,607 @@
+<!-- doc/src/sgml/logicaldecoding.sgml -->
+ <chapter id="logicaldecoding">
+  <title>Logical Decoding</title>
+  <indexterm zone="logicaldecoding">
+   <primary>Logical Decoding</primary>
+  </indexterm>
+  <indexterm zone="logicaldecoding">
+   <primary>Logical Replication</primary>
+  </indexterm>
+  <indexterm zone="logicaldecoding">
+   <primary>Changeset Extraction</primary>
+  </indexterm>
+  <para>
+   PostgreSQL provides infrastructure to stream the modifications performed
+   via SQL to external consumers which can be used to implement replication
+   solutions, perform auditing, and similar tasks.
+  </para>
+
+  <para>
+   Changes are sent out in streams where each stream outputs each change
+   exactly once. On the sender's side, each changestream is identified by a so
+   called logical replication slot.
+  </para>
+
+  <para>
+   The format in which those changes are streamed is determined by the output
+   plugin used. While an example plugin is provided, additional plugins can be
+   written to extend the choice of available formats without modifying any
+   core code.
+   Every output plugin has access to each individual new row produced
+   by <command>INSERT</command>, and the new row version created
+   by <command>UPDATE</command>. Which data is available for rows affected
+   by <command>DELETE</command> and for the old row version in
+   an <command>UPDATE</command> depends on the relation's
+   configured <link linkend="SQL-CREATETABLE-REPLICA-IDENTITY"><literal>REPLICA
+   IDENTITY</literal></link>.
+  </para>
+
+  <para>
+   Changes can be consumed either using the streaming replication protocol
+   (see <xref linkend="protocol-replication"> and
+   <xref linkend="logicaldecoding-walsender">), or by calling functions
+   via SQL (see <xref linkend="logicaldecoding-sql">). It is also possible
+   to write additional methods of consuming the output of a replication slot
+   without modifying core code
+   (see <xref linkend="logicaldecoding-writer">).
+  </para>
+
+  <sect1 id="logicaldecoding-example">
+   <title>Logical Decoding Example</title>
+   <para>
+    The following example shows usage of the SQL interface.
+   </para>
+   <para>
+    Before you can use logical decoding
+    <literal>postgresql.conf</literal> must be changed to ensure the following
+    parameters are set to at least:
+    <programlisting>
+wal_level = logical
+max_replication_slots = 1
+max_wal_senders = 1
+    </programlisting>
+    Then connect to the target database (in the example
+    below, <literal>postgres</literal>) as a superuser.
+   </para>
+   <programlisting>
+postgres=# -- max_replication_slots must be nonzero and wal_level must be logical
+postgres=# SHOW max_replication_slots;
+ max_replication_slots
+-----------------------
+ 1
+(1 row)
+
+postgres=# SHOW wal_level;
+ wal_level
+-----------
+ logical
+(1 row)
+
+postgres=# SELECT * FROM pg_replication_slots;
+ slot_name | plugin | slot_type | datoid | database | active | xmin | catalog_xmin | restart_lsn
+-----------+--------+-----------+--------+----------+--------+------+--------------+-------------
+(0 rows)
+
+postgres=# -- Create a slot named 'regression_slot' using the output plugin 'test_decoding'
+postgres=# SELECT * FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
+    slotname     | xlog_position
+-----------------+---------------
+ regression_slot | 0/16B1970
+(1 row)
+
+postgres=# SELECT * FROM pg_replication_slots;
+    slot_name    |    plugin     | slot_type | datoid | database | active |  xmin  | catalog_xmin | restart_lsn
+-----------------+---------------+-----------+--------+----------+--------+--------+--------------+-------------
+ regression_slot | test_decoding | logical   |  12052 | postgres | f      |        |          684 | 0/16A4408
+(1 row)
+
+postgres=# -- There are no changes to see yet
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location | xid | data
+----------+-----+------
+(0 rows)
+
+postgres=# CREATE TABLE data(id serial primary key, data text);
+CREATE TABLE
+
+postgres=# -- DDL isn't replicated, so all you'll see is the transaction
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location  | xid |    data
+-----------+-----+------------
+ 0/16D5D48 | 688 | BEGIN 688
+ 0/16E0380 | 688 | COMMIT 688
+(2 rows)
+
+postgres=# -- Once changes are read, they're consumed and not emitted
+postgres=# -- in a subsequent call:
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location | xid | data
+----------+-----+------
+(0 rows)
+
+postgres=# BEGIN;
+postgres=# INSERT INTO data(data) VALUES('1');
+postgres=# INSERT INTO data(data) VALUES('2');
+postgres=# COMMIT;
+
+postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E0478 | 689 | BEGIN 689
+ 0/16E0478 | 689 | table public.data: INSERT: id[int4]:1 data[text]:'1'
+ 0/16E0580 | 689 | table public.data: INSERT: id[int4]:2 data[text]:'2'
+ 0/16E0650 | 689 | COMMIT 689
+(4 rows)
+
+postgres=# INSERT INTO data(data) VALUES('3');
+
+postgres=# -- You can also peek ahead in the change stream without consuming changes
+postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E09C0 | 690 | BEGIN 690
+ 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3'
+ 0/16E0B90 | 690 | COMMIT 690
+(3 rows)
+
+postgres=# -- You can also peek ahead in the change stream without consuming changes
+postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E09C0 | 690 | BEGIN 690
+ 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3'
+ 0/16E0B90 | 690 | COMMIT 690
+(3 rows)
+
+postgres=# -- options can be passed to output plugin, to influence the formatting
+postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL, 'include-timestamp', 'on');
+ location  | xid |                     data
+-----------+-----+-----------------------------------------------
+ 0/16E09C0 | 690 | BEGIN 690
+ 0/16E09C0 | 690 | table public.data: INSERT: id[int4]:3 data[text]:'3'
+ 0/16E0B90 | 690 | COMMIT 690 (at 2014-02-27 16:41:51.863092+01)
+(3 rows)
+
+postgres=# -- Remember to destroy a slot you no longer need to stop it consuming
+postgres=# -- server resources:
+postgres=# SELECT pg_drop_replication_slot('regression_slot');
+ pg_drop_replication_slot
+-----------------------
+
+(1 row)
+    </programlisting>
+   <para>
+    The following example shows usage of the walsender interface using
+    the <link linkend="app-pgrecvlogical"><command>pg_recvlogical</command></link>
+    shell command. It requires the replication configurations to be allowed
+    (see <xref linkend="streaming-replication-authentication">)
+    and <varname>max_wal_senders</varname> to be set sufficiently high for
+    another connection.
+   </para>
+   <programlisting>
+# pg_recvlogical -d testdb --slot test --create
+# pg_recvlogical -d testdb --slot test --start -f -
+CTRL-Z
+# psql -c "INSERT INTO data(data) VALUES('4');"
+# fg
+BEGIN 693
+table public.data: INSERT: id[int4]:4 data[text]:'4'
+COMMIT 693
+CTRL-C
+# pg_recvlogical -d testdb --slot test --drop
+   </programlisting>
+  </sect1>
+  <sect1 id="logicaldecoding-explanation">
+   <title>Logical Decoding Concepts</title>
+   <sect2>
+    <indexterm>
+     <primary>Logical Decoding</primary>
+    </indexterm>
+    <title>Logical Decoding</title>
+    <para>
+     Logical decoding is the the process of extracting all persistent changes
+     to a database's tables into a coherent, easy to understand format which
+     can be interpreted without detailed knowledge of the database's internal
+     state.
+    </para>
+    <para>
+     In <productname>PostgreSQL</productname> logical decoding is implemented
+     by decoding the <link linkend="wal">WAL's</link> contents, which describe
+     changes on a storage level, into an application-specific form such as a
+     stream of tuples or SQL statements.
+    </para>
+   </sect2>
+
+   <sect2>
+    <indexterm>
+     <primary>Logical Replication Slot</primary>
+    </indexterm>
+    <indexterm>
+     <primary>Replication Slot</primary>
+    </indexterm>
+    <title>Replication Slots</title>
+    <para>
+     In the context of logical replication a slot represents a stream of
+     changes which can be replayed to a client in the order they were made on
+     the origin server. Each slot streams a sequence of changes from a single
+     database, sending each change exactly once (unless peeking forward in the
+     stream).
+    </para>
+    <note>
+     <para>PostgreSQL also has streaming replication slots
+     (see <xref linkend="streaming-replication">), but they are used somewhat
+     differently there.
+     </para>
+    </note>
+    <para>
+     Replication slots have an identifier which is unique across all databases
+     in a <productname>PostgreSQL</productname> cluster. Slots persist
+     independently of the connection using them and are crash-safe.  They can
+     be allocated in primary servers and hot-standby servers (streaming
+     replicas or archive-replaying hot standbys), so it's possible to
+     replicate changes over physical replication and read a logical change
+     stream from that physical replica server.
+    </para>
+    <para>
+     Multiple independent slots may exist for a single database. Each slot has
+     its own state, allowing different consumers to receive changes from
+     different points in the database change stream. For most applications a
+     separate slot is required for each consumer.
+    </para>
+    <para>
+     A logical replication slot knows nothing about the state of the
+     receiver(s).  It's even possible to have multiple different receivers using
+     the same slot at different times; they'll just get the changes following
+     on from when the last receiver stopped consuming them. Only one receiver
+     may consume changes from a slot at any given time.
+    </para>
+    <note>
+     <para>
+      Replication slots persist across crashes and know nothing about the state of
+      their consumer(s). They will prevent removal of required resources even
+      when there is no connection using them. This consumes storage because
+      neither required WAL nor required rows from the system catalogs can be
+      removed by VACUUM as long as they are required by a replication slot, so
+      if a slot is no longer required it should be dropped.
+     </para>
+     <para>
+      Slots may be created manually, or using a client like a replication
+      tool. Keep this in mind when you retire a client that uses a replication
+      slot, like a logical replica - you may need to give it a specific
+      command to remove its replication slot, or drop the slot yourself, even
+      if you did not initially create the slot by hand.
+     </para>
+    </note>
+   </sect2>
+   <sect2>
+    <title>Output Plugins</title>
+    <para>
+     Output plugins transform the data from postgres' internal representation
+     into the format the consumer of a replication slot desires. Additional
+     output plugins can be written without modifying core postgres code.
+    </para>
+   </sect2>
+   <sect2>
+    <title>Exported Snapshots</title>
+    <para>
+     When a new replication slot is created over the walsender interface a
+     snapshot is exported
+     (see <xref linkend="functions-snapshot-synchronization">) which will show
+     exactly the state of the database after which all changes will be
+     included in the changestream. This can be used to create a new replica by
+     using <link linkend="sql-set-transaction"><literal>SET TRANSACTION
+     SNAPSHOT</literal></link> to read the state of the database at the moment
+     the slot was created. This transaction can then be used to dump the
+     database's state at that point in time which afterwards can be updated
+     using the slot's contents without loosing any changes.
+    </para>
+   </sect2>
+  </sect1>
+  <sect1 id="logicaldecoding-walsender">
+   <title>Streaming Replication Protocol Interface</title>
+   <para>
+    The <literal>CREATE_REPLICATION_SLOT SLOT slotname LOGICAL
+    options</literal>, <literal>DROP_REPLICATION_SLOT SLOT slotname</literal>
+    and <literal>START_REPLICATION SLOT slotname LOGICAL options</literal>
+    commands can be used to create, drop and stream changes from a replication
+    slot respectively. These commands are only available over a replication
+    connection; they won't work on the SQL
+    level. See <xref linkend="protocol-replication">.
+   </para>
+   <para>
+    The <command>pg_recvlogical</command> command
+    (see <xref linkend="app-pgrecvlogical">) can be used to control logical
+    decoding over a walsender connection.
+   </para>
+  </sect1>
+  <sect1 id="logicaldecoding-sql">
+   <title>Logical Decoding <acronym>SQL</acronym> Interface</title>
+   <para>
+     See <xref linkend="functions-replication"> for detailed documentation on
+     the SQL-level API for interacting with logical decoding.
+   </para>
+   <para>
+    Synchronous replication (see <xref linkend="synchronous-replication">) is
+    only supported on replication slots used over the walsender interface. The
+    function interface and additional, non-core interfaces do not support
+    synchronous replication.
+   </para>
+  </sect1>
+  <sect1 id="logicaldecoding-catalogs">
+   <title>System catalogs related to logical decoding</title>
+   <para>
+    The <link linkend="catalog-pg-replication-slots"><structname>pg_replication_slots</structname></link>
+    view and the
+    <link linkend="monitoring-stats-views-table"><structname>pg_stat_replication</structname></link>
+    view provide information about the current state of replication slots and
+    walsender connections respectively. These views apply to both physical and
+    logical replication.
+   </para>
+  </sect1>
+  <sect1 id="logicaldecoding-output-plugin">
+   <title>Logical Decoding Output Plugins</title>
+   <para>
+    An example output plugin can be found in the
+    <link linkend="test-decoding">
+     <filename>contrib/test_decoding</filename>
+    </link>
+    subdirectory of the PostgreSQL source tree.
+   </para>
+   <sect2 id="logicaldecoding-output-init">
+    <title>Initialization Function</title>
+    <indexterm zone="logicaldecoding">
+     <primary>_PG_output_plugin_init</primary>
+    </indexterm>
+    <para>
+     An output plugin is loaded by dynamically loading a shared library with
+     the output plugin's name as the library basename. The normal library
+     search path is used to locate the library. To provide the required output
+     plugin callbacks and to indicate that the library is actually an output
+     plugin it needs to provide a function named
+     <function>_PG_output_plugin_init</function>. This function is passed a
+     struct that needs to be filled with the callback function pointers for
+     individual actions.
+     <programlisting>
+typedef struct OutputPluginCallbacks
+{
+    LogicalDecodeStartupCB startup_cb;
+    LogicalDecodeBeginCB begin_cb;
+    LogicalDecodeChangeCB change_cb;
+    LogicalDecodeCommitCB commit_cb;
+    LogicalDecodeShutdownCB shutdown_cb;
+} OutputPluginCallbacks;
+typedef void (*LogicalOutputPluginInit)(struct OutputPluginCallbacks *cb);
+     </programlisting>
+     The <function>begin_cb</function>, <function>change_cb</function>
+     and <function>commit_cb</function> callbacks are required,
+     while <function>startup_cb</function>
+     and <function>shutdown_cb</function> are optional.
+    </para>
+   </sect2>
+
+   <sect2 id="logicaldecoding-capabilities">
+    <title>Capabilities</title>
+    <para>
+     To decode, format and output changes, output plugins can use most of the
+     backend's normal infrastructure, including calling output functions. Read
+     only access to relations is permitted as long as only relations are
+     accessed that either have been created by <command>initdb</command> in
+     the <literal>pg_catalog</literal> schema, or have are marked as user
+     provided catalog tables using
+     <programlisting>
+ALTER TABLE user_catalog_table SET (user_catalog_table = true);
+CREATE TABLE another_catalog_table(data text) WITH (user_catalog_table = true);
+     </programlisting>
+     Any actions leading to xid assignment are prohibited. That, among others,
+     includes writing to tables, performing DDL changes and
+     calling <literal>txid_current()</literal>.
+    </para>
+   </sect2>
+
+   <sect2 id="logicaldecoding-output-plugin-callbacks">
+    <title>Output Plugin Callbacks</title>
+    <para>
+     An output plugin gets notified about changes that are happening via
+     various callbacks it needs to provide.
+    </para>
+    <para>
+     Concurrent transactions are decoded in commit order and only changes
+     belonging to a specific transaction are decoded inbetween
+     the <literal>begin</literal> and <literal>commit</literal>
+     callbacks. Transactions that were rolled back explicitly or implicitly
+     never get
+     decoded. Successfull <link linkend="SQL-SAVEPOINT">SAVEPOINTs</link> are
+     folded into the transaction containing them in the order they were
+     exectuded within that transaction.
+    </para>
+    <note>
+     <para>
+      Only transactions that have already safely been flushed to disk will be
+      decoded. That can lead to a COMMIT not immediately being decoded in a
+      directly following <literal>pg_logical_slot_get_changes()</literal>
+      when <varname>synchronous_commit</varname> is set
+      to <literal>off</literal>.
+     </para>
+    </note>
+    <sect3 id="logicaldecoding-output-plugin-startup">
+     <title>Startup Callback</title>
+     <para>
+      The optional <function>startup_cb</function> callback is called whenever
+      an replication slot is created or asked to stream changes, independent
+      of the number of changes that are ready to be put out.
+      <programlisting>
+typedef void (*LogicalDecodeStartupCB) (
+    struct LogicalDecodingContext *ctx,
+    OutputPluginOptions *options,
+    bool is_init
+);
+      </programlisting>
+      The <literal>is_init</literal> paramter will be true when the
+      replication slot is being created and false
+      otherwise. <parameter>options</parameter> points to a struct of options
+      that output plugins can set:
+      <programlisting>
+typedef struct OutputPluginOptions
+{
+    OutputPluginOutputType output_type;
+} OutputPluginOptions;
+      </programlisting>
+      <literal>output_type</literal> has to either be set to
+      <literal>OUTPUT_PLUGIN_TEXTUAL_OUTPUT</literal>
+      or <literal>OUTPUT_PLUGIN_BINARY_OUTPUT</literal>.
+     </para>
+     <para>
+      The startup callback should validate the options present in
+      <literal>ctx-&gt;output_plugin_options</literal>. If the output plugin
+      needs to have a state, it can
+      use <literal>ctx-&gt;output_plugin_private</literal> to store it.
+     </para>
+    </sect3>
+    <sect3 id="logicaldecoding-output-plugin-shutdown">
+     <title>Shutdown Callback</title>
+     <para>
+      The optional <function>shutdown_cb</function> callback is called
+      whenever a formerly active replication slot is not used anymore and can
+      be used to deallocate resources private to the output plugin. The slot
+      isn't necessarily being dropped, streaming is just being stopped.
+      <programlisting>
+typedef void (*LogicalDecodeShutdownCB) (
+    struct LogicalDecodingContext *ctx
+);
+      </programlisting>
+     </para>
+   </sect3>
+    <sect3 id="logicaldecoding-output-plugin-begin">
+     <title>Transaction Begin Callback</title>
+     <para>
+      The required <function>begin_cb</function> callback is called whenever a
+      start of a commited transaction has been decoded. Aborted transactions
+      and their contents never get decoded.
+      <programlisting>
+typedef void (*LogicalDecodeBeginCB) (
+    struct LogicalDecodingContext *,
+    ReorderBufferTXN *txn
+);
+      </programlisting>
+      The <parameter>txn</parameter> parameter contains meta information about
+      the transaction, like the timestamp at which it has been committed and
+      its XID.
+     </para>
+   </sect3>
+    <sect3 id="logicaldecoding-output-plugin-commit">
+     <title>Transaction End Callback</title>
+     <para>
+      The required <function>commit_cb</function> callback is called whenever
+      a transaction commit has been
+      decoded. The <function>change_cb</function> callbacks for all modified
+      rows will have been called before this, if there have been any modified
+      rows.
+      <programlisting>
+typedef void (*LogicalDecodeCommitCB) (
+    struct LogicalDecodingContext *,
+    ReorderBufferTXN *txn
+);
+      </programlisting>
+     </para>
+    </sect3>
+    <sect3 id="logicaldecoding-output-plugin-change">
+     <title>Callback called for each individual change in a
+     transaction</title>
+     <para>
+      The required <function>change_cb</function> callback is called for every
+      individual row modification inside a transaction, may it be
+      an <command>INSERT</command>, <command>UPDATE</command>
+      or <command>DELETE</command>. Even if the original command modified
+      several rows at once the callback will be called indvidually for each
+      row.
+      <programlisting>
+typedef void (*LogicalDecodeChangeCB) (
+    struct LogicalDecodingContext *ctx,
+    ReorderBufferTXN *txn,
+    Relation relation,
+    ReorderBufferChange *change
+);
+      </programlisting>
+      The <parameter>ctx</parameter> and <parameter>txn</parameter> parameters
+      have the same contents as for the <function>begin_cb</function>
+      and <function>commit_cb</function> callbacks, but additionally the
+      relation descriptor <parameter>relation</parameter> points to the
+      relation the row belongs to and a struct
+      <parameter>change</parameter> describing the row modification are passed
+      in.
+     </para>
+     <note>
+      <para>
+       Only changes in user defined tables that are not unlogged
+       (see <xref linkend="SQL-CREATETABLE-UNLOGGED">) and not temporary
+       (see <xref linkend="SQL-CREATETABLE-TEMPORARY">) can be extracted using
+       logical decoding.
+      </para>
+     </note>
+    </sect3>
+   </sect2>
+   <sect2 id="logicaldecoding-output-plugin-output">
+    <title>Functions for producing output from an output plugin</title>
+    <para>
+     To actually produce output, output plugins can write data to
+     the <literal>StringInfo</literal> output buffer
+     in <literal>ctx-&gt;out</literal> when inside
+     the <function>begin_cb</function>, <function>commit_cb</function>
+     or <function>change_cb</function> callbacks. Before writing to the output
+     buffer <function>OutputPluginPrepareWrite(ctx, last_write)</function> has
+     to be called, and after finishing writing to the
+     buffer <function>OutputPluginWrite(ctx, last_write)</function> has to be
+     called to perform the write. The <parameter>last_write</parameter>
+     indicates whether a particular write was the callback's last write.
+    </para>
+    <para>
+     The following example shows how to output data to the consumer of an
+     output plugin:
+     <programlisting>
+OutputPluginPrepareWrite(ctx, true);
+appendStringInfo(ctx->out, "BEGIN %u", txn->xid);
+OutputPluginWrite(ctx, true);
+     </programlisting>
+    </para>
+   </sect2>
+  </sect1>
+  <sect1 id="logicaldecoding-writer">
+   <title>Logical Decoding Output Writers</title>
+   <para>
+    It is possible to add more output methods in addition to the SQL and
+    replication protocol variants for consuming logical replication data. For
+    details look at the implementation of the SQL interface functions
+    in <filename>src/backend/replication/logical/logicalfuncs.c</filename>.
+    Essentially three functions need to be provided, one to read WAL, one to
+    prepare writing output, and one to write the output
+    (see <xref linkend="logicaldecoding-output-plugin-output">).
+   </para>
+  </sect1>
+  <sect1 id="logicaldecoding-synchronous">
+   <title>Synchronous replication support for Logical Decoding</title>
+   <para>
+    The Logical Decoding support in <productname>PostgreSQL</productname> may
+    be used to to build <link linkend="synchronous-replication">synchronous
+    replication</link> solutions with the same user interface as synchronous
+    replication for <link linkend="streaming-replication">streaming
+    replication</link> if the walsender interface
+    (see <xref linkend="logicaldecoding-walsender">) is used to stream out
+    data. Clients have to send <literal>Standby status update (F)</literal>
+    (see <xref linkend="protocol-replication">) messages, just like streaming
+    replication clients do.
+   </para>
+   <note>
+    <para>
+     A synchronous replica receiving changes via logical decoding will work in
+     the scope of a single database. Since, in contrast to
+     that, <parameter>synchronous_standby_names</parameter> currently is
+     server wide, this means that if more than one database in a cluster
+     require the use of synchronous replication it won't work properly if a
+     replica using logical replication is contained
+     in <parameter>synchronous_standby_names</parameter>. Essentially using a
+     logical replica as a synchronous replica requires that only one database
+     in a cluster is actively used.
+     </para>
+   </note>
+  </sect1>
+ </chapter>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index b47bf52..9bde108 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -219,6 +219,7 @@
 
   &spi;
   &bgworker;
+  &logicaldecoding;
 
  </part>
 
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index cb2dfb2..b13304a 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1309,16 +1309,30 @@ the simple query protocol can be used in walsender mode.
 Passing <literal>database</> as the value instructs walsender to connect to
 the database specified in the <literal>dbname</> parameter, which will allow
 the connection to be used for logical replication from that database.
+</para>
+<para>
+ For the purpose of testing replication commands, you can make a replication
+ connection via <application>psql</application> or any other <literal>libpq</literal>-using
+ tool with a connection string including the <literal>replication</literal> option,
+ e.g.:
+ <programlisting>
+  psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
+ </programlisting>
+ However it is often more useful to use
+ <application>pg_receivexlog</application> (for physical replication) or
+ <application>pg_recvlogical</application> (for logical replication).
+</para>
 
+<para>
 The commands accepted in walsender mode are:
-
 <variablelist>
   <varlistentry>
     <term>IDENTIFY_SYSTEM</term>
     <listitem>
      <para>
-      Requests the server to identify itself. Server replies with a result
-      set of a single row, containing four fields:
+      Requests the server to identify itself. Does not require a database name
+      to be specified for the connection. Server replies with a result set of a
+      single row, containing four fields:
      </para>
 
      <para>
@@ -1381,7 +1395,8 @@ The commands accepted in walsender mode are:
     <listitem>
      <para>
       Requests the server to send over the timeline history file for timeline
-      <replaceable class="parameter">tli</replaceable>.  Server replies with a
+      <replaceable class="parameter">tli</replaceable>. Does not require a database
+      name to be specified for the connection. Server replies with a
       result set of a single row, containing two fields:
      </para>
 
@@ -1764,17 +1779,55 @@ The commands accepted in walsender mode are:
      </para>
     </listitem>
   </varlistentry>
+  <varlistentry>
+    <term><literal>START_REPLICATION</literal> <literal>SLOT</literal> <replaceable class="parameter">slotname</> <literal>LOGICAL</literal> <replaceable class="parameter">XXX/XXX</></term>
+    <listitem>
+     <para>
+      Instructs server to start streaming WAL for logical replication, starting
+      at WAL position <replaceable class="parameter">XXX/XXX</>. The server can
+      reply with an error, e.g. if the requested section of WAL has already
+      been recycled. On success, server responds with a CopyBothResponse
+      message, and then starts to stream WAL to the frontend.
+     </para>
+     <para>
+      The output plugin associated with the selected slot is used
+      to process the output for streaming.
+     </para>
+     <variablelist>
+      <varlistentry>
+       <term><literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
+       <listitem>
+         <para>
+          The name of the slot to stream changes from. This parameter is required,
+          and must correspond to an existing logical replication slot created
+          with <literal>CREATE_REPLICATION_SLOT</literal> in
+          <literal>LOGICAL</literal> mode.
+         </para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><replaceable class="parameter">XXX/XXX</></term>
+       <listitem>
+        <para>
+         The WAL position to begin streaming at.
+        </para>
+       </listitem>
+      </varlistentry>
+     </variablelist>
+    </listitem>
+  </varlistentry>
 
   <varlistentry>
-    <term><literal>DROP_REPLICATION_SLOT</literal> <replaceable class="parameter">slotname</></term>
+    <term><literal>DROP_REPLICATION_SLOT</literal> <literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
     <listitem>
      <para>
-      Drops a replication slot, freeing any reserved server-side resources. If
-      the slot is currently in use by an active connection, this command fails.
+      Drops a physical or logical replication slot, freeing any reserved server-side
+      resources. If the slot is currently in use by an active connection this command
+      fails.
      </para>
      <variablelist>
       <varlistentry>
-       <term><replaceable class="parameter">slotname</></term>
+       <term><literal>SLOT</literal> <replaceable class="parameter">slotname</></term>
        <listitem>
          <para>
           The name of the slot to drop.
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index ce7a5e3..1b0962c 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -183,6 +183,7 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY pgDumpall          SYSTEM "pg_dumpall.sgml">
 <!ENTITY pgIsready          SYSTEM "pg_isready.sgml">
 <!ENTITY pgReceivexlog      SYSTEM "pg_receivexlog.sgml">
+<!ENTITY pgRecvlogical      SYSTEM "pg_recvlogical.sgml">
 <!ENTITY pgResetxlog        SYSTEM "pg_resetxlog.sgml">
 <!ENTITY pgRestore          SYSTEM "pg_restore.sgml">
 <!ENTITY postgres           SYSTEM "postgres-ref.sgml">
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 2b02e66..4847d66 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -580,7 +580,7 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceable>
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-REPLICA-IDENTITY">
     <term><literal>REPLICA IDENTITY</literal></term>
     <listitem>
      <para>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index fc7ad09..2a985b8 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -137,7 +137,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
 
   <variablelist>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-TEMPORARY">
     <term><literal>TEMPORARY</> or <literal>TEMP</></term>
     <listitem>
      <para>
@@ -171,7 +171,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     </listitem>
    </varlistentry>
 
-   <varlistentry>
+   <varlistentry id="SQL-CREATETABLE-UNLOGGED">
     <term><literal>UNLOGGED</></term>
     <listitem>
      <para>
@@ -1051,6 +1051,17 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>user_catalog_table</literal> (<type>boolean</type>)</term>
+    <listitem>
+     <para>
+      Declare a table as an additional catalog table, e.g. for the purpose of
+      logical replication. See
+      <xref linkend="logicaldecoding-capabilities"> for details.
+     </para>
+    </listitem>
+   </varlistentry>
+
    </variablelist>
 
   </refsect2>
diff --git a/doc/src/sgml/ref/pg_recvlogical.sgml b/doc/src/sgml/ref/pg_recvlogical.sgml
new file mode 100644
index 0000000..d27eacb
--- /dev/null
+++ b/doc/src/sgml/ref/pg_recvlogical.sgml
@@ -0,0 +1,338 @@
+<!--
+doc/src/sgml/ref/pg_recvlogical.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="app-pgrecvlogical">
+ <refmeta>
+  <refentrytitle><application>pg_recvlogical</application></refentrytitle>
+  <manvolnum>1</manvolnum>
+  <refmiscinfo>Application</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>pg_recvlogical</refname>
+  <refpurpose>Control logical decoding (see <xref linkend="logicaldecoding">)
+   streams over a walsender connection.</refpurpose>
+ </refnamediv>
+
+ <indexterm zone="app-pgrecvlogical">
+  <primary>pg_recvlogical</primary>
+ </indexterm>
+
+ <refsynopsisdiv>
+  <cmdsynopsis>
+   <command>pg_recvlogical</command>
+   <arg rep="repeat" choice="opt"><option>option</option></arg>
+  </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="R1-APP-PGRECVLOGICAL-1">
+  <title>Description</title>
+  <para>
+   <command>pg_recvlogical</command> controls logical decoding replication
+   slots and streams data from such replication slots.
+  </para>
+  <para>
+   It creates a replication-mode connection, so it is subject to the same
+   constraints as <link
+   linkend="app-pgreceivexlog"><application>pg_receivexlog</application></link>,
+   plus those for logical replication (see <xref
+   linkend="logicaldecoding">).
+  </para>
+
+ </refsect1>
+
+ <refsect1>
+  <title>Options</title>
+
+   <para>
+    <application>pg_recvlogical</application> runs in one of three modes, which
+    control its primary action:
+
+    <variablelist>
+
+     <varlistentry>
+      <term><option>--create</option></term>
+      <listitem>
+       <para>
+        Create a new logical replication slot with the name specified in
+        <option>--slot</option>, using the output plugin
+        <option>--plugin</option>, then exit. The slot is created for the
+        database given in <option>--dbname</option>.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--start</option></term>
+      <listitem>
+       <para>
+        Begin streaming changes from the logical replication slot with the name
+        specified in <option>--slot</option>, continuing until terminated with a
+        signal. If the server side change stream ends with a server
+        shutdown / disconnect, retry in a loop unless <option>--no-loop</option>
+        is specified. The stream format is determined by the output plugin
+        specified when the slot was created.
+       </para>
+       <para>
+        You must connect to the same <option>--dbname</option> as the slot was
+        created with to stream changes from a logical replication slot.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>--drop</option></term>
+      <listitem>
+       <para>
+        Drop the replication slot with the name specified
+        in <option>--slot</option>, then exit.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
+
+   </para>
+
+   <para>
+    <application>pg_recvlogical</application> supports all the usual
+    <literal>libpq</literal>-based options. These are explained in detail in
+    the documentation for
+    <link linkend="APP-PSQL"><application>psql</application></link> and for
+    <link linkend="libpq"><literal>libpq</literal></link>.
+
+    <variablelist>
+
+      <varlistentry>
+       <term><option>-U <replaceable>user</replaceable></option></term>
+       <term><option>--username <replaceable>user</replaceable></option></term>
+       <listitem>
+        <para>
+         Username to connect as. Must have a suitable <literal>pg_hba.conf</literal>
+         entry allowing <literal>replication</literal> connections. Defaults to
+         current operating system user name.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-d <replaceable>database</replaceable></option></term>
+       <term><option>--dbname <replaceable>database</replaceable></option></term>
+       <listitem>
+        <para>
+         The database to connect to in <literal>replication</literal> mode; see
+         mode descriptions for details. May be
+         a <link linkend="LIBPQ-CONNSTRING">libpq connstring</link>
+         instead. Defaults to user name.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-h <replaceable>hostname-or-ip</replaceable></option></term>
+       <term><option>--host <replaceable>hostname-or-ip</replaceable></option></term>
+       <listitem>
+        <para>
+         Host or socket to connect
+         to. See <link linkend="APP-PSQL"><application>psql</application></link>
+         and <link linkend="libpq"><literal>libpq</literal></link>
+         documentation.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-p <replaceable>port</replaceable></option></term>
+       <term><option>--port <replaceable>port</replaceable></option></term>
+       <listitem>
+        <para>
+         Port number to connect to. See
+         <link linkend="R1-APP-PSQL-3"><application>psql</application></link>
+         for an explanation of default port choices when this is not
+         specified.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-w</option></term>
+       <term><option>--no-password</option></term>
+       <listitem>
+        <para>
+         Prevent prompting for a password. Will exit with an error code if a
+         password is required but not available.
+        </para>
+       </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><option>-W</option></term>
+       <term><option>--password</option></term>
+       <listitem>
+        <para>
+         Provide a password for this connection. Please use the pgservice file
+         (see <xref linkend="libpq-pgservice">) or an environment variable
+         instead of this option.
+        </para>
+       </listitem>
+      </varlistentry>
+
+     </variablelist>
+
+   </para>
+
+   <para>
+    The following command-line options control the location and format of the
+    output and other replication behaviour:
+
+    <variablelist>
+
+     <varlistentry>
+      <term><option>-f <replaceable>filename</replaceable></option></term>
+      <term><option>--file=<replaceable>filename</replaceable></option></term>
+      <listitem>
+       <para>
+        Write received and decoded transaction data into this
+        file. Use <literal>-</> for stdout.
+       </para>
+      </listitem>
+     </varlistentry>
+
+
+     <varlistentry>
+      <term><option>-n</option></term>
+      <term><option>--no-loop</option></term>
+      <listitem>
+       <para>
+        When the connection to the server is lost, do not retry in a loop, just exit.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-o <replaceable>NAME</replaceable>[=<replaceable>VALUE</replaceable>]</option></term>
+      <term><option>--option=<replaceable>NAME</replaceable>[=<replaceable>VALUE</replaceable>]</option></term>
+      <listitem>
+       <para>
+        Pass the option <parameter>NAME</parameter> to the output plugin with,
+        if specified, the option value <parameter>NAME</parameter>. Which
+        options exist and their effects depends on the used output plugin.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-F <replaceable>interval_seconds</replaceable></option></term>
+      <term><option>--fsync-interval=<replaceable>interval_seconds</replaceable></option></term>
+      <listitem>
+       <para>
+        How often should
+        <link linkend="app-pgreceivexlog"><application>pg_receivexlog</application></link>
+        issue sync commands to ensure the <parameter>--outputfile</parameter>
+        is safely flushed to disk without being asked by the server to do
+        so. Specifying an interval of <literal>0</literal> disables issuing
+        fsyncs alltogether, while still reporting progress the server.
+         <note>
+          <para>
+           Output written to standard output, pipes and similar can never be
+           safely synced to disk.
+          </para>
+         </note>
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-P <replaceable>plugin</replaceable></option></term>
+      <term><option>--plugin=<replaceable>plugin</replaceable></option></term>
+      <listitem>
+       <para>
+        When creating a slot, use the logical decoding output
+        plugin. See <xref linkend="logicaldecoding">. This option has no
+        effect if the slot already exists.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-s <replaceable>interval_seconds</replaceable></option></term>
+      <term><option>--status-interval=<replaceable>interval_seconds</replaceable></option></term>
+      <listitem>
+       <para>
+        This option has the same effect as the option of the same name in <link
+        linkend="app-pgreceivexlog"><application>pg_receivexlog</application></link>.
+        See the description there.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-S <replaceable>slot_name</replaceable></option></term>
+      <term><option>--slot=<replaceable>slot_name</replaceable></option></term>
+      <listitem>
+       <para>
+        In <option>--start</option> mode, use the existing logical replication slot named
+        <replaceable>slot_name</replaceable>. In <option>--create</option> mode, create the
+        slot with this name. In <option>--drop</option> mode, delete the slot with this name.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-I <replaceable>lsn</replaceable></option></term>
+      <term><option>--startpos=<replaceable>lsn</replaceable></option></term>
+      <listitem>
+       <para>
+        In <option>--start</option> mode, start replication from the given
+        LSN.  For details on the effect of this, see the documentation
+        in <xref linkend="logicaldecoding">
+        and <xref linkend="protocol-replication">. Ignored in other modes.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
+
+   </para>
+
+   <para>
+
+    The following additional options are available:
+
+    <variablelist>
+
+     <varlistentry>
+       <term><option>-v</></term>
+       <term><option>--verbose</></term>
+       <listitem>
+       <para>
+        Output verbose (detailed) error messages suitable for debugging and fault diagnosis.
+       </para>
+       </listitem>
+     </varlistentry>
+
+     <varlistentry>
+       <term><option>-V</></term>
+       <term><option>--version</></term>
+       <listitem>
+       <para>
+        Print the <application>pg_recvlogical</application> version and exit.
+       </para>
+       </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><option>-?</></term>
+      <term><option>--help</></term>
+       <listitem>
+        <para>
+         Show help about <application>pg_recvlogical</application> command line
+         arguments, and exit.
+        </para>
+       </listitem>
+      </varlistentry>
+
+    </variablelist>
+   </para>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 87e8e9e..a6575f5 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -231,6 +231,7 @@
    &pgDumpall;
    &pgIsready;
    &pgReceivexlog;
+   &pgRecvlogical;
    &pgRestore;
    &psqlRef;
    &reindexdb;
-- 
1.8.3.251.g1462b67

#151Andres Freund
andres@2ndquadrant.com
In reply to: Jim Nasby (#98)
Re: Changeset Extraction v7.6.1

On 2014-02-21 15:14:15 -0600, Jim Nasby wrote:

On 2/17/14, 7:31 PM, Robert Haas wrote:

But do you really want to keep that snapshot around long enough to
copy the entire database? I bet you don't: if the database is big,
holding back xmin for long enough to copy the whole thing isn't likely
to be fun.

I can confirm that this would be epic fail, at least for londiste. It takes about 3 weeks for a new copy of a ~2TB database. There's no way that'd work with one snapshot. (Granted, copy performance in londiste is rather lackluster, but still...)

I'd marked this email as todo:
If you have such a huge database you can, with logical decoding at
least, use a basebackup using pg_basebackup or pg_start/stop_backup()
and roll forwards from that... That'll hopefull make such huge copies
much faster.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#152Jim Nasby
jim@nasby.net
In reply to: Andres Freund (#151)
Re: Changeset Extraction v7.6.1

On 5/31/14, 9:11 AM, Andres Freund wrote:

On 2014-02-21 15:14:15 -0600, Jim Nasby wrote:

On 2/17/14, 7:31 PM, Robert Haas wrote:

But do you really want to keep that snapshot around long enough to
copy the entire database? I bet you don't: if the database is big,
holding back xmin for long enough to copy the whole thing isn't likely
to be fun.

I can confirm that this would be epic fail, at least for londiste. It takes about 3 weeks for a new copy of a ~2TB database. There's no way that'd work with one snapshot. (Granted, copy performance in londiste is rather lackluster, but still...)

I'd marked this email as todo:
If you have such a huge database you can, with logical decoding at
least, use a basebackup using pg_basebackup or pg_start/stop_backup()
and roll forwards from that... That'll hopefull make such huge copies
much faster.

Just keep in mind that one of the use cases for logical replication is upgrades.
--
Jim C. Nasby, Data Architect jim@nasby.net
512.569.9461 (cell) http://jim.nasby.net

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#153Andres Freund
andres@2ndquadrant.com
In reply to: Jim Nasby (#152)
Re: Changeset Extraction v7.6.1

On 2014-06-01 00:50:58 -0500, Jim Nasby wrote:

On 5/31/14, 9:11 AM, Andres Freund wrote:

On 2014-02-21 15:14:15 -0600, Jim Nasby wrote:

On 2/17/14, 7:31 PM, Robert Haas wrote:

But do you really want to keep that snapshot around long enough to
copy the entire database? I bet you don't: if the database is big,
holding back xmin for long enough to copy the whole thing isn't likely
to be fun.

I can confirm that this would be epic fail, at least for londiste. It takes about 3 weeks for a new copy of a ~2TB database. There's no way that'd work with one snapshot. (Granted, copy performance in londiste is rather lackluster, but still...)

I'd marked this email as todo:
If you have such a huge database you can, with logical decoding at
least, use a basebackup using pg_basebackup or pg_start/stop_backup()
and roll forwards from that... That'll hopefull make such huge copies
much faster.

Just keep in mind that one of the use cases for logical replication is upgrades.

Should still be fine. Make a physical copy; pg_upgrade; catchup via
logical rep.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#154Euler Taveira
euler@timbira.com.br
In reply to: Andres Freund (#153)
Re: Changeset Extraction v7.6.1

On 01-06-2014 02:57, Andres Freund wrote:

On 2014-06-01 00:50:58 -0500, Jim Nasby wrote:

On 5/31/14, 9:11 AM, Andres Freund wrote:

On 2014-02-21 15:14:15 -0600, Jim Nasby wrote:

On 2/17/14, 7:31 PM, Robert Haas wrote:

But do you really want to keep that snapshot around long enough to
copy the entire database? I bet you don't: if the database is big,
holding back xmin for long enough to copy the whole thing isn't likely
to be fun.

I can confirm that this would be epic fail, at least for londiste. It takes about 3 weeks for a new copy of a ~2TB database. There's no way that'd work with one snapshot. (Granted, copy performance in londiste is rather lackluster, but still...)

I'd marked this email as todo:
If you have such a huge database you can, with logical decoding at
least, use a basebackup using pg_basebackup or pg_start/stop_backup()
and roll forwards from that... That'll hopefull make such huge copies
much faster.

Just keep in mind that one of the use cases for logical replication is upgrades.

Should still be fine. Make a physical copy; pg_upgrade; catchup via
logical rep.

Have in mind that it is not an option if you want to copy *part* of the
database(s) (unless you have space available and want to do the cleanup
after upgrade). In a near future, a (new) tool could do (a) copy schema,
(b) accumulate modifications while copying data, (c) copy whole table
and (d) apply modifications for selected table(s)/schema(s). Such a tool
could even be an alternative to pg_upgrade.

--
Euler Taveira Timbira - http://www.timbira.com.br/
PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#155Jim Nasby
jim@nasby.net
In reply to: Euler Taveira (#154)
Re: Changeset Extraction v7.6.1

On 6/1/14, 10:49 AM, Euler Taveira wrote:

On 01-06-2014 02:57, Andres Freund wrote:

On 2014-06-01 00:50:58 -0500, Jim Nasby wrote:

On 5/31/14, 9:11 AM, Andres Freund wrote:

On 2014-02-21 15:14:15 -0600, Jim Nasby wrote:

On 2/17/14, 7:31 PM, Robert Haas wrote:

But do you really want to keep that snapshot around long enough to
copy the entire database? I bet you don't: if the database is big,
holding back xmin for long enough to copy the whole thing isn't likely
to be fun.

I can confirm that this would be epic fail, at least for londiste. It takes about 3 weeks for a new copy of a ~2TB database. There's no way that'd work with one snapshot. (Granted, copy performance in londiste is rather lackluster, but still...)

I'd marked this email as todo:
If you have such a huge database you can, with logical decoding at
least, use a basebackup using pg_basebackup or pg_start/stop_backup()
and roll forwards from that... That'll hopefull make such huge copies
much faster.

Just keep in mind that one of the use cases for logical replication is upgrades.

Should still be fine. Make a physical copy; pg_upgrade; catchup via
logical rep.

Have in mind that it is not an option if you want to copy *part* of the
database(s) (unless you have space available and want to do the cleanup
after upgrade). In a near future, a (new) tool could do (a) copy schema,
(b) accumulate modifications while copying data, (c) copy whole table
and (d) apply modifications for selected table(s)/schema(s). Such a tool
could even be an alternative to pg_upgrade.

There's also things that pg_upgrade doesn't handle, so it's not always an option.
--
Jim C. Nasby, Data Architect jim@nasby.net
512.569.9461 (cell) http://jim.nasby.net

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers