<div dir="ltr">Thank you, the new VM did fix it.<div>-cbc</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Aug 28, 2014 at 8:17 PM, David T. Lewis <span dir="ltr"><<a href="mailto:lewis@mail.msen.com" target="_blank">lewis@mail.msen.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="">On Thu, Aug 28, 2014 at 03:17:24PM -0700, Chris Cunningham wrote:<br>
> Hi.<br>
> What is the status of this bug? Have you tried this fix?<br>
<br>
</div>Good question. There were a number of interdependent issues, but the short<br>
answer is that you probably have an up to date trunk image, and a not so<br>
up to date VM.<br>
<br>
There was a legitimate fix to an obscure bug, and that fix that was introduced<br>
into trunk (Collections-eem.567). This fix ended up requiring VM changes to<br>
accomodate the fix. If you are using a VM that was not built recently, then<br>
it may not have the required support.<br>
<br>
The VM support was added in the July 2014 time frame to VMMaker.oscog-eem.826<br>
(for Cog) and VMMaker-dtl.348 (for interpreter VM). If your image is updated<br>
with Collections-eem.567 or later, then you will need a recently compiled VM<br>
in order to avoid the bug.<br>
<br>
Dave<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
><br>
> I have recently been running into a related symptom - I can't write out big<br>
> PNG files (it tries to write beyond the buffer as well). I suspect it is<br>
> the same issue.<br>
><br>
> Here is a sample script that will produce the same error. Not all PNG<br>
> generated file have it - but a number that I'm trying to produce manage to<br>
> run into this bug.<br>
><br>
> | canvas stream dx |<br>
> canvas := FormCanvas extent: ((31 * 40)@(101 * 40)) depth: 32.<br>
> canvas<br>
> fillRectangle: ((0@0) corner: canvas extent) color: Color white;<br>
> frameRectangle: ((0@0) corner: canvas extent) color: Color black.<br>
> dx := 38.<br>
> 1 to: 100 do: [:y|<br>
> 1 to: 30 do: [:x|<br>
> canvas fillRectangle: (((x * dx) @ (y * dx)) corner: (((x * dx) + 2) @ ((y<br>
> * dx) + 2))) color: Color green.<br>
> ].<br>
> ].<br>
> stream := ByteArray new writeStream.<br>
> PNGReadWriter putForm: canvas form onStream: stream.<br>
><br>
> Thanks.<br>
> -cbc<br>
><br>
><br>
> On Fri, Jul 18, 2014 at 12:46 PM, Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>><br>
> wrote:<br>
><br>
> ><br>
> ><br>
> ><br>
> > On Fri, Jul 18, 2014 at 12:38 PM, Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>><br>
> > wrote:<br>
> ><br>
> >> Stupid me. It's got to be the DeflateStream, and its subclasses<br>
> >> ZipWriteStream, GZipWriteStream and ZLibWriteStream. So my change screws<br>
> >> all uses of these in plugins. So what to do about fixing this? I would<br>
> >> like to have a go at fixing the plugins. But cheaper might be to fix<br>
> >> WriteStream with some property hack, storing the initialPosition somewhere<br>
> >> else (a class side weak dictionary of stream -> initialPosition ?? (yuck)).<br>
> >><br>
> >><br>
> >> On Fri, Jul 18, 2014 at 12:31 PM, Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>><br>
> >> wrote:<br>
> >><br>
> >>><br>
> >>><br>
> >>><br>
> >>> On Thu, Jul 17, 2014 at 4:02 PM, David T. Lewis <<a href="mailto:lewis@mail.msen.com">lewis@mail.msen.com</a>><br>
> >>> wrote:<br>
> >>><br>
> >>>> On Fri, Jul 18, 2014 at 12:24:29AM +0200, Nicolas Cellier wrote:<br>
> >>>> > 2014-07-13 16:22 GMT+02:00 David T. Lewis <<a href="mailto:lewis@mail.msen.com">lewis@mail.msen.com</a>>:<br>
> >>>> ><br>
> >>>> > > On Sun, Jul 13, 2014 at 09:55:41AM -0400, David T. Lewis wrote:<br>
> >>>> > > > On Sun, Jul 06, 2014 at 12:47:25PM -0400, David T. Lewis wrote:<br>
> >>>> > > > > On Sun, Jul 06, 2014 at 12:23:11PM -0400, David T. Lewis wrote:<br>
> >>>> > > > > > On Sun, Jul 06, 2014 at 10:34:15AM +0200, Nicolas Cellier<br>
> >>>> wrote:<br>
> >>>> > > > > > > 2014-07-04 0:47 GMT+02:00 Nicolas Cellier <<br>
> >>>> > > > > > > <a href="mailto:nicolas.cellier.aka.nice@gmail.com">nicolas.cellier.aka.nice@gmail.com</a>>:<br>
> >>>> > > > > > ><br>
> >>>> > > > > > > ><br>
> >>>> > > > > > > ><br>
> >>>> > > > > > > ><br>
> >>>> > > > > > > > 2014-07-04 0:09 GMT+02:00 Eliot Miranda <<br>
> >>>> <a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a><br>
> >>>> > > >:<br>
> >>>> > > > > > > ><br>
> >>>> > > > > > > ><br>
> >>>> > > > > > > >><br>
> >>>> > > > > > > >><br>
> >>>> > > > > > > >> On Thu, Jul 3, 2014 at 12:33 PM, Nicolas Cellier <<br>
> >>>> > > > > > > >> <a href="mailto:nicolas.cellier.aka.nice@gmail.com">nicolas.cellier.aka.nice@gmail.com</a>> wrote:<br>
> >>>> > > > > > > >><br>
> >>>> > > > > > > >>> The bug is repeatable, i simply have to execute this<br>
> >>>> snippet<br>
> >>>> > > with my<br>
> >>>> > > > > > > >>> test file:<br>
> >>>> > > > > > > >>><br>
> >>>> > > > > > > >>> (FileStream fileNamed: 'snapshot.bin') binary<br>
> >>>> > > contentsOfEntireFile<br>
> >>>> > > > > > > >>> asString zipped.<br>
> >>>> > > > > > > >>><br>
> >>>> > > > > > > >>> The file is too big for an attachment here - 7.3 Mbytes<br>
> >>>> - or<br>
> >>>> > > 1.7 Mbytes<br>
> >>>> > > > > > > >>> gzipped by external tool.<br>
> >>>> > > > > > > >>> If someone can suggest an upload site, or want it by<br>
> >>>> mail,<br>
> >>>> > > just ask.<br>
> >>>> > > > > > > >>><br>
> >>>> > > > > > > >><br>
> >>>> > > > > > > >> You're welcome to put it on <a href="http://ftp.mirandanamda.org" target="_blank">ftp.mirandanamda.org</a>,<br>
> >>>> cogftpuser,<br>
> >>>> > > pw cogging<br>
> >>>> > > > > > > >> with 0's & 1's.<br>
> >>>> > > > > > > >><br>
> >>>> > > > > > > >><br>
> >>>> > > > > > > > done, pollution of your site engaged...<br>
> >>>> > > > > > > > Thanks Eliot!<br>
> >>>> > > > > > > ><br>
> >>>> > > > > > > ><br>
> >>>> > > > > > > >><br>
> >>>> > > > > > > I inquired a bit more about this bug.<br>
> >>>> > > > > > > An important clue is that it does not happen in Pharo3.0!<br>
> >>>> > > > > > ><br>
> >>>> > > > > > > But Pharo3.0 did not fundamentally change compression<br>
> >>>> > > > > > > (except some FileSystem related changes, separation of CRC<br>
> >>>> stuff<br>
> >>>> > > in another<br>
> >>>> > > > > > > package, some other cosmetic changes like replacing some<br>
> >>>> self<br>
> >>>> > > assert: ...<br>
> >>>> > > > > > > by [...] assert and a potential bug in<br>
> >>>> > > > > > > DeflateStream>>nextPutAll:startingAt: introduced by<br>
> >>>> CamilleTeruel).<br>
> >>>> > > > > > > Squeak behavior is presumably not due to a Compression<br>
> >>>> change.<br>
> >>>> > > > > > ><br>
> >>>> > > > > > > Neither is it a VM problem, the bugs still shows up when<br>
> >>>> running<br>
> >>>> > > the Squeak<br>
> >>>> > > > > > > image with Pharo VM.<br>
> >>>> > > > > > ><br>
> >>>> > > > > ><br>
> >>>> > > > > > Yes, it is definite a problem in the Squeak trunk image.<br>
> >>>> > > > > ><br>
> >>>> > > > > ><br>
> >>>> > > > > > > So the difference lies somewhere else: in our beloved<br>
> >>>> Stream.<br>
> >>>> > > > > > > I remembered a recent change of Eliot related to handling of<br>
> >>>> > > Stream created<br>
> >>>> > > > > > > with on:from:to: (Collections-eem.567).<br>
> >>>> > > > > > > Reverting those changes just make the snippet pass!<br>
> >>>> > > > > > ><br>
> >>>> > > > > > > Ah ah! At the time, i found the change of Eliot quite<br>
> >>>> minimal and<br>
> >>>> > > nice.<br>
> >>>> > > > > > > But I wish I had time to analyze this small innocent change<br>
> >>>> deeper.<br>
> >>>> > > > > > > Indeed, I remembered I previously broke my teeth on this<br>
> >>>> one 2<br>
> >>>> > > years or so<br>
> >>>> > > > > > > ago, and preferred to adopt another strategy: avoid using<br>
> >>>> > > on:from:to: and<br>
> >>>> > > > > > > ReadWriteStream as much as possible.<br>
> >>>> > > > > > > Why? because when analyzing the usage of inst.var. in Stream<br>
> >>>> > > hierarchy, it<br>
> >>>> > > > > > > gave me headaches, some subclass are just ignoring<br>
> >>>> superclass<br>
> >>>> > > variables, or<br>
> >>>> > > > > > > worse are bending the semantics of superclass variables.<br>
> >>>> > > > > > > I came to the conclusion that I could not decently master a<br>
> >>>> change<br>
> >>>> > > of<br>
> >>>> > > > > > > on:from:to:<br>
> >>>> > > > > ><br>
> >>>> > > > > > I can not confirm this. I have an image in which I can<br>
> >>>> reliably<br>
> >>>> > > reproduce the<br>
> >>>> > > > > > failure in writing the MCZ to a file. I tried reverting the<br>
> >>>> methods<br>
> >>>> > > that were<br>
> >>>> > > > > > introduced in Collections-eem.567 and I am still getting the<br>
> >>>> same<br>
> >>>> > > failure.<br>
> >>>> > > > > ><br>
> >>>> > > > > > Dave<br>
> >>>> > > > ><br>
> >>>> > > > > Oops, I spoke too soon. Indeed the problem appears as of<br>
> >>>> > > Collections-eem.567,<br>
> >>>> > > > > and does not appear in Collections-nice.566.<br>
> >>>> > > > ><br>
> >>>> > > > > So I am confirming Nicolas' observations ... now to find the<br>
> >>>> bug :)<br>
> >>>> > > > ><br>
> >>>> > > > > Dave<br>
> >>>> > > > ><br>
> >>>> > > ><br>
> >>>> > > > This seems to be a rather tricky bug, and I don't think any of us<br>
> >>>> knows<br>
> >>>> > > the<br>
> >>>> > > > cause right now. In case anyone else wants to have a look at it,<br>
> >>>> here is<br>
> >>>> > > a<br>
> >>>> > > > recipe for reproducing the bug in a clean 4.5 image:<br>
> >>>> > > ><br>
> >>>> > > > - Start with a clean Squeak 4.5 image in and empty working<br>
> >>>> directory.<br>
> >>>> > > > <a href="ftp://ftp.squeak.org/4.5/Squeak4.5-13680.zip" target="_blank">ftp://ftp.squeak.org/4.5/Squeak4.5-13680.zip</a><br>
> >>>> > > ><br>
> >>>> > > > - Open the image, do not update it.<br>
> >>>> > > ><br>
> >>>> > > > - Open an MC browser and add the <a href="http://source.squeak.org/trunk" target="_blank">http://source.squeak.org/trunk</a><br>
> >>>> > > repository for the Help-Squeak-Project package and Collections<br>
> >>>> package.<br>
> >>>> > > ><br>
> >>>> > > > - Load Help-Squeak-Project-kfr.18 from trunk.<br>
> >>>> > > ><br>
> >>>> > > > - Load Collections-eem.567 from trunk.<br>
> >>>> > > ><br>
> >>>> > > > - Open a browser on class SqueakToolsDebuggerHelp, and delete the<br>
> >>>> class<br>
> >>>> > > side method #showDebuggerMenuForm.<br>
> >>>> > > ><br>
> >>>> > > > - Remove the <a href="http://source.squeak.org/trunk" target="_blank">http://source.squeak.org/trunk</a> repository form the<br>
> >>>> > > Help-Squeak-Project package in the MC browser.<br>
> >>>> > > ><br>
> >>>> > > > - Highlight your package-cache repository and try to save<br>
> >>>> > > Help-Squeak-project to the package-cache repository.<br>
> >>>> > > ><br>
> >>>> > > > - Enter author initials 'dtl'.<br>
> >>>> > > ><br>
> >>>> > > > - For the package comment, enter 'Remove unreferenced method'.<br>
> >>>> > > ><br>
> >>>> > > > - Package save will fail part way through saving the MCZ.<br>
> >>>> > > ><br>
> >>>> > > > - To reproduce the failure in this image, do the following in a<br>
> >>>> > > workspace:<br>
> >>>> > > ><br>
> >>>> > > > mcv := MCVersion allInstances detect: [:e | e name = 'a<br>
> >>>> > > MCVersion(Help-Squeak-Project-dtl.19)'].<br>
> >>>> > > > [f := FileStream fileNamed: 'junk.mcz'.<br>
> >>>> > > > mcv fileOutOn: f]<br>
> >>>> > > > ensure: [f close].<br>
> >>>> > > ><br>
> >>>> > ><br>
> >>>> > > In addition to the above recipe, here are some other observations:<br>
> >>>> > ><br>
> >>>> > > - Reverting from Collections-eem.567 to Collections-nice.566 makes<br>
> >>>> the<br>
> >>>> > > problem go away, but ONLY if the DeflatePlugin is active.<br>
> >>>> > ><br>
> >>>> > > - The failure appears while executing the fallback code for<br>
> >>>> > > #primitiveDeflateBlock<br>
> >>>> > > in ZipWriteStream>>deflateBlock:chainLength:goodMatch:<br>
> >>>> > ><br>
> >>>> > > - If this primitive is deactivate by commenting out the<br>
> >>>> > > <primitive: 'primitiveDeflateBlock' module: 'ZipPlugin'> in<br>
> >>>> > > ZipWriteStream>>deflateBlock:chainLength:goodMatch: then the<br>
> >>>> problem will<br>
> >>>> > > occur regardless of which version of Collections is loaded.<br>
> >>>> > ><br>
> >>>> > > - When Collections-eem.567 is loaded, the primitive will fail on<br>
> >>>> the 22nd<br>
> >>>> > > call to #deflateBlock:chainLength:goodMatch: and a debugger<br>
> >>>> appears<br>
> >>>> > > during<br>
> >>>> > > execution of the fallback code.<br>
> >>>> > ><br>
> >>>> > > - When Collections-nice.566 is loaded, the primitive does not fail<br>
> >>>> on the<br>
> >>>> > > 22nd<br>
> >>>> > > call to #deflateBlock:chainLength:goodMatch:, the fallback code<br>
> >>>> is never<br>
> >>>> > > run,<br>
> >>>> > > and no error appears.<br>
> >>>> > ><br>
> >>>> > > - When Collections-nice.566 is loaded and the primitive is disabled<br>
> >>>> to<br>
> >>>> > > force<br>
> >>>> > > use of the fallback code, the error appears on on the 22nd call to<br>
> >>>> > > #deflateBlock:chainLength:goodMatch: in exactlly the same place<br>
> >>>> as when<br>
> >>>> > > Collections-eem.567 is loaded.<br>
> >>>> > ><br>
> >>>> > > - If I inspect the ZipWriteStream at the failure point (when the<br>
> >>>> debugger<br>
> >>>> > > pops<br>
> >>>> > > up after the problem), I see no obvious difference in the state<br>
> >>>> of the<br>
> >>>> > > stream<br>
> >>>> > > between the Collections-eem.567 case versus the<br>
> >>>> Collections-nice.566 with<br>
> >>>> > > primitive disabled case.<br>
> >>>> > ><br>
> >>>> > > Dave<br>
> >>>> > ><br>
> >>>> > ><br>
> >>>> > Very good mining work!<br>
> >>>> > When I hear Stream, I think fluid...<br>
> >>>> > But these snags make it so viscous, it's like our Stream is going to<br>
> >>>> freeze<br>
> >>>> > soon.<br>
> >>>> > Or is it more than frozen? The vein you're after sounds as hard as<br>
> >>>> diamond,<br>
> >>>> > we gonna need a sharp peak pickaxe.<br>
> >>>> ><br>
> >>>><br>
> >>>> I keep hoping that your stream fixes will somehow make this problem go<br>
> >>>> away, but<br>
> >>>> maybe we are not so lucky.<br>
> >>>><br>
> >>>> Whenever I get more time to play with this, I think I will try to catch<br>
> >>>> it with<br>
> >>>> gdb in the primitive. There is something strange happening that seems<br>
> >>>> to first<br>
> >>>> be detectable in the primitive failure, but only if Eliot's image fix<br>
> >>>> is present.<br>
> >>>><br>
> >>>> This kind of problem is a nice way to spend the morning with a good cup<br>
> >>>> of coffee,<br>
> >>>> as some people do with the NY Times crossword puzzle ;)<br>
> >>>><br>
> >>>> <a href="http://en.wikipedia.org/wiki/The_New_York_Times_crossword_puzzle" target="_blank">http://en.wikipedia.org/wiki/The_New_York_Times_crossword_puzzle</a><br>
> >>>><br>
> >>>> Another "morning coffee" project is to figure out which version of the<br>
> >>>> LargeIntegersPlugin<br>
> >>>> should be used, which of course was the original topic that started<br>
> >>>> this thread.<br>
> >>>><br>
> >>><br>
> >>> So given that the change adds an instance variable to WriteStream could<br>
> >>> that affect some plugin that somehow accesses a stream? What plugin could<br>
> >>> that be? I don't see any obvious inst vars in the DeflatePlugin or<br>
> >>> InflatePlugin. To remind ourselves, the three changes are<br>
> >>><br>
> >>> add inst var to WriteStream:<br>
> >>><br>
> >>> PositionableStream subclass: #WriteStream<br>
> >>> instanceVariableNames: 'writeLimit initialPositionOrNil'<br>
> >>> classVariableNames: ''<br>
> >>> poolDictionaries: ''<br>
> >>> category: 'Collections-Streams'<br>
> >>><br>
> >>> use it in two places:<br>
> >>> contents<br>
> >>> "Answer with a copy of my collection from the start to the current<br>
> >>> position."<br>
> >>><br>
> >>> readLimit := readLimit max: position.<br>
> >>> ^collection copyFrom: (initialPositionOrNil ifNil: [1]) to: position<br>
> >>><br>
> >>> on: aCollection from: firstIndex to: lastIndex<br>
> >>><br>
> >>> | len |<br>
> >>> collection := aCollection.<br>
> >>> readLimit :=<br>
> >>> writeLimit := lastIndex > (len := collection size)<br>
> >>> ifTrue: [len]<br>
> >>> ifFalse: [lastIndex].<br>
> >>> position := firstIndex <= 1<br>
> >>> ifTrue: [0]<br>
> >>> ifFalse: [firstIndex - 1].<br>
> >>> initialPositionOrNil := position + 1<br>
> >>><br>
> >>> What I've just found is that if I revert all three changes to<br>
> >>> WriteStream the bug goes away, but if I only revert the two method changes<br>
> >>> the bug remains. So I think the problem is merely the adding of the inst<br>
> >>> var. This could break some plugin which was expecting inst vars in<br>
> >>> subclasses of WriteStream to be at particular offsets determined by<br>
> >>> WriteStream instSize = 4 now being 5. The question is which plugin(s)?<br>
> >>><br>
> >><br>
> > Doh!<br>
> ><br>
> > DeflatePlugin>>loadDeflateStreamFrom: rcvr<br>
> > | oop |<br>
> > <inline: false><br>
> > ((interpreterProxy isPointers: rcvr)<br>
> > and: [(interpreterProxy slotSizeOf: rcvr) >= 15]) ifFalse:<br>
> > [^false].<br>
> > oop := interpreterProxy fetchPointer: 0 ofObject: rcvr.<br>
> > (interpreterProxy isBytes: oop) ifFalse:<br>
> > [^false].<br>
> > zipCollection := interpreterProxy firstIndexableField: oop.<br>
> > zipCollectionSize := interpreterProxy byteSizeOf: oop.<br>
> ><br>
> > zipPosition := interpreterProxy fetchInteger: 1 ofObject: rcvr.<br>
> > zipReadLimit := interpreterProxy fetchInteger: 2 ofObject: rcvr.<br>
> > "zipWriteLimit := interpreterProxy fetchInteger: 3 ofObject: rcvr."<br>
> ><br>
> > oop := interpreterProxy fetchPointer: 4 ofObject: rcvr.<br>
> > ((interpreterProxy isWords: oop)<br>
> > and: [(interpreterProxy slotSizeOf: oop) = DeflateHashTableSize]) ifFalse:<br>
> > [^false].<br>
> > zipHashHead := interpreterProxy firstIndexableField: oop.<br>
> > oop := interpreterProxy fetchPointer: 5 ofObject: rcvr.<br>
> > ((interpreterProxy isWords: oop)<br>
> > and: [(interpreterProxy slotSizeOf: oop) = DeflateWindowSize]) ifFalse:<br>
> > [^false].<br>
> > zipHashTail := interpreterProxy firstIndexableField: oop.<br>
> > zipHashValue := interpreterProxy fetchInteger: 6 ofObject: rcvr.<br>
> > zipBlockPos := interpreterProxy fetchInteger: 7 ofObject: rcvr.<br>
> > "zipBlockStart := interpreterProxy fetchInteger: 8 ofObject: rcvr."<br>
> > oop := interpreterProxy fetchPointer: 9 ofObject: rcvr.<br>
> > (interpreterProxy isBytes: oop) ifFalse:<br>
> > [^false].<br>
> > zipLiteralSize := interpreterProxy slotSizeOf: oop.<br>
> > zipLiterals := interpreterProxy firstIndexableField: oop.<br>
> ><br>
> > oop := interpreterProxy fetchPointer: 10 ofObject: rcvr.<br>
> > ((interpreterProxy isWords: oop)<br>
> > and: [(interpreterProxy slotSizeOf: oop) >= zipLiteralSize]) ifFalse:<br>
> > [^false].<br>
> > zipDistances := interpreterProxy firstIndexableField: oop.<br>
> ><br>
> > oop := interpreterProxy fetchPointer: 11 ofObject: rcvr.<br>
> > ((interpreterProxy isWords: oop)<br>
> > and: [(interpreterProxy slotSizeOf: oop) = DeflateMaxLiteralCodes])<br>
> > ifFalse:<br>
> > [^false].<br>
> > zipLiteralFreq := interpreterProxy firstIndexableField: oop.<br>
> ><br>
> > oop := interpreterProxy fetchPointer: 12 ofObject: rcvr.<br>
> > ((interpreterProxy isWords: oop)<br>
> > and: [(interpreterProxy slotSizeOf: oop) = DeflateMaxDistanceCodes])<br>
> > ifFalse:<br>
> > [^false].<br>
> > zipDistanceFreq := interpreterProxy firstIndexableField: oop.<br>
> ><br>
> > zipLiteralCount := interpreterProxy fetchInteger: 13 ofObject: rcvr.<br>
> > zipMatchCount := interpreterProxy fetchInteger: 14 ofObject: rcvr.<br>
> ><br>
> > ^interpreterProxy failed not<br>
> ><br>
> > I propose to add a variable that holds the inst size of the superclass of<br>
> > InflateStream, and to use this to correct the offsets. Objections?<br>
> > --<br>
> > best,<br>
> > Eliot<br>
> ><br>
> ><br>
> ><br>
> ><br>
<br>
><br>
<br>
<br>
</div></div></blockquote></div><br></div>