* @license GNU General Public License, version 2 (GPL-2.0) * * For full copyright and license information, please see * the docs/CREDITS.txt file. * */ namespace phpbb\db; /** * Collects rows for insert into a database until the buffer size is reached. * Then flushes the buffer to the database and starts over again. * * Benefits over collecting a (possibly huge) insert array and then using * $db->sql_multi_insert() include: * * - Going over max packet size of the database connection is usually prevented * because the data is submitted in batches. * * - Reaching database connection timeout is usually prevented because * submission of batches talks to the database every now and then. * * - Usage of less PHP memory because data no longer needed is discarded on * buffer flush. * * Attention: * Please note that users of this class have to call flush() to flush the * remaining rows to the database after their batch insert operation is * finished. * * Usage: * * $buffer = new \phpbb\db\sql_insert_buffer($db, 'test_table', 1234); * * while (do_stuff()) * { * $buffer->insert(array( * 'column1' => 'value1', * 'column2' => 'value2', * )); * } * * $buffer->flush(); * */ class sql_insert_buffer { /** @var \phpbb\db\driver\driver_interface */ protected $db; /** @var string */ protected $table_name; /** @var int */ protected $max_buffered_rows; /** @var array */ protected $buffer = array(); /** * @param \phpbb\db\driver\driver_interface $db * @param string $table_name * @param int $max_buffered_rows */ public function __construct(\phpbb\db\driver\driver_interface $db, $table_name, $max_buffered_rows = 500) { $this->db = $db; $this->table_name = $table_name; $this->max_buffered_rows = $max_buffered_rows; } /** * Inserts a single row into the buffer if multi insert is supported by the * database (otherwise an insert query is sent immediately). Then flushes * the buffer if the number of rows in the buffer is now greater than or * equal to $max_buffered_rows. * * @param array $row * * @return bool True when some data was flushed to the database. * False otherwise. */ public function insert(array $row) { $this->buffer[] = $row; // Flush buffer if it is full or when DB does not support multi inserts. // In the later case, the buffer will always only contain one row. if (!$this->db->multi_insert || sizeof($this->buffer) >= $this->max_buffered_rows) { return $this->flush(); } return false; } /** * Inserts a row set, i.e. an array of rows, by calling insert(). * * Please note that it is in most cases better to use insert() instead of * first building a huge rowset. Or at least sizeof($rows) should be kept * small. * * @param array $rows * * @return bool True when some data was flushed to the database. * False otherwise. */ public function insert_all(array $rows) { // Using bitwise |= because PHP does not have logical ||= $result = 0; foreach ($rows as $row) { $result |= (int) $this->insert($row); } return (bool) $result; } /** * Flushes the buffer content to the DB and clears the buffer. * * @return bool True when some data was flushed to the database. * False otherwise. */ public function flush() { if (!empty($this->buffer)) { $this->db->sql_multi_insert($this->table_name, $this->buffer); $this->buffer = array(); return true; } return false; } }  b8܎ Y- SMfRKN~Kٝ{5oS B'jn ת4}W)8& 3hRXڹ~V%L"9fultGlz]Uվ68^׾M)M`Y lwvU AuEYxFc,l<ְG@qhk:xp@L1>͹7u?AOԸqWZVW֗o:/eP*UI9k[WG~t#q"+FɝϷ۽?7 +6Ю|K%6r,*AπQ%[נyݻ]S# 2ΜB_F++^:6l.iSI YIBr+*f0q egۧf sAKH+e=/T(X=Z;XSXF܊e2ײ,CSmW>Y"Q?^8:QFySi݉ѝZlw@3]yU>n}f?؊|tfHDBYhv5@'އ:Hcgd)ӛ\l*ذXs|X~ıHxb)U[8 $Rz32lQ\M8Msjٲ+2@6?FCfR@0Ch4_hw9*پ-T5xn"i>;%]OMs7εDOzPHD. P$Lb`nT  M))@S:Q1Q`Rkpڙ j#%?W%_UJq3/4×8Ss^vQƮE$M IG1 u@B?ˉij"ק=X

"=|P2[6 ԦI{!0~Curj<d1^\o=qhio&Uc@y%:G:tt3ڲF;m?UbpKz6uc{_PVA;0==CTi$; FW @WBWllikii9d!'9h/sُ"M2l͔dvHC!RHGpv6/Oj R3!Y{л1K*LXkDy5H˘>9r\Q?yCW"I.{u*=י>$?a! NJ 1.FbX`Ve>/mTӇ^!D@߾0Ph#`/66 d޹7[Ɗ+jYa26x0Fg[6nE nav m!g)Jp/U3dIs~'~6bL9[}֖'%[n D9cn,kV:N峠ٳV#9f},(tŃ\Rс VK?tפX{Cq`$@{xmH!}eD$P%* 9|e):"mh=Y hDnPn!Q:rĬV?!I돯8f,b#*LDPYtch]spЭWɛ@qp u s̐֍} ΖU;F+J+Щ0F[C5e?%2VE "0Hj{eBYho ̤[gmй7b"9Q˝}|BLr [3y_'#y٪ z c6\N%no6?l4sln.\[7r7pcoF^yYa ͑-Rm*tm=cIRSDu]:p)p Yca0> Qaٺi*QHq)6i'l>fL* $5ǐk ;Oi9*5Og__A(x%q-w#EY񲇙7TH4= @LDCE7CwyDz?ӑBY$IiPT扪œi85e3Y6ؙ!|_y%ܻd3LQ5`n$k@#quUßSezB#5WH;g>MF,(K<4]O%xp".;+cZ 띮.UtPD^(6H Ӗ-S7(Dw>UFܲtE|: i菇vL.N&uAn{4m@暘l*nJd ?BJx6-=~&3C+fLF ŝrg8LOq:At$ 4?AGoUpHQCSxiHFϨJlOsq9D0Ea8ʡiѮJ.17sn 0MxXfOWH09L'ë&ՓI3&ռ7fm<(aЀVNp6 Z{Ooᄡ¿Y*ar 5z'[kkBҽ (]#UA}'c9:{ |f[ P ߻ %Mh3MaPۮ%!?f7l*PxhbNi@)@ C1`N*/vAT9ς%?b*ڦ]]< {/Q\}Q{d`Yf(agmDz/SD`,;gyΐ2x94=mX+sw3yNB /@IHb?6{%@a:pwoi߹87ZpjkapV؊v @Q $vWЃ겆<7-eU LGR#^8ɷz ej)T!1y6,Ҋ sqFYߖ1Q6z쏖zk+G8G! .X32Ԇn|폣x]Q[%[Nn C)AUc_(h#f%}!ڎf7[My2t;gY,@HkVByf"7zXo(17TIuCjYq T6\]hkq-qjxb ;簊c=Jbih%W?&a]مumHL&Z;}"KUp;%8 z1z{16,A y z;>SC5Ao)BE*jT yLcַ"DZ@/ +5*sJe ;!9UzNpއi6hu~K0 ɓ3߸EsY 2?H 6~x-1>dIc|,x$_-UXٮl}<>.aq!!`t.h&i s)ƣay/W)4ݹlǰ{QמyZ&F/#|:FrWt;P#(d]`oe5h :qjYADS2' cNXǚc$ǩiR!AAo4,uwAG_Mk *R\4Espl'\=)\Ժ$„^&7,8JiM2Hl]s-H{ʺC Qnm'p)Q>OZN)R r-eQ ۳bVgOǿC}cYB9VG+['z {yggWMZъ>i+.8ke± _ F?v#/IIхⱹ˻Yĝ I-SW,JL4[c/hD6)?Ӣ$6~fUr- Y[B5n <6^=#D,3ēDS>rok7=#c(Z .I\b;k؊c)dp-V(Ʋ} :aa CeNN#9?RVXzt:UY'Q(qGW~C-%g+l[U@\D,Q72]2$?'T.[58Y*P;f)is'VM`眵bUz'=$[";u\?{yM;A؛"Aj&_/pKަ];UIO6m$ NQ#j p~IAAeARR:% @ )Z%!m'syzjfem^Su(Wdwn uVg0Iɦb0[5Qy2j&H ߙxHFƣDž|Ua~؃/~:&W"Ahd R$!c/*v$˼ *xGz>JRdu#x`ڞBMDمc ǔF'+ NC2b)Y y騫^^Ó༺5ѡD W{![_"T[踭5_uձ+`(&-V/Mqs+3/9,jV jf0/^b’ȌaEFm(F;eݾ ]FPBLUs02-IVtXk| M͊\+HL7CQC(|q| =~͟9-C5P6$ٰ#a~JpcT"گPAnVNl)دE=0E~eճ#40:1 +kyҚx3@WDItrTX_?bD%@1b}sܹ q^˺GxeTz w9#ƌe [z^4lv ܋Jc )I+4LBH;4K^!$#ƍךمNQtG$TU>korܗ^ y3yOV"ر^DtTLAp*K00Nb~J5`) ]g-?6A& VpܵJNϊ]/rNOB1Aϝ<46eq ɗ0_'wuIAr#y&+L ; HJOKO+,D23.rt"'2C;[ijZ+f$,/"Ov =(HQg9}owv)3Iq%h3DV 8H?~g; 'J^ MQ]smc"!'6W zrB*WrDJb#oI//Z(R@BtY!N^>ۧlPԁiH}К MEt`IN]/ƃ˶z^:{ { wq`O)&gP u@f/PQ]gϭHh3`r?Clz%Uw/Ym" @_OӹhTa]_>[m+!F*2ASDПVsa˨Cs?7ls@S%aoX|; Њ,hn~-y\(Z; *Pi C< H|٠ʣa 3-&D=-& ?ȜOayeNݢc!PoȯbcKYu㓜Rkxm/~u5^\ &N#yf7Qup"63e򜣌̝v=|T/)`j;CNWt=9]łsS^| I jۑ!r@ѯ"C !vN_˚ΞUmX:ҾEZlX|F_ηOIY]ܱVK*!z! /U"kšxVX:k"gDޗ>WLӅ JJ)Ru1hsh!a0{!п-ܗc7wce`mMlPe؜С㖎r PTwpKre"wS/<\R{XsP"V 4jkl cւ9#?ȡPy%ti {_b9v<) T(v3.≽R;6jC.y 8j^m};i|R%]Pn-(rغ*R9_t֌#sBD7"/{Zp 4 <~:l?Oxhd# ;m,Mix޾ZLbp"q@"*L <~WͿ3%I0 tI7MIFV3hɢ!8zX6 p'bFCɋMiZQMׄTuHN;GECQnrC6coq ;NNu9'S;rtƓZ‹1|0^>3 ?\5<|v}7X6=.$~{)_%p%,ps,PC衋ѳT++C=@CS7xwGse_-ZU= pg/ +rn)F>Z(r"~۳\%Fi֌q ƇT'߿t<ζ:_{K5gb(,!iPڽA-teyk^[C,JbMMAR2ϗG2H`l+x S '|:s9K5 N9qJegI@S˔ -W4| _E}+E3zPx9V%%Yw,LE%V55JBx]M߃!دC=~pHXގءojTPU𓗗1FڔN/SM5-uFZR77+"ł>'s"qm/ܤivʎs+K(=[p|\v7{|Kc3rϢɭ]24 9l/ݮz:zbK{mk4~[dML:f"~`SiVNCn ?]˰.>hѫk?MܚHpAˈHEx)}(l8yZ#aLg/^4T"~ ?s UOVvX_KLm{uYBuKl vxo=xx/& fܘ8]GwnN EaԫW@̨JZ z"c˷s= :F'V5"ql2:Y-Iɝ <5L؅@l0,&prS/E_JrbO@5Yc`-ےnv #2^_VIpEX1*(Fb @Ehj 0F@EC"9?(`bSg|d-. 08O)2z~Ą5PEJS>={ `de-N%R"ܢJb>oN iϥ | r^9p;729Sc[Ph4exʵ 6޺Yƶr;6@Cz-v>m }dCT>G'C~3P"Q(Ytb0-Ei409k0e=[F+q>{^˃q#u֙l?{6Lk'5Mogp7ЪeC9ϝY&^(&>C$#-"EԐ4IQAWƥO Vv!z"iś}SWq6q/63Nbx%@aq eVgslĒtS\D&=boC+N7Qgь)3tV8x9VY+K)?!pC9& |Ϲ֤b6!4o6Xf%n?+eeGdJ"82B>.ʬ>{ZltiW<{+UUHɹ*\;-wc{~"a0?P;Pky^zE)..>=M(vOH bSfcǔTKgbx*0Wr=,Z?MOӴvTF|vB ˍcgg{|_H\QrhYaG kJ춻 qȑ܄Ŝ$tNpI!xcՏݮ/Lj[WKuCˉvc3G`sƳG )%Wی|e~Hiw+'ﰅ@BNl64eXВb3R٫KQzFp} ]?";|p橥;g醐 f#W5'Ȧrk{!)v ExĈ&nwPt 96ن76&,#K][ta%"?pw0=<bN=2`S޼ùQR{%fmɻ*I(NAkɊCK;it) fA4u|VQ)Vb~=3RD?"}k|_Obq2Ȍn ςWa'? mg,te>FL3OsOkry<^aW5 DgɊ=\5RF\lQOַ [6WrAg)B4|104+2 H3&Q+Y #Ǥ$I>*@nus3.6HZ8г˃ VVs>8X&pbbj ɼr{hE`P0~b$A%%4my+e;vOM5jk0).W#n`X8=xq*ma^lɇ2>WHTr@ٿG45#ݠ9ygH^ݦI4KVQg ŒJS i?19uzΌA]P< R"[dΝ 2]MfĽu"G ɲ\.4pO*D^Ο6wo+u!cȱtQxO* zkNo +>bzEQ&~UG^jI 4ji^/{y~v$#23$>^^c0 sOζwbQh v-g/dm'\s[;)-)4G(|E 0W"WR}R<- (c2ۚrN ҙ}g~ ,2~JڥpWῠl]Y4ۤ~6B9skU/砨TCIVq9H릶j&gB 3 O0Mcd>WExݯĒџٖ Yqm ߎiۿH+`F^8AX2uYGJooOTl gm"ԇًۜ?\WxkMwn3I]K+RxiʷN'k/vClۿEQjH׋LBgcǞ<| }uZ⇶GMȂ:Vd)X'ڿӫW_M5`^5 }\nb49V'CQM0`a=8g\0c CDάD1.ip``7yQA_6&"DrjPPP}8FaA4OG <A*ҨzSyr5y,4'$O߭vcˢ (8錂Ŷփ%`MfP1]v$jh`͐r@` GM ۖCneGKAo}UR:z MN/CFY7D̙=]wEWOfr0=FKgVfTSb1~\]"Ź>a_-I22tFɹ&65O7`J@XDLA<u=dق)d )#U66\0S;-1*B% |ǬR&T-muڣB7F _aM*l1\"_y{ #{|LHe/{l]`fS^RG_-|~ zd *_v|QGUFB*|D>=]^XTs*4iD1<.PЊ>ho%&&| FS>}4ԕߦ$nD4a,8KKhTY#d8]8{ mO}0 >VYRDPup<#F+0nX>uV>x8)V3I]mbXdC]?r9&t.pg@vyW$M]4R=_Qp֧iF~^ /Y3oXKpz/S_l3 .,A +fu|^Rx`6reܾ4ʬWŷeFgļ] qU+Lߤ0ԫZ#F 5sSgٻ9e|rn; cMs8ȰE 4(5 [iOBfo<*>k;L,׆Mi&"i(jGTjDei %NEv} bi:s5X#Ձ#VE$f9q[uHLJelK_6_CW2_hE#E'GXt\w~V_SxHtjxSJ[cMaQh#TZ#1I\ks.kYt[/S@Bq"h+hHmTPp ~j.˰d^[ta,fa}"vwlz2J&_,SG]XFO>Z-ksAwpEԉ%FxO^+Wap\]ymp)۞O"NH%װ"+ZS hccm O;lPGu- p4|8\A|_iFbøNLu 2퓾Ҕ#6[fMj˩Y@q1W9~ Z n[#۪%M5`@iAZ<( ڶY&c}l X_J_YR}Q_![b+bjcMcLQN;QH)S3njw~FgUNw={}x7Yu+;sMhaa ^gj-00y>: *V{AM[ Dؕь/46u! \u+ꊵS5T-|81vAWI:_@qF H L8šh7zwF$T8ЏKk!fx{8ʞdhW'Hsp'm+R֎yF}i-12q{7c)[SKz[q«qNd]&[Wl,+]4o?WG9OF?vb^D$l%;<`7H4׍u ߪ>`C7=mıYur݈#sEb*=OcGv$@?RL*1t7!D52dl?ǘVF/0wR/zXQiDDExYQQ.#~ 6w۷JFfNab:뫤s7sH$;/iM䢗c1ϢنݨY)w~K$jQhPKyk'Wh#HCcӀϸr}5CQ+v_Qde>/%0O{1ݵNsdcReu( Eyb:%xp[ڄK!It|i*t@Ip+%##){CkK˔gspm\^@8v>[WWi98 kF\=A3/QIg-'_l䠱&CPhsSG}F x):}^Cb9N2%A4viS IEvanb#\5kc7C1WAeY>iٗh7Qn @UndR ^2PpF324r_X;]N5Hog"O.7-dk.DɈ=&2Ck<&7t0ψ&i_oKdj{%O88Ĩ볥Xe@Ɋ*0%,'SL^#d' 4k 1_ ,yGWcX%{k8 @:૥1Mih_fTB@)4._{a:zy}QN%r ʶ\@?j*denxOoUt:՝0̀c7mVaV6,xKh!'`*+DQ7.v9]T9x3H Cv'8UCΟ<]/ݳKvGn'*o}y5v*f\ ҧ )\64(-M `KWf )$" [޽fU.֑hw5*FĶ-?? |xcުxy'9 S,Yp^qŠKa¦KċvkZ5T+"JLɴ!gk; u8h=M NnȽJ2^n[pdLnhmfF?dRvt8;y ča1nqsQ\`~&1i][2>?򰜪T}s&tvY{26s%t(*23ܢSv*[!#,; # (ĀV֪.tHuIn4OswN$WGC׎run~(v Ļ,iF[G!lY !V !6ͩc5Ķ׶ag {_$Ue_՛R/YaxXJ!Z2*'VcV_rߟ;#KNqի[+ZfW`,zeҲѰDؕOs%O1)]Q-KӂR#1jq寋/m#Ҳ_VmA/;Sl 3=fm[4,Y_BL(ڻ+rU}" _%{Gg. 3X?޹\NRSq}01SzOzȱLWN (~Q.ٙn?,A>nQ WѼ*5|>6.'2 vޠ&jFƙD2y0ϐ:B,TI$C斬'cȐ3 .#\'=WXGx#n`=Ɓ2G[.YhOPs TQɭ+UmT[kh{Na!-)x_\*+M.Il@Q~8K?{̄Ɛ8>s-7`T8ѐ[j1 *w')v܄X*ة9 ' ̟r Ki8OB&~WW +s?㐰y娀pyp|I;+?ɬE; ҈ ^RD(2\(Dll$۔;2 e.P_!}I?*:XB@AH!UTZsCĦ) @I/zkڗ"E\buHgdv>M)|้̝x4Ƕ5Bo_9Ta;0ehi++73a 7{eijʼnXw>VŔae*wzmM1NBܳ_?X6j=B{v*LoV5ΰhmg&Шk N6Ou1g%/+2yɆ ׀s9- [ 4!-kaCk.t.aَZ?<|y?<2hPd?)6 tp.e${wv24dn 3<<kPel] jMf 3 (?0 4B]X: HJ(6rMFm+o*b.jIa5dxpRؕ=Uy²x].5_oDZShE&U#n -YT4g# b+M2>9-Oәk^@_ꄋ4iܟ4gr&(jqS}7:6#Kxqtpya  Q<,rdmkwLF9 ܃\4#Fvrޅ툗ACv M$.;ۮ}d%-`sQ,w|5!LPSY~+,L94l1cG.v mG?ws fift+nL=@6!G.X"ƍ7: CImi!9b/\+f!!WHg!|>;Ȍ~nѫtl,0: cif=FQIMˎG[<2"4쨚70O~xM_z)Wn);c@#\h+0J6sG{A؛#-FG#kOҼC{u67DjVxW8(Tk L,(tqNE18߾^RuEah)uF?~c P>LkKaC~i-4lG'6Ymn=C:vݽ%~ysh@=T4b,+Ikۺ?{m6Hd1z;^b%ZbDoaZ%:q-<JcyX%iS9^U=Ot0&[#5[\up-9; PAVppW?|;eH 1!'uzgA 5J$(6c\kA^MG6}M8ck煟;;XRN/շCݻY6+FV @>Z䯲Q1O8;ql&%*?s("4B293눾Aq. 6Y6s;喴ź8ZvQ 7AeI,5NheKn0Kvܧ\`I$km yW% ÅY1e>[U#\Җs(Օ*v}~ZjUQ/EٍOI]|kY xq"2$c5ޮ}wLMU rq|kЮְ]//듦w=Pr} c/|͑Nj+؁3 PUNr mz̪Gg+J CA Dt8^ k$ 2٫V|+V6AjeO|Of{lBVr@g[값3{WKJ (B}<舽 8V vmj{zkی*g}vcA8H~ۚ[k1тĴ23*J]-|Q̔)+|(>\Xz5Z7jYI4~E]F8uP7zyp4o;N#;F>?^GPٛ`l%-n&ay+?q*KQUtw@G Ww>#E&le6LOon vgHIU`8fV0Ц]kwH]@6/P̈Y~iֵ} `3Àd0u/tfz GVa-ϴ0{%&0ˬO^U88MmňEۜGp -fgeJ0"?dK7\?02h9c-u+c)_ˠPOPhb"*%`|sZs4")mky$@$-OZc8BL`=R3,ej& 'A'ށ`-m6Z&dw_ηflH#[pŊΗ<^e6JcOL+ 1mo\cE^%m *VS=*IP̉tGOt0wW.INHH:gB'Yƒ3,VHΞkZ) Ñz(bx}PJE?/UaN̯(Onͫ]C {a9dwT ?C2e=GaL #Nŗ)"lv:7ƕ`nGeފvg𤎽mh%=h'3~'NSo 5Oȼ5H ^*S̟,)-Z-86gūA,.$D@H͊^ 8F5 X-$̐c 3hÀX`"Zya$dpCvc׆}i zbW@e}Wp#+k<\S>;DDh݌+_,g1-l$KSfol{p,e}<5^H0Wn]5YS=B:+HJgGϗX(ZXp ]F;.%A aY~P(1Tlt&еW[| .ƶyzZkjt("o-C7EMKX0HdÕur=S YZߏдK6QxQD qR4WM./H-:{c+:\&M"1v4SQ&q5]w0QPb8o/ɁyR{Rh'fNxh|Su@ᵌ{rDD39JoGZ9] .uiw+BS0踕#COtyͨ^}P$)ň.eP8aoͦ7zZ0,Wˎ9)G6i {,Zd:Wcpn`@m{z75_:)hQcF!q*Ln=]{^׭f%<-c屔xFFNPĠ5v-8vĻ}럿~ZhiI™%#oe()H=Zdfq;,)ݢ'|*H®q2~ tvw~8J BtB7!}sXv5##W>~-=3KsHْ^wO\mW|޵R4 5:\jAޝ.y]Bz)"_ш }NW2T0sfhGm~KQn 1V E2yfо7e( %LW!1yPiٺBB.j0߭ѳav\Nj֍|AhqwV3[WP7Y! K`!N"SYgOUNAe0Z*"9Em>XI]cوf`Vq<\旈q6}tO"5P؝İGh\X 57C7mRS jf=O# l l@͏t٣+@9A.ZvثW'NI"h/ #O긽xF8 &R0X bYYZcI+ o.R1x(hjs[́Ϡ%mFB(BTg ^[&iZ4X:B{,= {u{ z+O[q۹ vӰb(dʁ`4"Ϫ|fXJ̇.xE3|Q)봤N s*kLٯSE,({ U^ = mG)폇xqO:"g Na>n%N8}sDU4rNT8O)Sa tGe^ t]1hX"^^{[4wTZ-(!堝ڢbyanWI7092h h83%(`i@Lx9CDLg3 Ε]l2rMIwq i$ dyL6!4xuzLgn|gkݩXu1WNY{J{7uj O9(邓e%_t7!(ذfptsF4_3X_0_G~k&߬ -LSrYPNUU :Ik?E'`Snc2h?;/ fٹ3_3EYV% 4E +,,]٥pTg9δH:U nP:X) ^H]:]p[9=GgGΛ7z#5C4[1uS9AKtf}1S4?Kn%GL*h sJ]YM4 ĉ2+KNKq{4U^WT9IR]DJO7MV_ۃGUyTc=@ =,k@StD"aH.E.J@׶6lԅnAtE %)hXC,w&B th ò)bF5dϓ=S8hHH,]^*w8ڌRo񐂀y@ї;zv!3O,^WNѓ#Ύu(1Yi3P:7nݣ3O婍1x>3Eݙ l/XpL؅8_} S0v f+ޡEţ+&Fb4%sq-Cl_SYHsIL7, d]aZ*JnL&bY$ƣ֧ToE}p?$G)K#S"R`4m&ɱ[fg$5p9yt([u /ߡ Ҽ2IBۅ\`oܬyk-xUљ eI0;zn&Nٱ񖂵ςB7"'cwqR ($a֢@ԂnqK D2<__ z:ݬ#s{4:Q&5x+MYt꫒;[ ΝIb:?dsN NwIUZ5%"-RID;βPGܠzPkK,Ɲ% 7=8^.=L]Fm3f~9rigl;N }s,: !ovXC%OM8S k]GC$ebԯ:w@/  saɶcռlۊISẑ$"XQ%*|4r."s&x "nyyN)N}a%y822>`"DO5H(+3;aQABVyڵ?o?}P IU[C:lxAs&¡ 32z\a_n;'ᆑbޒHF%V.5(!@j;c-`y3_3b;s uV5/QƱ:-`[@?ȺsKE ٛFyF~>t4T t.CPSz5aWQih*`׾8"YP {8/+AQ 0 }Q !ͺN*_(1K~g:jaV}Eu+(⺭zxk_}y[Fj YpF:)N "$apҤS}:u\wbi1|.>R1DEGW2(*3ze[@yBIjŶ>d!j}?= O2 M'=rx<yw&İ7b@@>, ;͏ =`ͦsٽCjeinmNY:6twŽ4bv|`5:ٮ WVNhtܝ S _?]P^Tb*Ǐ=V d6mx;ALƷ_9XC@^ 3i8Oފ!%qh)~C'kῸu/wJQV\]PX?d(I'^&Y"Q\I!sH~L[yetP]f1ܙN fne[;S-}h $[jQ㡷Y8GB`U<}伵Vƙ*y{Wif;l{.nPsXq.On^~.\k̙^0T~\ݿf~{;۩1 •yߗxUh('NI^DN@dqrx"uΩ6brq*lba/ܓ1׼K3 }LHo>lSg&nBYVleԋy-"{ֺZ)UȨr)@4~tA7{lR$k;U.ls=b .DF'r~ ϡ19,5՘vmW~$x3#"Sxwqu` + |l"/\Ae?"^S=Q"]^rq&w-gTC7jh4>r鴴1g`ˊח2>dϼ7GXSppg 8`)tCsEfUZ՛?LjB=xE|\x7v.UK[2"X:/' TVĤ1N_0,qD=K=qezpF6ϕMg;XſygQH 7SP9s`/t):y#K HĀCdv/R;o 1T욐y82e5#&+@tsmW\bܤA?6BZ'5 J8D纜 >(v.@Q&d+zyÃ6lv>p HOF"4 ߂OֳE9?6À@- FXQ?uIGEKɂ; ;*[FZr}:.R8qv9Bfʶ䐺@7/ ,_r-3x%gp%BO&7T2%ƪ",ҸIL[8 T7,G\`{Ra 6܋.8{lrއλ\WߡKH]YP& >:Dz(H/եXϋeK#ĘFE18PH-I'GmbǨˬJ E&оm`a/?Gp- Н${N vqJW{N:S½)i7sf Kdczok@FmY)J ^βS@A=YR*;ϥLR[aC0\,wwq?QMZFsu^wFCυʩɈϮEFgI7pz3 Wt}/)v,߫T"91Gsewn,[1egol ,2 HR3 ?H Rn8eC+> h xŧJ6&d5Lω]+幵 C'.vGzTUw3 %jl,OZS9,5 ۾ͽwF HN2AĦj]4QP |t=Hq.A W9|Xÿ>Q@Ԁ~&MfAi T=ibaK!=~b+Z |⚗ѓ4}gl:?kJ7K6PZM`/ݤ. 庩tb}9)?  Z=s-|ɴ~+EkK?a tګSM ׯϦ8MLNK6Ilm) 5_84luA$51'YR KZxe>Mz&Nu}6$_mkhk2zJ_eIigSDH}q3Wi(Z$ V#(X2Ob\\6KTEd͘ohHt0lvה(',]/ye'YxUwSw\Ec+ 9l=yĠLUnѥ׬Qº),W)*5 1o*]=,`=1J[T&^y&Of V$&Z]F(8$G}VNr&;-~rر\{bV_eӹiy1Rч># 1͍j#ku &Нޜlg\K% t Sl qԄwTя@2tVbCáO1R OȸM DG==mn[pnnɒze_$/WqxpY`2GEMh77.0=ebRLz4He)kPI5?氦۩$iӖ"8C fþzYpDtD$l-!4 Icͣm%҄,O9<'@s\\lFc5F`Cti'~~_Ӌk ۴Eh V GޤG~X2N][fI&9} x6\xBPb}ʪUzh]7rp+|oِN-@v)*8skyx =Ԁux\r0LL;N:Wr- OR|l8L$P[gl<4[7}|f[af >mUy6 24#Ոxt F>廲@t%uDjCŸVJ+&P[sogÉ1ERzH TMG !se(/ɺK0ǚܷPo?/jyS*H*H(I )Y>8:"uRU!S ǻZcAScߛ?-x@(قTHDrb߳ա3 `s&9وxߣyl/<{ 2Ԋ)}*[97jsy80_Oy:ev|5䙵86]_!/ĝJ4xBVQRʨz.{<)6`gִJ3 `e5X^uRhU'csu :`2ߔA.úa2"3}!}}'#V:F^MR/m]5ε3n,_?EUud-C?tЋArO}a\[f'lj%tA1_Q50i|ikʤ<+ ?$(kr94X*M 2f;)Ԯ~mabQ\\0ߐ-5\>ɼ[%/?E1혉lɷ_ @(R2Dkq`p?i@O</7i3 q )"2:OɒP4t@Sj&]Pḫ7x$Ap@d:K| +~ .'F906[XVcnZ&2]ӊEC&ӡWd'kA؜>i27_z>|>pB5^/PV#m*߄+JZgt P.܍؜"Nr.l1" I<}(X*S&»,x\7烙"9?,\[ )u(4[bXJvfѬ9 kd1 ݗH_Bu@зCU=bGur3{ddUQmyȴ? $VB ;0>Qn DA8v*X}_bXi]Do[pa4ۍvqmqx0lh AvGsm'd-]?=[v'H8~]3">Y 0aDE8iN\̗-Y^{_OBE ;t ͉0u%$톿u $صIF/d2H3 0NiE6;kOc OHFmPob\A\8+^j_q6k-lE H(f Oi@J̠zE-{R鯩^kZK8)Hƙ-dQ9Ws4UX7D$[1:+6ux+7ryp8 Hޜ]ހjuXBK.ɺ47Ҍa $>?!].Z!PܦI4^07Ns idkNJ{q N(1XHt>rPvve& 2C݊Tr[5Sn!<{yuj>b +]9'2Nq?z& O/o<ӻ|ԍBD#NriK{-mW'F'K"4й7AA,F-bӢQ|FWg.?m!4S /ETQ7C4zUՔz,^IN(FzV*Qpfg]Cӂ49߆uI^LBF3-!tk]N!s;qX0: ! u68Sц 3 3Cl4 z췶.9h9,LţQot2aU:\>Ձd}[q-SP1 rJYbd}y+`Cbʦ!"^b Tklc/wS/Z!3SV|;"r+i 7quiȕ- u$|T9=[*Lb@H4fBa]nfGqcE.NP:^8P `hxpRȃ~e4tK+MpJ+*fX(̻FO[- )ӝ2iJ4,65›&([6 UAͺ=MX<2 +J+v\jvl_Q&!Tl}_!}8[4YAIOg *t7ڧGװҖCqTm;P#6/=uqfD]Q'aɂWVR $g( xFC@H]m!jZ(Wd Y+z9!zAxMgEVҿJ-pi΀Za\%c͝og.(V%~!HKͤ7손 '*ž$hl!hTdiŴ\z"$ڷ~)Mjaj]o^EhaݲtD;SrKzlmPTe8{dA hdgwm:fv*/hgYyz*%R!jq, `;fdSnͺ7Y]x™T@+[BtJgML7.|G[a& rx39oXaA:%.iND% 2|\O}sö4pdR3-D~ jjE-"׉$Cm۷!҂}91yXiX&c&H)?DfMӹ)>(i0 f^ZwJ jj۳S x*Zp&]\&a`MhفNc0>kJ@Un,^rK/f0PeW,\s*T?EH0onUt/x.<8\kdNѠ=>n})3D#;kq9ؔ%) dyD4jWk/a'kKJp@/Hp%,lFzvJ*wB;Sq0Hdwc\>ݳcV֚3-a3O597b"d7j01^ٲɾA GrWN=fޗ5 qHWoui w8dƴxM-3s -^Pz4C餹mgG\?'Ysfe;GV[9'<֭@3 0vbHu ?\Ge1'Ê\FDEQ1k}6XqD]EԐlOxuEP=>ai]UPhNpx l:{+4EEv;Qc *=['T_`0S2Ub;i(Gю0XuIԶ4 jf9gҸZ) 91\͞R^"e+417#oDDH6"~[?9B S2ȢK!ꓥcH};oER˲/1Ny{,v:yCº9{p r*1,О2I 2q5 v4 >FAC2}5o=3`sJW} _d6|{R%'# b& ElLEF 1)HL aOF2 @W}xii<9H9-zIdg+;weȫVϐP;XOfL%*O:nlȯkF0D/{ a͂ݷ'0s9Jϰ"v|Ta5I}iW.&Jѧ_OHv~FPK܁.| 3 [2k$rOW$9c?}18mN%KR{pn\G3,LoM,@rNcoV03-]"/&l6ށ}_eܽHZ$$8U;i[HHwFofm.еuLЪD@ el| `P>۞ -(Wx8b8+ÀVB diFw(MH@wN-$]Zr].> Bt "h"f^v"3ݨEh dOT.RRՌ{v[Do18%ܓ<V.g؂6}fS +JbeQ> }WY<o*?DJ=Z޶cOGL@w+4ȃUǫ/HL(X}D =Bw hYaFf$Z=ʼnAnLweR)&I՗Z;/@>[fXh"y_^{(Xgۤ 4] qpI?hk#]Hx",* ź>q8sw mp?tzOKwd_lzӶMUT0lHD~IXrd1p[2=+ ̪//y?d{])հdZ$ jj&ǝuvdNv_tnPCcsLXƥTܓeL2{h?v[3xV]֯|]J\gB ]k&RLc۫o2*},BOY̸*BB>) 15.ZpTJ 9>KOؤT>1?6e ۑo;Jl;қm3TT.;{0/͸J/͗$:W=ܶ_#5ZPՈFۣ`Q鎧mkoZc>6~飊fy(3הN,͕<` Jz:Ĵ:V*),8V  v`kH^nﰒOj^x| de3FQ@3Kli^ D@:/DD V d⃱[ V3m J3߭Nޫx]z&B99]fӤҐTBHcvj'':H}YFƭRKSL?p1E({gCW n1:\l~Xso?[monut܂!pHyaxwoԐfDlhoZ g R/:#H| +|{;gV rr^{Fj[ r6V39W(>? z'tlOsB&D,ʘ٣$:=l/")ap)VTiMJe.>k'!2W#dd'lv!Ⱥ"wb{cEwK;&p:?'UNz` ;Y%y}IoϙR~TOdÚfje p$d싮Lq\vIΓ}> {zrp dc:;1WZVr޳6b]n_WY :X}$&lK/F*Nc;nKHmjL_)G, \> rv!P倠T%deTx+o =$kn?^6MHW) 4bn1tc|-o[/ԇyv}GFҝ91#bǫW~qn$G#HӇJe"O d ?Fzu7 klKZ7]/H,S:'TrӒG5Ush>Y XÊS줦> ]ٸ| o؀zay}›DD+K%WDokkm_P_W?gR4rp|=>N 512qeJ"Z-!IJzH5]ZTޟz8 敵|MjѩAMw`0좝DUpԦ'ȶ8[߰"92ZM[K0*W`* ݼ6C]#2p᎟ǎtn`%#Wǐ@Q* RF0hcO=p*J gtrJ$\K Ers8YyQAhj|]קc ->6Āۆ4lO}oJ@}Q-}ey`O)B,s_&R)|E=B-w!<zv>zCK6XPB'Yd4Wx=v$E C A[o  {UxTcp\ԱjO]aEyz+Y~T#S;y%Y.lea0GߎXilNi4krNv(FUgK* bִ8j=hL+Am$C鮋* MYi[↸) ͩ4_C#񃡝lf^UFH>1RŻ lgnS oM rdD\''ݓ 5HӞ34rDsaDfJҀl 8:?y-Z580Af9>'BRWK}˶@ Pu?R8Rh@a\7҂ vAm½Fsv 0IzToqZbrJfr߯{8pžSr "K ŠvK4[/_sd_SY6dX-AT$? N;J7keF oCH+(~,&u x ]Ѻ[C/߉=s{VNLv`SgWSu _I Y*xX ت-C v%"27ʆJ&!ϫ'ְy Ֆ~ i'Y\u(y9]AO,C4{wQӃQbVV4" ލpgH$N9||ʼ4P{Ђ$P{n$Bm'w0;&?ylI*؂%f{8Z1KSNRݒ@տ]OS%+'&,%d55r;~mw,cհ,@Βc%G'呍n"<>h΃ l ]7+m͒_V: -2Mvq7rZnLg2,.ҥlxPOqM/nH$^8'_6_*Y5Ƭ_~=k|Ҝ1:[Rk P\O(۴F&".ƬD /F=4w,/z {dT3L⦗O|"mJ; |QPZy$x [ЉDS)Z$@m+ kF(=MQ I F޿N{Jyu~p21hwV9d/߮\waɆn(;d:>E&45ACR̓<lj%y|Ib۲ VQJfmjE/z#eKuj?7(k2I#9jW2*AKEtJᎌ *#{1]]">(f~L׵^OT=d9E.aHSpDdxMeA 9=4&g0Ls>w]RD/Y el#(ZDPKWT 2Y":1q1-تb@Y 0/hxTu9Gl!ٯ+̯-9W;y-iCTD,?L@o:;m׷wW [ϻjE FPp4el)?Oê20o:W:KĨh35י wsW'g9)_O!T@pf>+wO'Cs0:puZS+)cu m|7cHNI+YQH(bD-Yp~in,H9}ޖLTP6kNa;cCB*0Zq_v56졭 k";Xcz^:HΏ |rBӸ oVY4wnwh5n\߫誉Nz:,R ]ȁU"hs=~ 7I.n<=Je|V8~.25j.ՎNZ ;{~3kpbD"UeA/%sk;w>` tKH+g p8K0 NJjIߔ8YvpZ?Uѝ"g}c9UzœD}` `A_a]tì"PU1QhAG<'y(s%F]V,tlDElzBcEThh+ZݙK!'}b:<+)f%8Y~ZVmIS c,aek a[R+]UK8]2>?,nb8A٧8xkpkAȭdHڢi7u&a>-!_=JLdyl;ŭש&4{%X1Wʏ\.VPtI}e WG`xͦJLjw\Ic};jZ',g`vDVZ'z+zr[@N"2&d[`l4LgsVnPgdUۗ&YZ0>Y;/* F$sUq=RP$ꐳDlnn[ٔGnx '\F={92!W\ R^s+D {{%bտ-:E)ɓ![k됕3YN}5&Q/s4R%G6{YroC%Db!G]Fgop%jWĩ j%sn Bv[ş5HVC(4 ZrfɌh6ۗ iKղnKiV{\`iF .ssj2~DݭNzyZ`U+ɘB-`իLp GޒM-4ƒ#{.42߄[jm&a~Ǭz{t pF-Щޘ"eN(rt̰N,L"녆2~.gHnjOD%u 5źsP|R+'8Z X]"41hn=n2(f>nsOds=@XLg eU'W[;٭&&ugJ ))KYSH"5Sx{;y`,kT)`희а5/Qg^qʌ[斦)qg;3[[ '~椇.c )0C3gM;ddS} #ˊ^8:]CHqۛB`2ȣo2 Q\[NL+vcqWEKioCzMrf,5kKe!0Ҭ(4^l\o+>)T-x0&dw.3:kt̕W9瑷9'k<{]˰oC]M7`/om31d? mv&Y]^^~&.č3CPaÐ[#%=h|%N ,bz֒tJ8mԿ6Z`A[Uaŷ0|5LD%&!xNHz `wgΉ&GM_%iۇK#LaSL*RFhx(4`BL?z$3HeD yK٬9}E()7>J`\q<%w} w& `^Gaʷe(1+jpҵsiti >eg,0z2RWWzKGb`ِkA-l?FUtN`yJ!^TwgoYDĶp.Y\sUO]W1J[ fҩ܈Pj&}#j6҆' I#G 0N(¹f )y 羚d&s%RMs5v>)Cͳ !@g[_{wH@i]2lQcTJ;[/'G&o`zػRnta ٺĂ8Hs5 PH<1E:K'.{dR0$G+⒞L @kQ]zHV%bxKhh#Pqn%Te,>2< jMF\.}6Q z(t f>f~5FdpiT' o:!^ #ջ4mttbHs!xnjMc&#^fSHkuk$Z(L;\Wrϱ),fnL) + kA! »&(m˕jCoFXMrtQzXA1Wyq !qe[4i+t+5 .