[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Omaha.pm] Project doc overkill




-lol-

Is it a good thing or a bad thing when my lines of documentation to lines of code ratio exceeds 95%?

Wrote this in June this year and yes, just 5 months later I definately needed all of that documentation to understand what the heck I was thinking...

:)

j




=head2 next_obj

Return whichever outbound filehandle I should write to next and advance my memorized
{last_obj_used} value.

  my $obj = $buffers->next_obj;

See source code for a warning about write()'ing to an inbound connection.

B<Discussion: 'round robin' vs. 'first free' queuing> (jhannah 2006-06-29)

This method's job is to return the next obj/filehandle/child we should write a payload to. The original implementation of this method was a simple round robin system. Under round robin queuing if you have 6 children, then each payload is sent to each child in order.
Once a payload is sent to the last child, we start over at the first child.
And so on. Pretty simple.

'first free' queuing is different. Instead of just
blindly writing to the next child, we attempt to find the next child
which is not busy. Which ones are busy? Well, under first free queuing it is assumed that each child can and should only handle one payload at a time. Therefore, when a write is
made to a child that child is flagged as "busy" here in the Buffers class. When the
child is done processing, it should return its response. Receiving a response from
a child triggers that child as no longer busy, so its status is cleared and it is once
again free to receive a payload.

So when a write() call is made we go fishing for the next available child to write
to. This process starts as simply as the round robin system: We know which child we
wrote to last, so we'll look to see if the next one is free. If it is, that's the
one we'll write to. If it's busy, we'll increment our counter and try again, wrapping
around our child list if we hit the end. If we make a full loop and it turns out that all of our children are busy, then we'll have to give up for now, saving this payload
for later transmission. Hopefully one of our children will
be free the next time we go searching.

Note that 'first free' queuing will probably not make you happy if your children
don't respond to requests. No response means Control::Multiplex will forever think
your child is still working on the first payload we sent it, and will never send
a second payload to that child. Further, you're likely to be dissatisfied if your children
enjoy receiving more than one payload at a time. Under 'round robin' queuing children are sent
work as fast as possible, but under 'first free' queuing any given child only ever has one
payload to process at a time.

=cut

sub next_obj {
   my ($self, $label) = @_;
   my $logger = $self->get_logger;
   if (defined $self->{outbound}->{$label}) {
      confess "ACK!" if ($label eq "INBOUND");
      if ($self->{queuing} eq "first free") {
         $logger->debug("Buffers.pm next_obj() has decided to use next_obj_first_free()");
         return $self->next_obj_first_free($label);
      } else {
         $logger->debug("Buffers.pm next_obj() has decided to use next_obj_round_robin()");
         return $self->next_obj_round_robin($label);
      }
   } elsif (defined $self->{inbound}->{$label}) {
      # We don't know about that outbound label, but this is an inbound label and
      # apparently we want to write back out to it. (Like an inbound TCP.)
      # ...
      # We probably can't write back to the first (0th) element in this array because that's
      # probably the listening socket. Bummer. Let's write back to the second one in the array.
      # Note this is NOT safe if there are 5 connections connected and you
      # want to specifically write back to the one whose input just caused the read() --
      # I'll probably have to implement that logic some day, but I don't need it for
      # any project current on the books. Currently we write() all our output back to
      # a single inbound connection, or a single outbound TCP connection for all inbound
      # work... -jhannah 11/8/04
      return $self->{inbound}->{$label}->{objs}->[1];
   } else {
      return undef;
   }
}