From 54095eb5cb0dbb13d52d15ff5906b05d8a7bac99 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Mon, 30 Nov 2015 14:25:01 -0500 Subject: [PATCH 1/2] Handle the common case of one chunk when calculating the uncompressed size Reference #992 --- data/database.py | 2 ++ ...403d02fea323_add_new_blobupload_columns.py | 28 ++++++++++++++++++ data/model/blob.py | 3 +- endpoints/v2/blob.py | 22 +++++++++++++- test/data/test.db | Bin 1134592 -> 1114112 bytes util/registry/gzipstream.py | 14 +++++++-- 6 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 data/migrations/versions/403d02fea323_add_new_blobupload_columns.py diff --git a/data/database.py b/data/database.py index 297656c6c..b4d7ba986 100644 --- a/data/database.py +++ b/data/database.py @@ -784,6 +784,8 @@ class BlobUpload(BaseModel): sha_state = ResumableSHAField(null=True, default=resumablehashlib.sha256) location = ForeignKeyField(ImageStorageLocation) storage_metadata = JSONField(null=True, default={}) + chunk_count = IntegerField(default=0) + uncompressed_byte_count = IntegerField(null=True) class Meta: database = db diff --git a/data/migrations/versions/403d02fea323_add_new_blobupload_columns.py b/data/migrations/versions/403d02fea323_add_new_blobupload_columns.py new file mode 100644 index 000000000..cb5b74317 --- /dev/null +++ b/data/migrations/versions/403d02fea323_add_new_blobupload_columns.py @@ -0,0 +1,28 @@ +"""Add new blobupload columns + +Revision ID: 403d02fea323 +Revises: 10b999e8db1f +Create Date: 2015-11-30 14:25:46.822730 + +""" + +# revision identifiers, used by Alembic. +revision = '403d02fea323' +down_revision = '10b999e8db1f' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +def upgrade(tables): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('blobupload', sa.Column('chunk_count', sa.Integer(), nullable=False)) + op.add_column('blobupload', sa.Column('uncompressed_byte_count', sa.Integer(), nullable=True)) + ### end Alembic commands ### + + +def downgrade(tables): + ### commands auto generated by Alembic - please adjust! ### + op.drop_column('blobupload', 'uncompressed_byte_count') + op.drop_column('blobupload', 'chunk_count') + ### end Alembic commands ### diff --git a/data/model/blob.py b/data/model/blob.py index b05ce6100..263978ec1 100644 --- a/data/model/blob.py +++ b/data/model/blob.py @@ -26,7 +26,7 @@ def get_repo_blob_by_digest(namespace, repo_name, blob_digest): def store_blob_record_and_temp_link(namespace, repo_name, blob_digest, location_obj, byte_count, - link_expiration_s): + link_expiration_s, uncompressed_byte_count=None): """ Store a record of the blob and temporarily link it to the specified repository. """ random_image_name = str(uuid4()) @@ -35,6 +35,7 @@ def store_blob_record_and_temp_link(namespace, repo_name, blob_digest, location_ try: storage = ImageStorage.get(content_checksum=blob_digest) storage.image_size = byte_count + storage.uncompressed_size = uncompressed_byte_count storage.save() ImageStoragePlacement.get(storage=storage, location=location_obj) diff --git a/endpoints/v2/blob.py b/endpoints/v2/blob.py index e7525c8a9..0d8dc4a4e 100644 --- a/endpoints/v2/blob.py +++ b/endpoints/v2/blob.py @@ -13,6 +13,7 @@ from auth.jwt_auth import process_jwt_auth from endpoints.decorators import anon_protect from util.cache import cache_control from util.registry.filelike import wrap_with_handler, StreamSlice +from util.registry.gzipstream import calculate_size_handler from storage.basestorage import InvalidChunkException @@ -220,6 +221,14 @@ def _upload_chunk(namespace, repo_name, upload_uuid): input_fp = wrap_with_handler(input_fp, found.sha_state.update) + # If this is the first chunk and we're starting at the 0 offset, add a handler to gunzip the + # stream so we can determine the uncompressed size. We'll throw out this data if another chunk + # comes in, but in the common case Docker only sends one chunk. + size_info = None + if start_offset == 0 and found.chunk_count == 0: + size_info, fn = calculate_size_handler() + input_fp = wrap_with_handler(input_fp, fn) + try: length_written, new_metadata, error = storage.stream_upload_chunk(location_set, upload_uuid, start_offset, length, input_fp, @@ -228,8 +237,18 @@ def _upload_chunk(namespace, repo_name, upload_uuid): except InvalidChunkException: _range_not_satisfiable(found.byte_count) + # If we determined an uncompressed size and this is the first chunk, add it to the blob. + # Otherwise, we clear the size from the blob as it was uploaded in multiple chunks. + if size_info is not None and found.chunk_count == 0 and size_info.is_valid: + found.uncompressed_byte_count = size_info.uncompressed_size + elif length_written > 0: + # Otherwise, if we wrote some bytes and the above conditions were not met, then we don't + # know the uncompressed size. + found.uncompressed_byte_count = None + found.storage_metadata = new_metadata found.byte_count += length_written + found.chunk_count += 1 return found, error @@ -257,7 +276,8 @@ def _finish_upload(namespace, repo_name, upload_obj, expected_digest): # Mark the blob as uploaded. model.blob.store_blob_record_and_temp_link(namespace, repo_name, expected_digest, upload_obj.location, upload_obj.byte_count, - app.config['PUSH_TEMP_TAG_EXPIRATION_SEC']) + app.config['PUSH_TEMP_TAG_EXPIRATION_SEC'], + upload_obj.uncompressed_byte_count) # Delete the upload tracking row. upload_obj.delete_instance() diff --git a/test/data/test.db b/test/data/test.db index 335b28e341d4ea58e6dd26512ba1e728d5daa50e..09d116ec48ed6251b3f0c3f9f636c73e796d56a0 100644 GIT binary patch delta 55990 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 G)&DO&3|b)o delta 56656 zcmeFa2b5gJl>j<#x~Ic*_l$&)MktOFl0YrJ{Q8lk&N=5c(CY5@Ugw+}!)OQwC(; zH^TIiSq)5^=fGsY025aLCWIa)Yj)oC_sL}kkcm0<o8? zrZ2Ew?efo^H}9Ey9s;(wPwir*X$_!0J?WXN&7q1jet_AdfBB*SPWl)m^D>0Umsw@X zpI`mSx!oT-Pr*cTjJx+2_uOOmc;-g0LKVmV#|z(BzvGT)z|A85B@lA*_g8-E^fNa& z<{r8Va#g=HHgV(M&Hv)GWaQj4rNqzf29Jgz%@aQk8DDkrRo07sCjobOA(?-HkmE1pbnEVoubr#h=b6K= zfrUK0QhL)L{tG<%3$0qL*;VU8pk*jn_GUrckYSnPz82YWWRZx`Cg#4z)B<6!>-r|t{&fh z%8hfEUVokf`|d^en-5;1n45UOGnc*rRjkK;c-D@m_J0{{`aEpNuOLM2+I`bD63RI%yC7wJ9Azw8A6E%yH46R;7Vy795G)uyk2YGUG) zX*dO5>A~c8379-{8cd$vFbY#-@;_iY^4eYMo4zxN{A2FdH}Aai_VH0<G(b_JMz8cwu>;acujhK*= z!S}C5PC|Br*RDqPAqzN&R?J%iR97S8;7WjO0?7ji3#wNlyyX1aPH+$)n~`1f{{;{? zqS0_8nkhGf%N+HiYzDIHk)6o4xo4Csf%$r54lQ3iuw!H}V~x z%a>DGzS*ia;Gbl(+HPdPOSF2`@o$j5X-N1nS}i~BjZ1A=c_e)E^p4F71TjXvZo`iC z@~J3+%m&}E_N#7ItvmV1($mI(SsyY_+dU?8Y>98d2T6jn7Q$-t3Rsv8?iAn?9jz75Np}Ib9UWY`IHy(WPDSehODGo zaAe+?uMKa{*N_Bg>(nb}j_gp8m!qg}-g&{+HS#HfKrX7bQt1-^2Ho%mp!J712`9zs-#aq&M-$ZRzSz%z(y|J)x&NzfWqT`>Rr4alldDO_OQ zxs9?Z@ZyzlrF=q6EeEAyWEVw*Y zT#IZ&b`JAjy9$wk(6w;ZZv*{nk!fTHxb|A)Ot?n=d@X_@+lNSJT!&BxZ$hNg^U{6D zD|>J8A=He5vsv;6$1Nj|k_&+H~6oEtll*(kUnCD{nhN=f8kV@fiCScka3O-a^>KpkQL zSEnR;#BvyX=Km{EG}_SvXIg?HX7K*B#G=?IpV|v+-y+t&0sJZrD>jKa>%o(0$vD`M zk(`L^1?G%o2V$JBWF$C(3>&o`^79}kp^?+U%ba8rq6e#a$!Tj(lTB?}iL{6Fyxrs* zNxq!Qm&8x|hJ0VhOQzSJIz-C8j?}28t1S^}FL;ob>_$!j|HDhxBWDbYY!W2fSF!S` zl`D~pox=$$Vv4_~&z~(wo<N>)RX zcaZ8;U{^`9eibz&Hp>i&HL4|E{AEG1B#9y3xX9I^uvfT)|mm*?Od+yj0vhipLb`9IAe zqljX+eCn(%$ZQeZaTT%-oOKnl9PGLZQ9(k7w+odBb;14P3s)g~5p>voII~m8_&nTQ zUK`HXgVPdZ-#k*2d~9rn=XC_CBRDOS!6_|C=mc#_Ak$hMg^?Ue=vYq2r`!EXDb>jG zCubUb3QBy~*S0vVr~PEiuvlgG73X17c(8wq10vl_*S0&cf@ zi4tSd940U+t-#~Bmc%oZHiczUS`Nhs8YNJQ;EC56t#&KC$R^_?Z6QP45+hN<;nA~X zoQ!y^ZfC@0vq#BI#Je?pV}h^~EvTj3-E=$7qiq#i#l3 z$fG!_!yu#YS5J!0G(qC57P70;k}OASbwpaw3Iw6!a2?!xbSV(- zNywSkXA-uXWpM&!#D;HE!G>>|9owlKfdoa01dcKcg$i067icX>r7~I_N2atCNyCa# zDIVvDYP;3Ub37cIt$1oHhHuRTy%c6D7_5e#O)vy?eIwq&cw^O8@3&()U$|JCiKT3P z!Ji+Hovc4sC39tKuu{eMwQ{LSvAH`_Eg#i#vEjIGH$jsuLyL@V9*2ysJ(5u!p61dF zj%f*+6X0B8QOGC{=RHGFC<&)L&vS=XB;=A6*>vJK6~Ijl;i3G+5>{E+7ye!Vk{hVmTFfzP?Ht%JSQ?b1A7mmWue#`6ezyBI}@d{Ce9dZ zo4bU`#}JfrwmSkZeVt%9UCFo;}fM)e~#*1~%Ox zDuG@)Vabx5*BA})LUrIWnb>;6T&F8l@+}yhIR%b86v{emxNNq|AgAn+@Fi(1j3+u)6x?O5Cu z@I~Du;c+Cw0oH3`7`rnNvCYsP!b>oI!V>Z^ai86<^H}{x%$SH{j$;>&$SOuKgxINj z#vrR3XUFy~u5gY^V>}~nWf%h`8$s)|I)P1z;tk_a9mSCuYLV4LT}q{#gLKbp2@XhI zAl3*GL3dopcpU{Q*K`J3ko&Ti$di_0*lpWAFcumG{ce*LjGZglbi~r3cQYs)?BRkw zSqk}rOXu`OzUZ`o;smDCrdimJWQx~mS&|^M=@g%WOPqtkOsKWfrF`ZPQvt^2BE#q& zZ-)#!cwIf;ZCFS?Y}k|cg-uyws@tbpdE2C0SF^<`cxS-c8>Rve?mkyCeH2p!#j>r5@tvWnb28T&jwnlqXdHLL zUDe~HJYJV29A_DuKSYM(4zC?|<3`JjGa4hKdM`=^%+|0W;)u9BxY>r{aVr+lA3LJ- zZi2#eBrYVINiC61Lnbkv)uuBHqh-a_!>7^|$uL~LIXsLk z^c}s`R~ND_p5}~3N^l8AGuv%?1MR5Im+{-}MjeeahA0^|b)u1ahL3c)7{3R1g74f0 zHP;R2N)*Q}?k70C8^uY6z`@=b$*L>`yAtK`lor$RaEm7?N~^;&yjDl2Nw_mHnG^*N zh6^2bXdI2HI2$Qu1y{5%=yto+zOkQ6><*UlJ!8KbsnvD69rgS`$Ty1dSTJSW&04H` zz*lD^dzQb>1ht#N2ppS#Wk#ZzR^2msVB$4RW5T5Q$Ncd(Niv$5cdC&sGfQVR$lEDQ zZ>lfN98#Djhh*NVGBYux^1o3vj(;Ov1AOpHl5_U`Q}X96#1AmtCeiQvC+7THPWkz- z-zMqpe#gUf&biJp`3Qo{YL-t*{`aFbbF_L3sYwq}n~=QIL4(93hlpt;Z!&f>|FoV6 zsf`|@CX>9=A%w(`Au*F?xkU1ghw>j!NmSG0*G%3!S)cGv?wkOd_Dw!?*Yv*gG&9yQ zI5Y@s{yRG#LBqh1&i{6VXO|1)o^|4R-LdZ$A=Y7u)#xnwZ$ zH{6Wga$z1^CjGl-N6^VwNUJvrw=X;paQUf--cGn_!sBAS@c>3ee7dk-7m0uelhSR# zmXvyTm~G(z7PrRrI?_aiV;;BLprOltoSOV?gsn5D%}g~JzPi)Zu+WJuW&(oDkMyZgr}~) zU%D35?v<_-sqRCZpnks;gRC4bqXPeWzw|`J0e*cyBdWGyb@T)P|3Zx8fm&rDZ05c+pC3XUpQnm*C zeN46m{EJ+s1b(HAUVT3E=JR?pBDwGs9(+hC!@+GbnPUEHN*T0_ao`&&*-oSYUQ)?U zLoz_CmhD3F;(u#FTP@p;q`?hp*={7a0Q#j`b~2I@u}%QHG?23_*r$Q~?*|uZWLpto z{_`4{fFMb*Y*L0IJkU?dV#wLx+DX|CSk>$(EcVk$+163vEO6@W(jBlu2-}OC2_7Dm zO~bmre!KK1$os&}cSspn4a{2&=I@X$2ixwJt^w=rlxmO!IO$F)32PW;cJGv8qvyrJ zckY6)vln1fcS{K*2Ap@pWpLJf?`~-pfou8cFH3jAdLTn5fGr2%@{WMiLFsB(+2Ejb z*ZQz*YTHVrIy8)mvLGoMCZR(>{G0%f9F*d4O}{Qd^apPmyZ`Jhq>j=uD{1@0x}xsi)eR7U$w2(;cpx)}rud^RDU5t!k1> zwfN1aOm99GTeo2KID~!f5z`sN4;e(@Tqa1}tQ1j>gc0TJm|j7!RElRPT1%{9Sa?K+ zTDF#DQ_vC!&vO|z4Mi?bfzQ7-W*(~Si-d5Nz?p-~WRLH`L@jy|KCEDLy+p5k!}=GB z?UUU->G~)7WpukFtbCorH)rsmPu829(FvIhG@vkAL8pT!Kpf}b5e6D}xReeqd>uoP zWJWr=XH+qQgq2XsQ>WQ9$HN1THZAbbSS4_bR+lEBc@dgia2-kWX&o++>_LVFkP$@9 zrQqQM6-a0p6%CMSDy7x&7&PtaFp`z0872)+>+}Ce%0_FVuj2HTh-+jrF!6zVV+zAH`o37b`UK56GSy+atYEs*w~%e>8d=L}h2UohP37slUcswUxp`7f?r_9vo>>iNH$~OUZUVi-O$N{h^FApku z@+m)s%v!~)HQ*1!-LMKTs(37a(U>d}`AsFsDS$= zP!zVo^Aec_3SdkMMOX_Yq)=Ryz_n6{+5q=SWq&}5;I=WD3#l*2=*P#PfccU_wjP9J z5T^jzGTA9eP0aKw@^Ghx@_qY)e21tqutN@|Xmzoy3~+KNb^o{9g7J`>V&lP=WRhK5 zX(G))LuUpWNHTD>q;Wy3Bh#2RL&FV|hIS}jDh;-;lb^OVl_mrZT6?tch|I$?IW)Vo zG&J!FEX(sW#R`~!fs5D4wOirY9j+uEp5AFliNr;FDkebx2bLz%EQO{~f(AcYC#SaR zIB2hdMi4DS($F;mMWN^wL7|kS7?z^B6tqPEY`y%HtsI^qP?X}d&`AMl>e7@J+NmL* zI*ek)4V~dK;Ij4d&07hU%;%nD7t(C*6-keM{Yl6*P?Jqol;KBC-&jD)k$JCmxk+NsJYG)1Hd0@~$p z49ZCor6FSftJTiisUk+0Nc*; z;NLdLw{PWW0i{Hn3!2eEA%sFhY8r|7B0o=Y( zzH2K+Q5o14X!qB_?jTb%oCP#=QDGbn>*olLbx=IQX>uwMm3H z_>%ZXbGPD8ljSrp`_?_cpN)Bq1f0ob5)nn&K zUz2`Nx=Hfkk#k1w964jrISW73XP1M&eMWKeiffMctzXceodC|yD%K-c&*wj@_z9wT z8+j=?ZdL`l3PwZuq?7bO}GJ29JM1aU$}u!x=jz%~=)r@6Ri=$Q)38 zL19&l%coA?G&;Kxct5XLuTGb$>2|GDO>rYviuosqgfyZ!m4Vy7pjfZEKr^cph0N$h z8L;<@iZ#d;An`@TufUeu6sLg$pHeKF`-WU6k<2Q9`c}os$mPR|-M1=Ch#Xvbt6~ds z88~>WV($i-sA`NZs2a^ys*x1!zEIT=KaX4rR(wf8PK}A@lhF&852cxyG0gnv{Mlbp zNRf$IseH=Kjt=8i_#SxpX2leE^frYOTy~pc3i-%_RDAF@gFQE`0mY$ zHKKH%LO#5huK^G4m!B~@I|}{*{~{kcB15H?je}B3zIk*O0hguZ2IPZBIx4W&`m4Z zH!t0yhBt(s3^WtUsY&#ZdUm)0N70jl;DmC^GK^h<1Xb z(S>0}8O4(PCE4<$vX}HJ%E*q)UfP=|Gj?otR&>iBu3UOl{*t~$8Od8`AEj?E9T}*O zDleXRqu!pDB6>vi7XAHp2;*;upjlSm6nOC_#aeLnO>m1m0o;F+0z*D2g51bzaQe-P z9mvh%_BFS6QU%)2DK{fiVzJfW_UDuqTl-r~i#Aa84)t`jB+b8C3nml1X z{7J=)h+?ID>V4}+XR`pg1y=I+Ps6QgAeL@FD6>kvc?_=G*XQ$66mau-$`x<0-ZkTIQxIj8%C|>Rye*1C zzIklsXcmuIwJT&x$Q-*WmyNwWigYQ;;icZ}rZKp97x$H8SLgKTw21Mh>v#Uu z8Rcgu-^a!yVWS;Q7>yY1p)8@0*=?~>CX?RnG3mn|yVq>8M58dA!R|J}sGUH_jQYI> zLxc>Q45%Rz8$VXkLdAoEQCaN#YnLe>-nj3b)^PB4<+XeMIo;%er<8_+FDXaQI$90V z(HM%(AMYMdB1auDMRLPyM6G%On~~-Lfg|EIW&Xk1AFBkgtk( z=fIe~x23Z~dLcHu6Fja_O(A#9|5BqmVN`P7><)12n2JR1TwK<&t7WR)Ftl}#Or=Ba zSOlL2<6G~Ssc7W(MUV_U`7R%|gNH2=aZUXXO zDo+Lv{_L<&-}MWn5_G<(*aE)yTjd7ucv`-Be*Txr6Gx>Jw~g!t&-_|>Dm(=30=KJG z+hhla=PdA%an-s7sr9N_wFU;zuhyuhkuL*Qqheub?;TG=rtbzH)2N`Vq-Li@B2MJ< zi>+ALfTYhWmtXaD*)p)Yaz^9G`bX_wdjbUgkk#6s8pMf zdw@i(Iu(Xl?p3RHfbS_)+rUTEs!azEjKcw5F|U4TT!Bb)kKJ@rc(c z4x?Z&2qcr@p&^77Z&1w2U@GgwL{fqs_P6~o`Ew8^zqi8V1@W@QFEE%qxeX>iIsqm> zoPX`{aRj~ka=CO~x=baXhKC$As>)0vFM--#m3{0*(b*4bFKP7iukBT-mm!LIwNI6t zME(bqk}4}*vK`#7dT^~jbn}N+?@^AdA4Q}v)~f_})n*H0Mn0^Gh&j8L=FlS_ zT*%Qb&7npv9_D~$?^jLDh=osHib9NBuu%Aa7X9%~iI&nz`-CroMZ3&#}4&hTyN_SuNu~H z#ks2EVUJ$2a_y2rXDVU-#Vgk=0Y?=>@Ci%60l5fXv3jwJ4vfRG$%eqG*MZb-)Vcs% z^*WH8*^Qb-=m%D;d>u;cM)xfMk6#3eZ9I7hT)AQi0}J3)$1U~~v|hlN^Xy3rG?p*Y z=s+*rjs@VdLqN4cAyVEvCh`DoJ5RL|_Q*vmCXOnzQOv#Q1kFOd(!=w4jTC~<5wljR zm#{P?W?i&Owa5~T*GoY^z%q#lUopN&UaWipxJtQzJOkGYGyuS;LfzyLdzE65%AtlW zz*oo@slbNeng!CbBZ1f<;MkEs^bk1Q;tD{{ZHgF*|M=4$973dqj!zUkl@Jv ziMuBzH4*hJlst!j&V;9xZSqAoFShI!>z!(VA;7DUTp$Zoq7U1t5Z)Q-yR~@bn3nE`oirxwG;Ukgp}Y7 zf>RN=34L?Eji@d};0=P3M70|1J5_xg@(s~xw+h@UQK^7MqS^*86u``rkgqSoF?hub z29|6=z6P+<)c>Z?$*0QON6$Y2JaxKy8`yKYdIR#vf>UAdn5qD;6#VFP^(n}|f;;xA zcLLv-Y7FSlP-F0NLGuhXgFGz4*MX0o0UPv#Gt?)+YX-<(HHtjA0Qc-w?}Aqi&e^M` zkOxGNS9$>fee^$&tG0uUW2%Ki*ZeAlstIMm$jBo{Dlc+OJ~iu~HGwB_br5-6WNHtP z66zHTZks#>KLJ9$7BPam2(=q|Of+*9;DwJ8sWu_s6Y-Pq!pCw7_TQuP(2Jr#4&J1C zcv1o<@%-0rQ(eDN`~)(Ot3HRUoL4`gx=20K>GwmKbhVc8<^$S{+mod%@m8)=4w|ao zTE?Ppr1OnH&|qq2s93ufuWK7+GLmaH{GLQISY{F^XNgdrvT;!EXR{Tv%aE&6Eqga^ zOlN8wk4F-{um>xLLWV-4(=(y5k}r`n4C?WE*z2x1ax-Q=+pYNBF%;L9>v`5(>-Adc zl(TD$)*J=aXCmFa!CEhALj^Wx81D-A!v=c2$(&dPS26!o_i|Q#)Fx+c3 ziUWKQEjW#iP&A9yEG=ihPTK6gK`@r?m~l@bU(^Z)3tA2NbnSdNU>G#Yty;Fqc|2~0 zs+uc$k2Yv$+|4eykzSSso+nisC+uj%WG1`?f8SfMlVJ9@6B}m?Ry*&gXWfn_Yb!-E zcGREc3o%E~))V|N5O~li*zsU4>8dcgmdRANXS{6;Yh?vXJkV)1sbI2N8TdMRa|CxL zT!i3Aq_s@gWaFIqPS{el;H;?=sWjrIzNzoexx0P46Q?r%p0VWTLWXQ~hIi(u1eP+; zNt2LpS4~WFd1DB6J#Bn0wzz15kCK|hRIJ=F!{+iOn$6{$$u$e@&h?c{u3%s zBi|QqHUEdWrv6<#U;LYRGxdr2*Pc=#K6syO`rv-`Ba^55bUxA%4>~3&n7->O^f+>0u{GkooDgO@xVO}F2L=I>Mk{Vz)M-uka)oZO;CGih^Do|} z{^WZb#=E>>JfME#4I^hKlJ!ha+bRW{xZTZl>!u{Gr8tw*AIRD0u&-Wd+DkoK)Z_TCd_pQ&?~qg?Wskv~+k~>#ilvwIRC|_iy&y30UOL(ixN1z^ zg6GR*%WlB1zNwnbB=H=TZOrrrLe|-}G+p`#5$<$aq`^wCsdAXM4$7EofL4;Ws;e5e zmcor5bUzP*wPG-zD0awpjHGQs*Ww+7;+_guK-*~6)sLYrzSMKGHb*d+FMARMYPRf|!|Xu{AejpzP{KvV(S7?+=u^aX#kk#|*ltjVor8SzoVL>c*Tda{k2!-<#C$ zx)$`<(n(D%XhFeX8j6?{O=pC9jj@G%MbhH*4(hR9o-(Cs!LWtT2g6Zc+G-0Ij1@C$ z^jV6$z1(&X%)qa!4eCMGW7d13UB1Q<{YbXi(-N5qk721GQE8AhgU%H)d1JgAUQ-LO zk!-`?wz+GCqBjd;GUyqGccYZY>dK{XRxhwU!cK>(Fe=Vv=c49XBuEf!&0=&FP&j3> zwrntHDwd*Mfe>JQ{<76xjT;BuzA;xUSWV`dIo|g6_)H(|WVN{>B{=;FyWQHO(O3b~ zIm}tD;MDb4#?52`#ZuPm>BJmXI%3N;$VyVE8Zt(xp<;m$-(-EAR@dgTHv;)uRi6vF ztb(U&);by{t{V!L*$8K|l>AnBMbc3z*=nI|RiEMc9ETUoq~7G|_~&1GTz&IV^%K!#-4#JUm z$Q&e!Trq|F;;tD-hBN3YnWk0G1haZ$)*aWJXw&{=D;tkS3+8;E zXxHL3ScLG?7J{Um7I@3Alx@Zbse+@)r*XDf&aeqqr}ZUtmNxCd+I<+?QfvlD)Se-$ zB{m)A8eR-_W{dtv(Sq3`bS2pC#v_&lP5SETn4j+mcurdz1hexmJ@wwKe%EF7|Gdep zPLqDSf#~zLq_34UGi@qfjA~>4WB_+E0^zQ3LY;^iO*x%&0Pm#-n(?Y%uz3Q0oxRYk z1ao;qEKZi)aSN5tyUb)AHv~#>=7dufW7c5xCpw%h+T;r+ZJyNj%MMpa@9xAKp}ODc zH#qyeV@7b4yXlTD*Ur|1fykiQ4N*0tv205aMBEZKRO=0)YmU(Nri;jF+ql1G3wdlp ze;@>*W*a4J1*TLs7IZN;+2DGCBG(A^(@`{13|IPi+nzBNdip-@?V;H|Wuw|@N6FVK z5y^0~Tnh+UgDZyX>y=olnn+sp|DVn3j4N$T)$Qp{ zQy2C*>1;HC2D?uASyQX&Ds;0hcfsv7vIUMZVhKLqYn6>*Zx8PMI&Y(c zldg8zpU$*VSIpcid#eHXl0wVcJNzM*KXX}K$r|(A5 z0q5WvWCOlYV0Oh!O{`0V{PC2-iN+hv`4?Y%Pp$qxo77xA;tZ5XoWqJ0eK4H%3S~EM z&ScxkDv8w-A(m))`p#g0$fdPy)~_{_eXI{B7E_MZJbbGj_800gKV$30sS;Dom+C!j zR_`gY>9#4BY}+UznM}K?G-c~}vt^GHbCvj>+0Hhtk)k=STaVY+OZT=GR*11pkffxhBAfODQ&W33knH4nhB=*L^6R^n*m!Vq>l?| zzDR^E=6p3!A_Ui<6|520p8qKp{9+4?A+fAlB$^xpAKj|C4rYI@aV9apYnvvADC%qf@XFAs zf8I8YdH$IbHER*+nKn6naEE3CqDGs)n>*}z2M>M%HoUM?^9{B5_~Rn@iJh8#$8A3M zwe$BcA9A%3@;|#?3NAfKb5L5@R62j&ak9pQs4qTq+ls|PkAG}p-~5kvX*MC!3*YzI z`T5thnhc`w!-v?0%=mXhW^UV~`PqAiv3L0}c7|q&-RzKwp-kp|o}wR1B(n}7A4|Gz zY|)YT1UuPK$(d<3V(0*e`lY+)uEkx!3}4qL=nj1L!W3{;q0lRv(~VjN-VN&nQI;^3 z6VYlurcXE+L(tyvx|rA?=HPRwXw2`4xqUsMTnaea-ek39<}8Ce8k@oK9AEK!oe9Rm z70qb4qoZm8L$eu7bkGoVJtgW`SeqI|8No^N<|G*)O|&~0Fti3HPo%&=sTcKd4U@@l z!V3Lf4Z6y(a?ZWojP7NCUS8@kPVpnpYjLNXZC}%Ex7y>yy1ni*xvLJ0 zt#FlGCrUSq4K|n?3BJjxpdt1j?yj0g2h^P9bpEDJ#VN)J&#u6=)7H7J6r#Fbe z$IzUXUeW6mlI|SCRq$fHXb)S>mWHjJiA0LfB<(463$!KYqD;L$)#x^>6?UN0d14N` zE6*irBms@y1nLe!6NC4?S^a;ew-%fMyVnzmvW|Kr+$q>PJp)l-(0HPm%XeremG%V8 z;zY|)$(*NP8KhHw6pQ6L#uj7iL`gqhNml*!RwttG`wMNW-Dxiw?1^~G9Y`4qv34?- z@4LO6vrd%xP%$2|+rqX6AOr4xF2-O&#+l{< z*?^rR3~bja3|djNWU_n0M$Clw1i@dhnJ`?R`sC)G|4*jZDTf+>^CZGh0R!9l}Msx3DqOPf&pGit@F`N&+kpgID6RS zPhvJ^;5EAq&Ve1iloK#U+cQqBE^Zf`rhc*NBA8aqn&>2|75Ffjt?sS~^-{rNGE_Qr zx>E8s;KQTdwyhUv6j*xTiD>bX8S|C~aed6=uhlB{zTNA$WtmW`PxnezN2OM(JKJ%* zo(WS;XS;=!$N;J>#w+$#juOgEM+nPBNoTx)#rz?>*zvV>LA=;Z81?8Nspqh?t}FC= zRkmyoy0J>Cls5)yteZBbjZ}q+2Whmf6XM2N0;AeKsAm~$Wp~ZcFq*0y9{N0H`(&he94cR zD}!RT&_&_Pe}i1AmMhl{v3`ehmP068tW;bK-=oWQN7*HCEz<8Zpy^JhO0@z7D#{e? zCf-{!7mHPAr{t~nEi)ub+x=Nf*H`WGWR!@P7+54lzHm35=uvq~e&F-4 z7IPxph_xd69F1XFB3BG$W32&Y*4Jx7!r4w`YXy6b@G>>{5^gfjx9bCoyXg}$!4MZ= zTUl+`<#gMbJnr$6Y>Y@nTDoAe<0%$GQQT99FMTG+fWO(&@`A182QSTNR;}AUGVviz zN39$Gq4Fz=kIJ`=-7Bq0)T4G}`^dk+1Nm*>y9YEsR-E+mUk1Zd=FH0)Gx+_i=Ihd} zvVAPL?|hAGMQY3N5W8vN5W8?(zx37#J$T;*nz}k2+4AAVGwfxz!t?N&3pKAwuXSn8 z0c$T3Pv)CmFRqmiizA?Z5j>fXe?Zfho@w~pH2B~L;9;Mi9wM$4>p6J=5$w4J*3-LK z(^k8PZ@wNuk6r`oIrS3FGtxV+c;NH%(;w8FfJi^?`)dW9{vpkEqi3%Nvwzd90BO&% zyCH!yfqc;0Zuq=|lAo;xntU+YkGZIvx9k~Eokn6{Cmr@gsEgLz zaTFdsVs$FTXno}YY6?}XMfjwsz8{4CeS15?8CxW+ExRp#>r5ioVTu`&>BDDMbwVCK z*kGnHODIQ{dWL$nL<$Cz#f`DfmNDRqL^2gNWGP0NK!7qgEAF^8=d)rZPnYJ=lqF@f z*V1l%z39<5vIAYcTC-Hs+J+k~`_N+3L84B#9y*TdQD=f}8UbV6a1QLXGrf6R~L1 zCFIIvxB~wR+O>r&cK%Pbt zBi|qKjEn%&?HZkex#Zx_+z$#>a1s2L8}RS9YvA|O*r!wLg#8zT@jEo|YjZw#K;iz) zb9HdJ_}}D~Ge5l&o4pfQ{~e-pcS3a8x6xOW2bS*#4~U@WMG&FKpRzuD>y04wrAZH{ z-339rpSo7A|3v+CaAp!>y)1%M*Vx!)r~Ts~*nPLgt3pWl+>}J3P|WU}yW_K4Wn;O& z$*=q~xc2)Hee}x^{R}ERAD!xrfaU)QL6?Xi;=x~?YHKck0X+0&$lD2f=1<#V_+ALS zCL(<7AVg58Xa1%#-E|Up^dLlFmlgi%{rR_E2EY9QM7U`lBAmW$?;YW5KXUfm|J?2Y zC*A`gdp;zw!)sXAfV1y`Md&2E-?ib_FM#qFVN39PA;PvNFIrAXgU^CTw?QiRh#>M0 z-~NGP^O`HcOZUPu8zah>Pk!>p4*-qW`mcROL?9=xwXeLb4qo{RL>Rx~=g&<%x_1Ih zo&_m9ai0d0fBLVb)7R{L6+9h)kjPhI5!p-k=#}%i_W?`}K|d8i;*O11Pdo_Di$GBN zeh6B%`ONx;SAO|#;9-%!Ux}bIl>GZ5|Mf=~n0^4(wQS-U*{X9+Re*bMg$RFq03uA> z{jt9ve|2FO*!3VpShMfzr*3`t_>JJB#tF~Chcs8bxBI=zyWeAPxchCKX}Mi)O4~#Y zl#oh<>1w1Oirafm=)FBYsO4=Q^!=T z#)?o)jHV2Af7@vC_dLdO9n<@*Id@J^S8~o+j~ZyxMn2n4(Wycy?TC4tj4=bFduNit zM6+!*QdYuI9Ta21M1uCA#zfy9Nm%uUGIak@#%`z*8`!MnR63NU>p7gG;$~f;oH5yK z{*JBWD{3oziD zXX(RJK(J^q=HOlD3g!-bb$&bEafVXxD+hG8Jce1DZm!>hen@jX&S8{+aI$SCGbq{V zR2(OAO)}YY=S&e@pv=}1?RME$D{`?U)}rQLeEhw`-@9(nc=Amqb*JwpbdFNOVx!Cv zitwVAimTC0HDhg)&(%#biExliq;=6q-j$88U98}OK?>nPC1FBz@CFqLDIM&s(=}N|lCT(0Rm2{#Jf8U(y)Pv3%uARX!s@Jf2 z%c*LdNfOZ8i<6#8pCBRyAL%R>Vt79p_Tc_TH(81_aXsBh2DL?V*wW0_x+S9AD)4UB z6gOI&gwx#V#f4rq%eHXA+O>2FT{c)}d)8 zPz*NhTA`iNH6pQ2o^It(65fV#St_+U%N7SkM>lHBwkc!2=dE~}@To^LhSj>pV5kb0 zZz~;k`e-|5q2pM%3e6!xHBcmTbr`n!)O&WicYRhb71i$ULNKzv<=~ux8&45MQ_$#l z+se?M+=NFCtF7-5tk9K4*Xue%+G%!Jx}GL&Oa%sci@x0QTM`yOo972~uxIs@N`xtw z)$@MAAH_3txfl*+f@sFc(k)Xx()W97v_Fg|qc8wHQcZetj<9P`4v?uC)*KxKJ^8-h z*)4ke9fOhd#ltOURbU$au!$@+1drR(P4Yg@+^JTA+Cj9~C+gKK&S&l2KH2D$To{(F zWvsQRevqgXQMa$@Y6xw%N+#Kq**$2&T_QmlZJ~IV?T0XLkILz5b)k@pc})3Itlouz z#Pw9z=CllK>896TwJ}66>S@@*@S8a@_<&(EJ)5Bt=2KYLkEWr=5zl1%)i&v^I8lG3 z#JB9mRIigxyM<&TGpMm)1Evk@!Amb{R;@{nOne;182o(vd}UT~itKx1oOHwJmys(+ zlF*>B7o7Ey<|_5?e*fQ}T0FVeUxLPlGk&M}q4Y2TcnG1Uzx@mNGc-2hDZI8Fvrk1w{Kt@=&xwoq*8_l|O0%@J1Q9<Z%cWlbKD9{872pP0Y)&zhZx^fMd%QSi;bz$k>(CoNJPk%H=9 zHC6S@zDF&KOkegv7!I)OZ<>{e!r>mRiE!}3pP_Z;(!Xn7kzSShg#a#n1zJt=+mA7? zTGzC)-w%bCjG!v>WoalL@9>Y-`ir-D7bwrFi-YrZb;qODcZThHlI9z&sk zSn~Qc6=R?ccf`qw_o58mZ6p8E zD1*bZx{yYFu6DEA(bExvAbj;q2FuwyJ~n6Ww=?mAsoZV)NFO#RnJYc6mrCdjd9T*h ziWTx5HkHgdN!H-W!|CJp4dSRNSw!iu*HJ9{>opGdxS{=BTL^aRsca}vOBHOMb}yF+ zgu5<%nsZxXy_q1Hgf1+jHJ5DE94&ohP}G&2^_Gwehtqm^XQ9@xZ;Tn-b!c54(2svO?Ag0J1AA**N$59v1lsbx8QE7m`P`#{-_TnJY=khH_ZKz zqs7B3(Jqc^ds@zRsN*fgXwu_K>(RK&7qbLtd%B%Zc6D$uz#BKkv^NW1jt@mm{!GS` zYr=1lBlQVBYbAPypu-rV3#K-_RVNhdx{58G^Ez^U3I+|s?`d*~*K;<$H>=-uS-pGW z=!mexvsy6p%wC7X&IU2Nz;`=QqELuHKaz_P^3F(;ZxyZSSUHfgcmuwwA(3-+;LX^E zyV}kcBYf6C>y3QNoG0VOZmvo}$GnRy$9wQnkBcPJo?O5mu)sG6^!Z-0SG1ck=bki`zTBAcmJP+Y-eDhL8MnWl_feiyD&7n>N0#Ot`Zr$#~ z>$_RXWN5jYvHnv_cMWvhtj>jJPj)hs%*^&q z!X+djgh0aWD3N5#vPmGZEm^WQ1;;BEt+hBVosj5*(fqp@6E{YQ-&~91XjzYTCte%NI+1S_7wF`>&9vZ(S0s586Wj9+Mzt+^?5;_yB1dGiM!8TTFs*ZkGzkB$3)2gV(acMffBn?L%4>-M6_P6qz>2j{$D??=JTeCyP$3qSJb z-#X@cc?eu@p6)1D03{fZGPvL==K@l@-IM?5 z>i>52p?~`6E$bs3fTZvJ&(O0&gzGO>CBIQ;@#)G0sA<}A?)x6 zwv=N?|N8qM-g)LJ&lvtIe!*?)ZxY~g>m$JT8K-~eE#;5A{qNRq`N+=84nEiOq= z`%nApTl-+J=%c{li1NHYJ>vs?VT~xj^x#K#kOQ}W_W4&FI=#O>odu)3^kcy3vi(mw zOWOaykJoVxb#Tq=ZvhU^{P#<~3nU!@3m#nH08tV9XpZ7T?|k|xopVh8k8fM62pI6~d%*u7 zzk9)s^%*x!03 zkd?mu-`4T_fawz()6P%zH$Lvi;@dzz0bFz7=YR6lL(lx)UF)Z|z;k`>R^U+j_)GED z7ysc&AfEsnp7pM8zV^A?Th{B#ehM7E@=4%u&RZ`3`-|T5$Jehj8kqW@0;cDd?!QyG zikYvk{S>(7a^syBs<*Yjw0_6WfP--xaCq8J2QyUq@V)EnZvze|?LTtWcKM9^)~9b0 z2jT6&;mp5&Z+_05KO)wrZXW(;8xzjI{&sfieRcivCKx8a1DGzoPkdkRtI4hF@mF@Z zH-38Ol(RpwZ|A*74juANz5n2=4uq%Fw(mYk+5ZH<<-TEsx@@g}dPmtAQjeZ;K_UHZ zpWfNqcHVW?z3cqWog2=4e)HH_dQ&-|KU`t(l{>-IcR#bkZ|m=$e|Yb<&+N>==X2z9 z`!3%reQsyEwf)`mF8JWyd;WaqSz8A`|ML6pJvPmM@#j0_`pI|gd}aIE&V#4#{p7Bl z7Xt3SABy)s@QXmL_At2C_8dRBOYt?9Z z6J8*XijBP9N#^dVMoBBT?P9oWhoY{`9Mc486)h#hYDuO?hU^imD3;w0t<0+(x#8EW zT1!H6474ldQ7`jLt2tKW8i|Un(x9(%V+n3F$38r@K`m*2*!CJI%b6X@losud)t%Lg z-WbR|=PeYRVoZ8GqNcqn)8vG4skIOdIG>Z{s#7MM$g7Xt!0sn`HGyI{BY}uouh!|~ z4W`!{`^8n%pLvx9YgRWR*9)&P*V6TCE-yr{JO7FsZuys;6IsIJeb9bvjm*Q7o3@2s zqnnP~Hl1)%Wxn|bqf}W&HHBmQjAD=$KblCUQ?D?^p|Bb+yFndKt&yPz3)!!>nsX7- z%(_8W>3(-XHgy*0QBN!}tmpL_H$moe%&kNt74w^mjkd6|ssvt|V1hRv%d4YUsL`oi z4=B7JwicveB6_+A=kUTTmYQHz%@?JvIP_4v!_`QoWtdr`2v>8nsXM9du#5!JxC7*= zyF8qY`1vw)p~h5i869cmOxwMcK@or)tx>B{m2xw;Mq|R&mfR5O&|C@wG3aL8@QA6Z z`_*N&#FU#OURp>kPSlq;GwvIKNA%L=lCu(R(bNI*%q*9Jya<@oA(x=ARa#X!4aO79 z={J2d&1y-q97)lp@cB0<4%)~4p#9i1A-no*LM3zt{>-+~Y!)bSDxnfr>Wrp<3k5MJ zu%!Y$XD>2^C5PY~B6x(DfL45Xu*#PnI|%`6$^@sC(U9U7ZCZ?$ItxKicO>SjgQ-?p z945&)Lsr!=qe^Imv|GgvS}IL>M=1{EWH69{al2wS8;sRRx4cCho9{XuWDm zdJUc@t41rLTsO9`I1$*SL=9wf8R+JS#^Dvm_(Bt@H%2{C9L_pz$Va)zSlDoXR(Aqb zG0KrumRxbrHtHzIeY#MslaYoK5n2dkqB`hVI6sf;gZZ+RcOi}@XA@p@6})e&trg3G z4i-YTsD4jhSoL|?8^&grp8+w-Nk^P>t*$xs7F3hzO=3_2Yn9}wJC8s7p+nSZCxNETmz+XxfB7VF>zDg}yzg~S{mF9g+TFtAwhnPM#+Zrk3rPjBsg@QlI=aDsl`{5i65dE=P{a&P{)!gGM_)9<>GITiz5^|%7L{?X$L z-#dBV+q9GJUjOYA3O5`%k2@B)Z5lyA66EL;3yW>%?)ru6Up}#L!{aRW|47k19M*Nu zDqOMtr?U$4gU`R`jM}l0J7Xt|KP!It>1e#7|v!M z&44^ohx(hd!EkRnr;r{jW8eSOvEhDoHhB6Mo?AF;Yy0FUJqOv#o?JL*3slU$a=iKR zF)rwLybJvL-#M?aedH|qkvoE4;3wx5ria5D{|EJmC(_vkMWatCtWMeb#ojY6D)^_I zi29CW)VHC@d`zXm!%GNlI5L%EDAl7h7l}|@6=fB#h^|Sl`Yj-n*=KyT8M2140myMKZ;#By|=?$;=a=GJ@5TDKj1S+43Nh0qxQPuEKK1b4whjhbn5LjTI;)9W_fL zmumr@uwl-4S+CZ`w4o1()$(a&SY#J+D_jnd(6203>bP8HqLClzc83_+T#CS)Rb_J- zg;|YLof-=bR8<9>SAgrZ9x3{2=}P5s8R|+^w^B2Ou2hRZ0J-SqwujnYDp_;c*ryf@=gT4;;#7EByf?MtmU5j1*M`zi-oS6U_jtUai?|adX+sCL>W;_IRG)YpTSv z<%~UAYnS=5Hk68%g>=BSNh1SH1mRt1RNY>gR0))f7jvW8ZzSa;EzM>Qz~;08-miH% zu|j5z_AD)X1cte+9SvCXF+h41g1We&8mt*9xHh;OuYT z{Oi5T8U@gPaK<0M>xT7>M4@x$_yvz{bq}{b+_MId-sNQBCEHiN{H5Pof0``ZaOQE_-&{U5=pR{VLMyoYj zt}xrpxeifdN(;>v$UGNE5VI^}WJPOtn0k9$Sh^EVdRi&EFZKc(86_2c2xVyAd%wAM<1W?jxcDMwM z=1Oq_fDRF{ZDhce(U8E$Ib{}oqEVjAyTPyuh>*G-JYmKQt-K5gqSVhKgs78kM_;wq z58Qav0(}Dj8S^q!E z@?Tu296Y)5vgQH)i5IV-cLS*P-WM0(gXjJ7B~O3Oi{3w4zjgypt3zOVBD?=%=ihkJ z=hrXacztVQLjL@PE%F0D_|5A+d%MKPxFSv=i`D6F3 zuM@y1kqI20Yu}RzpS`fLz7pL9fcnOC{^#F$JM_JeoVFfrVEva`!1Vaj|My)_K6>pF z)_=1>diReuBfs^G(@!ouiCLffTyWtlH>N}W+umCE)%(7&e(Jx1C)%-rsr<1wD{m=0@kzg42MieNYzLSwds^Wd33>b{*OOf^*4sCxXJ7p5TQ1#M z|K<9s_kas8ayJ)V`t0}ah<_ulU*v+{AeE)`TT=?EA-n_nNGs5$I;P712yg|5K1&BT=(W8iQm_KE7*-@W^m^}z{ns62=KCU?`X-1W7azdc1C_MY?4 zKYq{aH1NKS0C=OHV*iRd@b)LKUv(E4;0GJi!QN@+q4&&xvOYfqmuz;0C;j}K!|Qt} z@CZK(fx~ISYme;Akk$IXObZ}Ea^-ImBv(%h&phRcwJ)82ow&a2rUG|MR5*dV9q&c+ zWxpo|bEetC2KiDzjZ8d0NOX4N?<(OIU<9oKfHi-pV+INyhm+ zs@IvS2X#Di(Nsoouylc-fTAogY+gq?whvmd<*+sy!DgTla=xlN7827yBQzn$voYHr z*`=dZ#Y|e5@8k(A4{EyaAc82_9%%KB$kK{r!)k!H20CJ3X*%q?SrbNArFzdij><j^| zZ_$O#h7pwq+9(l&WiilPXIM`y6o)}yc`*i<+9Km-^UyPUQQ8XHQ6=Ictp%Qjs<$ec z6u|<^P7p2`bl_|*;9*;%6H%i5vgO8Oj4}iuI9^v<-H|(BGN)>2t#}qMX?29^E)e-; zY(O)e#woKZ1%o-Sji>O+Qx|Bgb&xz@D!R9#+sTX_awt(+mhv1Fe^r(Wm2(wW>*qCc zSPMGfoiys6%}8Pj!00a*PSi3U@1_2+RO9SJvwA^rlNnzz02EVQEUD>)l%ioJZP~Np z#6rS>xSZ4sb`Z7XT&d!G#~jv)e%El!a2f=waA#TD$u?u=Y+eI``o}Sk$zAOM=Lz{=}s7e z6L>Sw+Zq%3Fl&amrE?=t4skoYfs+y;C-KY|Jp9>UcWAUxbU~z_n%`wxc9>k7uc=sn}4oE zdzXH+5N~b2;tT4n>koabaKp~nee?|cob9#t@xqnbkMK_$RnHx)HEV;EHetmd->*X=nq z)GBb?Fv|mb)JE&G*-TY+t4a_YUP%G7Uz=6h_%PBX*+&qTX2(6IJBU|9lWUgsBC*Ji zN>fjxOOza^ShX8UMt!9V#ok=-D0MQO`b3tt=2|fa(o0%9(hRb>n6;hE6PwE%qD)60 z^D>~r24A)y;3bkVmuiAE>!_zT)3`L_+FDoV48)Q#!WDD9x2ReY-L%wIVijEpt*b<) zwW~HWsXDMekvn(*B?dPSkZwQ>Jph3-Ve0j){wUF^IH6;6$;N5cYtntb4VRaF+*-BZ zo>tXs-FT5yNDAeLZF#JLD&+?X$SGR~_AYp^Fg=k0InL48uYb?%p6D_pYe4vHOb!A2 z*D7A(^%z4v43xesI3|x}c)AjLeTnx6o$eHGEf_QqneoWY%p}x%)<~|XPJ6M)L~LFO zFaWXeS&^7l^Ik2Z2AW;3nd;J>eKB6sFoX#gL zm~ivV5t3OC7gV?rfNir>pV&F0tin#_yAyxj)nLmvIuU5)Y==R;;~7Ldo3@IH420zD zgfBG=91w!|!vRRis93i|cA1)5Y!b<+%`0WoV)7s|Bx`86bxiG1l+LYCiz)}*N(Y_| z`*l!m%2F;ptU=RmU^HO~C@vdbJ1VAKCMtRv%EAh0f$8ZrGLMsRPQ$!dN=S_Guy{ZZ zY295F!4ai!JMFute(m6A4!rr4OSW%6>E8Xx)`#}JdLRDU+L>oa z`R{C8_fWf6oOI-peEs)t+r8!x`u@-U_st#waL{#>fF7<7-nc8i;SYA_+Z(*+`5jK#BvvKyULE#YXRVNW!hf9(nGi? zn{;FvU9H-JGIOg_d7SF0U@}R*Vw}EICZJHr6g_4d^}L)8XymgdEg!;WFN8p(Gl53>Jvl)44o@* zJQ9G`Nm|MKPzA~-KuLiFa!(0cPwC3oODixJuX1q^;EIE}h>pjlX$-_m7|`Vj`Xr-% z?nm%E0PGpIHeJekvBQ^^*@US$D;SFqswwkDQ9_#i5ic|p3NsoN6`4{^%B0#e9^iz2 zYv!gQyc*#aoVQG?Q}elhK**mC*xBc)|;cb4TMSuu?@7`W^uJrEYGD*Z#<}kZg-9-Ex?F|yOrL& z56YqE-MNSKvz9q>yktgDY$lWVQ9b8Y?cu_U=Lr+`1|2k_m;e)SmCij!%CJcpG{E>6 z(+wvoN=7K4Kbw^FrcTn!`cNfgt=R)IQ;k*-pd2&;Ot4jFq5&O&7cZV1T>_xi8DpviXHnHf~(c215h_J@3p5L&~I!G zBGSS^sdiD(yxcHH$)wD$05}dS6Dd*E6`H55MR6ztVh@KYxj1OU*}du96Z82v&Sy}K z^`ggy9{F#PVFEIX^`xm+m$B)TEo;Gfi8EgMfJOo?O35&qOp#_##+V==)%tQ`%pHFm zYc2ysM74UW)ByxY&`dyU7%Jl&285iZ{Yig0s1BB8V-Y6Ps^~Uh9h|u%i z%)-q@#WK3=Q7-S0e0fmMpsrAMh=$v1tU7p8D$(^S83Zk!nptKDLtUV%Gx9kx2+C8^ zVFwUghak+Y*Sc2E%n~!M=%OYW6=Sl;)m6{i(Bu9jRrw1lz=PYt4>mdt_4di{Q{ zUmwULvm>zbOde8zNSX*6O@rKsE|1D{98kGmB###`7j z8Ug-VxL8g)vKCIK)q&?wJXnd4(LgR*#84}u@z7H^rDaBQz5!0TBbuGI@NTJ+!EvhA zn`EGJNfTAgZa#>l#cb+;VyILmBWH$GVrc{~M8Kyq2dIsaP7P4$aC9-6KtOk|=GP;@ zQftuY+%fz>u9$TTh@=%|HKw{53*w_@q0+f>PleUy*m>Oi0fEoQQ@o~=AmE=LuTnUuLv)n7!0 zR>ks`q}3(Cf;vc1Zy0`@r%)f#U9n;Sv}&p8Gp4D?4B|^-rsX09EgWn@0XTQ%<8lWL zw1uI1tr0^27V|LHEZS%=s##vnEEIfNOfivYND;`1Jp|Hzu+mZc9-ts+YhGWP&1%G4 zmOX=pfMRAhLu?J1O{$hYN=t}1#eB#Qz`_lKQ+ADPMr9f^*gkG2%e{B6P6X4(7v}$u zCo~sP1da7T9yhfyvS%|5MiK@Sb=qg)xm!299%ukkphiuATXMs*ObyaH&@Aatia7yl zjh0+CQ@h9!jbXErFnCzY`%0eHE4~!?;SxxYgyqpvhRPKNw41DqsM;Cx6_C` zw6R9ef?|+)7@~D+lEeMUu;1i|a5NdiEegXmB5&L6er+yWeJKeS!_hp_WHygsP!$2# zbtKTy!s`nk^WCb#1>x@haNOYgpWed#s3M-M*t8OsX9trFu~7y{Qqc7KJm=;%U=aXe(Jure);0k z?o-zX|9BS=$Nt6FFYNwLc;EWk&EFv1`^Dw2c>N33|L{)mSjMY&L8;oa&i%lpr(CJ7 z@7xr${a|B4-Zr$!rTonG`PYJL@Gm_058T=wTb(K&yyBFvp8SLDYfidz z{|#H$Y+d}()2}#f>rDCO2Yw4W?|(E~`oL3nuQ>V0CHwyHH*51XyMM90d1-6twY&Eo zrf=K&-;bcRFTViP6*K?u?iUViUfM(E^_`yuxb%x(2QKU0`&nV{*{|OPHO-s%wdcNJ z_X%5vglB#9Vd6E=kH1^n`{EmSpR{#o^THk;qV_Q`#3gUqedV@uQRBS5Prhk)XKQ=& z*7m;i<_*Ms7;4}R&bhel~gW~?Cf zMNUfb`En5>U4)iIMWHKGYpxmPiMeX9Dp2FLY<$$6E6K3p?7jO>PlO8pH$nv`y zp)@nc9Ak6PR#vMFB}R)XREH-@de)akw&PgE(x?;@Jy@Vc3ld2ZMF?h*ERT-lvOC0D zgxKi-rO`@XMu!keV42Zyl3o=pt5(~YfC9Ejx6$*kfF&jaJ*;)B^#$8sxiVv$sWJ>1 zni_zP{-ECw(jg-E72R^0d0u<-8`bj`d9Cm2UgIZ@4Or?bDI@9V*S&q{Q(~*k<25!hE!(d^ADbO&) zibb7a;eK1qM}pv+wQ85l+yzw|XMpAPsHcMy)})fe^U@T_N|k1cfON|$SV0Pp$`&iM z8`@wTtALJaG>T%@ zr05J6Wfhx+?T%Jc+##6p)%`1TMl#Zln++Ovx zIyMz*sGQLO+3FM#mIb_#{a&a}RtprON-8zibW|Y~p2aOMDz#W2bRfq)++o=j*X5{8 z96P+qR0LXPC!`(Kpp3v4{Tin%SAM?Bid)c~Xs zT?AwRI*aj?a!d22!-(Ce(VKWcRJ;@F#t`R4GMo_3q7yY%P}^n2rnHYI4aX&*+i_UQc%r04Z6DI z7S+I$WK>vMN;ggVVF09Q2K!m*x3ZC$0bzaDUB4GU>5>kwgNbBDuCp_qad8y z1f7Pn+TOc9zx$&Tx$FP@3C+NzX|1uOs&>&Dn1F|hTN)NZQk>y9p+20a)!Lv^m1Mw~ zxS|p})-nckXc%=fS$2wTAim|+in`tvhEM=Bd?zSIv7)Z|F$r2S;w2$g6K5)6ypX!> zKmek_5<3+_gdU8uaV=~xM^TISax#>oyuy!HGK@I&VXs$S_;eoWW2`o10?sjMsSo&M zTsE68sP;4kHM!%8!0Ywq#9wkLW|YPeYbVo%#&&wDN`g${$jt{>SrWMkKnwW^&h|xr zL^|z!)v2XsvD(R&pu>q%l2xtjRQZgbE2=Y(JZ%(q%Y>$dCK5tE60;~sy8C5fNT-HI z1=6%*a~3X2(YOIfUS@c(8Y{GrR6B$b)x^;Dw8$iN1!$J+e&XQv#ht$$@BP`=c86Qr z87F*aiOcKN{OArOtezAQ;G$xS*xO0=u_aPq1RW0d+*1 zszadu2<~?$5(Rh6oVRJYU#aWhe7C3;XCqu}8BKY>-5;$~7Rg$q$Mxs2&ca!IBxzWYDC@(f-WzlOT+AMDaWl zPwJwJYULQ`>$OHJ$69T`_Z_Bs(8T7H8l!2yj~2NVC_Pt}gxz-Lgh#SfbSw-o11d!& zkq}z_uGl7!&In(466Ev+lMNTBL-!_qKgU){$?2tyI%JC$_!?(b)NMF>@A|=sUEp}e z>Ax?m0rDS)TPosWf7TUXAdg+1)D^SHl>zT!-leq8s=jOvS-DwX)}p+LuLd)wq*>D% zj5CeOz+DD?w;Zl$Zr~5AYBuSTK2TsS>9~w((J-|0p{90V0~0}~Rkz)W8bpkgKyhd* zb3iA5>8R73R3=`xJ8S}7VNk&e3PWRW404*%kPjF~Gys)O4Uh>aT_Pq{d1($LCS9_) zN(a6wv#Vg(AY-O(P|7loUht|s>mMhJ@CK@Am#tYe70n;9BM^T3n?ZYw$dh@5^|>W z98+sBgevHI|V3+_JiAXwWgBl_aJeQnAgUPu9mZAdb~2S*#Vxf)UnAE-@KJ zHMpGPraGFnCMg*Wi9uf;L1A6&u}(R3;Jkv(meX{RGMvxOh!A3{m3G=^t)5Qr{mIXF ze|#cJ|IZIN7G6E5aBTy0SC64c>##_LAmb{VDn!YsHk(QrfYR!yN>c4g!<8wvJD*uL zEO{NXO7I*IKlA8JAzRvt)&_t!1!;;cD_?5$Au~_f`<5pDa~*Sqgo@VhuCcA>5Jt~zZUf4A~%`Kt%;TQM85Bc1GcAieH$4gOyIPPxr8sLpa8Jc@!4Qm0j+zp zA_lF9rAuYg7@K8Hr?$%SJmjjTEwn}0olvDoLr|4sQV;#5k(gnlrtzpH;dW!Jsg0fy qj$0)bbr(1yW<^$0z#`8fwQR|VE3_zFaN7CD{<~`P=L=7}>i+}r%m2Ut diff --git a/util/registry/gzipstream.py b/util/registry/gzipstream.py index 0f9ce1e6b..3a3f28542 100644 --- a/util/registry/gzipstream.py +++ b/util/registry/gzipstream.py @@ -16,6 +16,7 @@ class SizeInfo(object): def __init__(self): self.uncompressed_size = 0 self.compressed_size = 0 + self.is_valid = True def calculate_size_handler(): """ Returns an object and a SocketReader handler. The handler will gunzip the data it receives, @@ -23,17 +24,26 @@ def calculate_size_handler(): """ size_info = SizeInfo() - decompressor = zlib.decompressobj(ZLIB_GZIP_WINDOW) def fn(buf): + if not size_info.is_valid: + return + # Note: We set a maximum CHUNK_SIZE to prevent the decompress from taking too much # memory. As a result, we have to loop until the unconsumed tail is empty. current_data = buf size_info.compressed_size += len(current_data) while len(current_data) > 0: - size_info.uncompressed_size += len(decompressor.decompress(current_data, CHUNK_SIZE)) + try: + size_info.uncompressed_size += len(decompressor.decompress(current_data, CHUNK_SIZE)) + except: + # The gzip stream is not valid for some reason. + size_info.uncompressed_size = None + size_info.is_valid = False + return + current_data = decompressor.unconsumed_tail # Make sure we allow the scheduler to do other work if we get stuck in this tight loop. From 9698d6f6a0788e940d15fabf521ac2466fc3d60e Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Mon, 14 Dec 2015 15:26:15 -0500 Subject: [PATCH 2/2] Add created column to blob upload Fixes first half of #1054 --- data/database.py | 1 + ...2f_add_created_field_to_the_blobupload_.py | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 data/migrations/versions/88e0f440a2f_add_created_field_to_the_blobupload_.py diff --git a/data/database.py b/data/database.py index b4d7ba986..eb7cf8ed3 100644 --- a/data/database.py +++ b/data/database.py @@ -786,6 +786,7 @@ class BlobUpload(BaseModel): storage_metadata = JSONField(null=True, default={}) chunk_count = IntegerField(default=0) uncompressed_byte_count = IntegerField(null=True) + created = DateTimeField(default=datetime.now, index=True) class Meta: database = db diff --git a/data/migrations/versions/88e0f440a2f_add_created_field_to_the_blobupload_.py b/data/migrations/versions/88e0f440a2f_add_created_field_to_the_blobupload_.py new file mode 100644 index 000000000..ab9c63585 --- /dev/null +++ b/data/migrations/versions/88e0f440a2f_add_created_field_to_the_blobupload_.py @@ -0,0 +1,27 @@ +"""Add created field to the BlobUpload table + +Revision ID: 88e0f440a2f +Revises: 403d02fea323 +Create Date: 2015-12-14 15:19:11.825279 + +""" + +# revision identifiers, used by Alembic. +revision = '88e0f440a2f' +down_revision = '403d02fea323' + +from alembic import op +import sqlalchemy as sa + +def upgrade(tables): + ### commands auto generated by Alembic - please adjust! ### + op.add_column('blobupload', sa.Column('created', sa.DateTime(), nullable=False, server_default=sa.text('now()'))) + op.create_index('blobupload_created', 'blobupload', ['created'], unique=False) + ### end Alembic commands ### + + +def downgrade(tables): + ### commands auto generated by Alembic - please adjust! ### + op.drop_index('blobupload_created', table_name='blobupload') + op.drop_column('blobupload', 'created') + ### end Alembic commands ###