On 06/09/10 07:01, Alex Rousskov wrote:
> On 09/05/2010 05:12 AM, Amos Jeffries wrote:
>> To get around some layering violations between client and server side
>> I've found it easier to continue the rollout of Comm::Connection through
>> client-side that to work up a working hack.
>>
>> The attached patch contains only the src/comm/ API pieces for review so
>> we can ensure they are done properly before much more testing and work
>> is done to make use of them.
>>
>>
>> Comm::Connection - data object. stores the FD, local IP+port, remote
>> IP+port, and comm flags relevant to the socket connection.
>>
>> Comm::ConnAcceptor - was ListenStateData, but now converted to AsyncJob.
>> Takes a connection to listen on and emits active Comm::Connection
>> objects for new client connections.
>>
>> Comm::ConnConnector - take a closed template Comm::Connection and make
>> it an active connection.
>
>
> * s/ConnAcceptor::subscribe(call)/ConnAcceptor::callWhenReady(call)/ or
> similar to emphasize that this is not a subscription mechanism but a
> one-time arrangement. However, the subscription suggestion below makes
> this change unnecessary.
Yes, it will die as soon as I can get the subscribe accepting pre-made
AsyncCall objects.
>
> * I understand what you are doing with ConnAcceptor::subscribe() but I
> think we should generalize subscription-friendly callbacks rather than
> dissecting AsyncCall and trying to reconstruct it in ConnAcceptor (and,
> later, in other classes). It is not going to be much more complex than
> what you do now, but it will be reusable.
>
> Specifically, I suggest adding base/Subscription.h with the following
> API declaration (add refcounted Pointer type, and we can add more bells
> and whistles later):
>
>> /// allows to call back the subscriber many times
>> class Subscription: public RefCountable {
>> public:
>> /// returns a call object to be used for the next call back
>> virtual AsyncCall::Pointer callback() const = 0;
>> };
>
> And the following template to create actual subscription objects from
> Dialers.
>
>> /// implements Subscription API using Call's copy constructor
>> template <class Call>
>> class SubscriptionViaCopyT: public Subscription {
>> public:
>> CallSubscriptionT(const Call::Pointer &aCall): call(aCall) {}
>> virtual AsyncCall::Pointer callback() const { return new Call(call); }
>>
>> private:
>> Call::Pointer call; ///< gets copied to create callback calls
>> };
>
> The above will probably need some polishing to get it to work, but the
> idea should be clear.
>
> You will need to disable copying of AsyncCall objects (via the usual
> undefined and private copy constructor trick -- I should have done that
> long time ago) and then add copy constructors to a couple of AsyncCall
> kids that are already used for subscriptions in your patch.
>
> Your ConnAcceptor will have a single
>
> void ConnAcceptor::subscribe(const Subscription::Pointer &aSub)
>
> method used for all subscriptions. ConnAcceptor will use sub->callback()
> to get a call object for the next notification.
>
Nice. Will do.
>
> * You have several Musts in Comm::ConnAcceptor. If any of them throws,
> the job will quit but Squid will keep running. Same for any indirect
> exceptions the acceptor code might trigger. Are you sure no other job or
> module needs to be notified of the fact that there is no acceptor any
> more? Usually, the initiator cares if its initiatee dies...
Hmm, yes. What should we do if squid has a massive failure on a
listening http_port?
For now I'm wrapping the accept() sequence in a try-catch which calls
fatal() if anything throws. Any better ideas welcome.
The initiators using ConnAcceptor in the current 3.HEAD are
http_port_list, http_port_list and FTP. I can see icp_port/htcp_port
being converted to use it the same way as http_port.
FTP used to d its listening a bit strange with several hacks. I'm in
process of simplifying that.
>
> * We cannnot simply dereference raw pointers to jobs because a job may
> quit and free the job object. Consider using AsyncJob::Pointer instead
> and do check that the code does not dereference potentially invalid
> pointers. Any public job member (data or method) is a suspect.
>
> For example, how does Comm::AcceptLimiter::kick() know that
> deferred.shift() does not point to a dead job? A Vector<> of
> ConnAcceptor pointers is one example but there may be others.
Understood. These two have a rather special relationship.
ConnAcceptor registers itself into AcceptLimiter at which point its
isLimited gets incremented, once for every limiting record.
I've added the missing bits for ConnAcceptor::swanSong to safely and
quickly clear any entries it had remaining in the limiter.
>
> * Please make ConnAcceptor::notify() protected if possible.
Noted. Unfortunately there is a bit of abuse still to be cleaned up.
>
> * Consider adding a "const char *reason" parameter to unsubscribe, for
> debugging.
>
Okay I'll consider.
Amos
-- Please be using Current Stable Squid 2.7.STABLE9 or 3.1.8 Beta testers wanted for 3.2.0.2Received on Mon Sep 06 2010 - 13:09:00 MDT
This archive was generated by hypermail 2.2.0 : Mon Sep 06 2010 - 12:00:04 MDT