My work on POE::Filter::SSL is relevant here. I needed a way to pass OOB data back to the readwrite wheel during the SSL negotiation. The method LotR and I came up works great. I pass an array ref to get_one (lets call it $oob), and any time a filter has OOB data, it blesses it into a namespace, and pushes it onto @$oob. For Filter::SSL, I used the OOB namespace 'POE::OOB::put' for data that needs to be directly sent out the wheel's driver. Filter::Stackable and Wheel::ReadWrite needs to be aware of this OOB data, so I've patched them too. We can use this method to add 'POE::OOB::error' and handle it by sending an event.
Relevant files: http://svn.xantus.org/sprocket/trunk/Sprocket/lib/POE/Filter/Stackable.pm http://svn.xantus.org/sprocket/trunk/Sprocket/lib/POE/Filter/SSL.pm http://svn.xantus.org/sprocket/trunk/Sprocket/lib/POE/Wheel/ReadWrite.pm Cheers, David On 8/14/07, Martijn van Beers <[EMAIL PROTECTED]> wrote: > > There was a discussion about this on #poe, which I thought I'd share: > > <+nperez> an isa check every single time something goes through the > filter just seems like overkill... > <+LotR> compared to the work that Filter::XML does? > <+nperez> yes, because it will add up. hold on, writing a benchmark > script > <+LotR> I'm sure it will prove to be nothing compared to parsing an xml > subtree > <+nperez> but what about other filters? Stream? Line? > <+LotR> stream doesn't ever need to generate any errors. nor does line > <+LotR> if you just use those, you can forget about error checking > altogether > * LotR will send the discussion to the list when we're done > <+nopaste> "nperez" at 12.5.72.252 pasted "undef vs isa" (30 lines) at > http://nopaste.snit.ch:8001/10886 > <+nperez> take a look > <+nperez> that's a huge difference > <+LotR> but an isa() still is pretty damn fast. > <+nperez> besides, it is less of a rewrite checking for undef. > consider: > you have to now check ref and then isa on every return value > from the filter > <+nperez> what if it isn't a ref that gets returned? > <+nperez> and isa only worked on blessed objects > <+LotR> you're still going to have to check for undef too > <+nperez> works > <+nperez> exactly, so why do the other checks and you can just do the > one > <+LotR> and it is going to be more of a change if you then have to ask > the filter for extra data > <+nperez> not really, implementing an get_error() isn't as profound of > a > change > <+nperez> it is OOB > <+nperez> without you still have checking for undef for errors in a lot > of modules anyhow > <+nperez> if they want to know more info, they then call get_error() > <+nperez> otherwise, they might not care > <+LotR> that "whout you still.." sentence doesn't parse for me > <+LotR> without. duh > <+nperez> sorry, without get_error(), you still have checking for undef > <+LotR> still don't get it. how does checking for undef for errors in > 'a > lot of modules' have anything to do with filters? > <+nperez> because right now, the de facto indicator for error is > returning undef > <+LotR> no it isn't > <+LotR> in Filter::HTTPD, an HTTP::Response is returned > <+LotR> in Filter::XML, you get a callback > <+LotR> in Filter::SAXBuilder, you get an Error::Simple object > <+LotR> and I don't know any other filters that return errors right now > <+nperez> okay, thinking a little more general, perl built-ins return > undef on errors and set $! > <+nperez> following that convention can't be /that/ bad > <+LotR> right, but is it guaranteed that you always get the chance to > check the error before an extra error is created (meaning > filters > have to store more than one, and the $! analogy breaks down) > <@Leolo> test it against Scalar::Util::blessed > <+nperez> Leolo: that is a possibility too > <+LotR> Leolo: hmm? > <@Leolo> also, the filter could return undef(), then you ask the filter > ->is_error() or ->error_str() or whatever > <@Leolo> call this wrapped in POE::Filter::Fallible > <+LotR> I just don't particulary like the extra API > <@Leolo> s/call/all/ > <+nperez> well, it's incomplete as is. Error states are simply > unaccounted for. Most of the modules that I have been looking > through in the past 10 minutes make all sorts of assumptions > on > input > <+nperez> if there is an error, it will just die > <+nperez> or return [ ] > <+nperez> in which case, how do you know there was an error? > <+LotR> you don't. But I like the simplicity of array ref in; array ref > out > <@Leolo> they probably assume they are talking to another > POE::Filter::Foo. in which case there should be no error > <@Leolo> lotr : true > <+nperez> the simplicity fails. If the filter gets into an inconsistent > state due to bad input, but never tells the outside world > what > is going on, that's just poor > <+nperez> returning [] is just too overloaded > <+LotR> plus, if you stack the filters, can you make sure you will just > have had one error if you get out of the filter? > <+LotR> nperez: I'm not saying returning [] on error is a good idea, it > isn't. > <+nperez> there probably needs to be a way to aggregate/bubble errors > up > from stacked filters > <+LotR> I'm saying returning an error object in the array ref out keeps > the simplicity > < imMute> maybe it should return some kind of POE::Filter::Error object > on error > < imMute> and then the wheel thats processing it can deal with the error > < imMute> or the next filter in stackable can just pass it on > <+nperez> LotR: but that adds checking in-band which is a performance > killer > <+nperez> maybe no killer, but detrimental to performance i should say > <+nperez> maybe no killer, but detrimental to performance i should say > < imMute> its better than just suddenly not getting any records from a > filter and not knowing why > <+LotR> nperez: right. so we disagree on how bad such a performance hit > that is > <+nperez> imMute: getting an undef should be a strong idicator of error > in which case you check the error property on the filter > <+nperez> agreed on that point LotR > < imMute> nperez: are we going to standardize the name of that call, > and > what it should return? > * LotR wonders if there are no filters that return undef for reasons > other than error > <+nperez> imMute: that's what we would like to happen, yes > < imMute> personally I think we should standardize the arrayref in, > arrayref out first, because I know there are filters that > dont > follow that > <+nperez> it is standard, if they subclass POE::Filter > <+nperez> and stay "true" to form > < imMute> some dont though > <+nperez> then we should file bugs on rt for them :) > < imMute> i know few of BinGOs' filters subclass POE::Filter > < imMute> and he complained loudly when i added an isa() check to > Stackable > <@BinGOs> all of them do. > <+nperez> I did too > <+nperez> I had to make changes to make the filter stabled > <+nperez> stackable > <+purl> well, stackable is newer than PFX? > <@BinGOs> this is why I was screaming blue fucking murder earlier. > < imMute> maybe its changed since i last messed with filters, its been > a > few months > <+nperez> It is implicit that filters take aref in and spit aref out > <+LotR> explicit in the docs actually > <+nperez> right > <@BinGOs> My take is POE::Filter shouldn't shit out anything they > shouldn't > <+LotR> BinGOs: meaning? > <+purl> somebody said meaning was in the individual, whether a > definition > <@BinGOs> otherwise a world of fucking hurt is going to happen. > <@BinGOs> meaning, don't return anything on a fucking error. > <+LotR> why not? > <@BinGOs> because I will hunt you down like a dog > <+nperez> BinGOs: if there is an error, I'd like to know about it > <@BinGOs> then 'warn' > <+nperez> returning [] is not tenable > <+nperez> the state of the filter may need to be reset > <+nperez> I can't capture warns and adjust accordingly > <@BinGOs> if you are in a POE::Filter::Stackable then everyone may not > be > following the rules. > <+nperez> which is why we are wanting to update the POE::Filter API and > introduce a standard way to report errors > <+LotR> BinGOs: there'll be new rules :) > <+nperez> heh > <@BinGOs> I am not the bad guy here >:) > <+nperez> BinGOs: if you want patches to your modules after the change, > I'll help, promise. Because you have a shit load and I don't > blame you for beign resistant to change ;) > <+LotR> BinGOs: oh no? so what happens if Filter::IRC gets a line that > doesn't parse? > <@BinGOs> it warns > <+LotR> which isn't very nice > <@BinGOs> and b). I am not using POE::Filter::IRC these days. > <+LotR> Filter::IRCD then > <@BinGOs> and c). yes, POE::Filter::IRCD warns > <+nperez> warnings disappear into the aether and don't control > autocorrecting procedures > <+LotR> BinGOs: which you can't handle very nicely. > <@BinGOs> Okay, you have a POE::Filter::Stackable > < imMute> what does PCI use for the client then? > <@BinGOs> the first filter produces an error, what happens next ? > <@BinGOs> ( you have four filters in the chain ) > <+nperez> stackable checks the error property, sets its own error > property and returns undef > <+nperez> skipping the other three > <@BinGOs> do you produce an event at the end ? > <+LotR> or > <+LotR> it sticks an error object in the listref out. (and probably > skips > the other three filters) > < imMute> BinGOs: no > <+LotR> BinGOs: filters don't know anything about POE events. I want to > keep it that way > <@BinGOs> PCI uses Filter::IRCD and POE::Filter::IRC::Compat in a > stackable. > < imMute> BinGOs: stackable doesnt produce output unless the last > filter > returns something > <@BinGOs> SO what happens to your error then ? > <+nperez> returning undef should be an indicator to check the error > property on the filter > <+LotR> BinGOs: read the scrollback? we've been over this and haven't > come to an agreement. nperez and I have different views on how > to > do it > <+LotR> but we agree there should be some error reporting in filters > <@BinGOs> Hell, I'll work around whatever you come up with anyways >:) > <+nperez> haha > <@BinGOs> difficult audience. > <+nperez> Ultimately is up to dngor about an API change > <+nperez> we are wanting to do something rather fundamental > <+nperez> especially with a 1.0 approaching > <@BinGOs> this is why I am stomping my little feet. > <+nperez> If it's broken, it's broken. Bitching how much the fix hurts > isn't going to make it go away :) > <+LotR> another reason not to do an ->get_error() method. no need to > change old filters who don't care about error reporting > <+nperez> if they don't care about error reporting, they aren't > checking > their inputs enough ;) > <@BinGOs> I am a team player and have a 'Can do attitude' > <@BinGOs> the whole POE::Filter sub-class thing was no problem to me. > <+nperez> BinGOs: we aren't interviewing you here. You are more than > welcome to be the devil's advocate and general asshole. It > helps :) > <@BinGOs> Yes, I am playing devil's advocate > <@BinGOs> and yes, I am an asshole. > <+nperez> You represent a large swath of incumbent modules. Your > opinion > counts > <@BinGOs> I always have an eye on backwards compatibility. > <@perigrin> to watch it slip away > <+nperez> That is certainly something to consider. LotR's idea is > probably better for backwards compat > <@Leolo> backwards compatible with "do nothing useful" is easy > > > -- David Davis Software Engineer