DaemonDebug (Chapter14)


 
Network Programming with Perl
By Lincoln  D.  Stein
Slots : 1
Table of Contents
Appendix A.   Additonal Source Code

    Content

IO::LineBufferedSessionData (Chapter 13)

This module works with IO::LineBufferedSet to provide line-oriented reading in a nonblocking multiplexed application. It inherits from IO::SessionData, which is listed in Chapter 13.

 0   package IO::LineBufferedSessionData;   1   # file: IO/LineBufferedSessionData.pm      2   use strict;   3   use Carp;   4   use IO::SessionData;   5   use Errno 'EWOULDBLOCK';   6   use IO::SessionData;   7   use IO::LineBufferedSet;   8   use vars '@ISA','$VERSION';      9   @ISA = 'IO::SessionData';  10   $VERSION = 1.00;    11   use constant BUFSIZE => 3000;    12   # override new() by adding new instance variables  13   sub new {  14     my $pack = shift;  15     my $self = $pack->SUPER::new(@_);  16     @{$self}{qw(read_limit inbuffer linemode index eof error)} = (BUFSIZE,' ', 0,0,0, graphics/ccc.gif 0);  17     return $self;  18   }    19   # line_mode is set to true if the package detects that you are doing  20   # line-oriented input.  You can also set this yourself.  21   sub line_mode        {  22     my $self = shift;  23     return defined $_[0] ? $self->{linemode} = $_[0]  24                          : $self->{linemode};  25   }    26   # Object method: read_limit([$bufsize])  27   # Get or set the limit on the size of the read buffer.  28   # Only affects line-oriented reading.  29   sub read_limit {  30     my $self = shift;  31     return defined $_[0] ? $self->{read_limit} = $_[0]  32                          : $self->{read_limit};  33   }    34   # Add three new methods to tell us when there's buffered data available.  35   sub buffered        { return length shift->{inbuffer} }  36   sub lines_pending   {  37     my $self = shift;  38     return index($self->{inbuffer},$/,$self->{index}) >= 0;  39   }  40   sub has_buffered_data {  41     my $self = shift;  42     return $self->line_mode ? $self->lines_pending : $self->buffered;  43   }    44   # override read() to deal with buffered data  45   sub read {  46     my $self = shift;    47     $self->line_mode(0);            # turn off line mode  48     $self->{index} = 0;             # rezero our internal newline pointer  49     if ($self->buffered) { # buffered data from an earlier getline  50       my $data = substr($self->{inbuffer},0,$_[1]);  51       substr($_[0], $_[2]0, $_[1]) = $data;  52       substr($self->{inbuffer},0,$_[1]) = ";  53       return length $data;  54     }    55     # if we get here, do the inherited read  56     return $self->SUPER::read(@_);  57   }    58   # return the last error  59   sub error { $_[0]->{error} }    60   # $bytes = $reader->getline($data);  61   # returns bytes read on success  62   # returns undef on error  63   # returns 0 on EOF  64   # returns 0E0 if would block  65   sub getline {  66     my $self = shift;  67     croak "usage: getline($scalar)\n" unless @_ == 1;    68     $self->line_mode(1);  # turn on line mode  69     return unless my $handle = $self->handle;    70     undef $_[0];  # empty the caller's scalar    71     # If inbuffer is gone, then we encountered a read error and returned  72     # everything we had on a previous pass.  So return undef.  73     return 0 if $self->{eof};  74     return   if $self->{error};    75     # Look up position of the line end character in the buffer.  76     my $i = index($self->{inbuffer},$/,$self->{index});    77     # If the line end character is not there and the buffer is below the  78     # read length, then fetch more data.    79    if ($i < 0 and $self->buffered < $self->read_limit) {  80      $self->{index} = $self->buffered;  81      my $rc = $self->SUPER::read($self->{inbuffer},BUFSIZE,$self->buffered);    82      unless (defined $rc) {  # we got an error  83        return '0E0' if $! == EWOULDBLOCK;  # wouldblock is OK  84        $_[0] = $self->{buffer};            # return whatever we have left  85        $self->{error} = $!;                # remember what happened  86        return length $_[0];                # and return the size  87      }  88      elsif ($rc == 0) {    # we got EOF  89        $_[0] = $self->{buffer};            # return whatever we have left  90        $self->{eof}++;                     # remember what happened  91        return length $_[0];  92      }    93      # try once again to find the newline  94      $i = index($self->{inbuffer},$/,$self->{index});  95    }    96    # If $i < 0, then newline not found.  If we've already buffered more  97    # than the limit, then return everything up to the limit  98    if ($i < 0) {  99      if ($self->buffered > $self->read_limit) { 100        $i = $self->read_limit-1; 101      } else { 102        # otherwise return "would block" and set the search index to the 103        # end of the buffer so that we don't search it again 104        $self->{index} = $self->buffered; 105        return '0E0'; 106      } 107    } 108    # remove the line from the input buffer and reset the search 109    # index. 110    $_[0] = substr($self->{inbuffer},0,$i+1);  # save the line 111    substr($self->{inbuffer},0,$i+1) = ' ';    # and chop off the rest 112    $self->{index} = 0; 113    return length $_[0]; 114  } 115  1; 116  =head1 NAME 117  IO::LineBufferedSessionData - Handling of nonblocking line-buffered I/O 118  =head1 SYNOPSIS 119   use IO::LineBufferedSet; 120   my $set = IO::LineBufferedSet->new(); 121   $set->add($_) foreach ($handle1,$handle2,$handle3); 122   my $line; 123   while ($set->sessions) { 124     my @ready = $set->wait; 125     for my $h (@ready) { 126       unless (my $bytes = $h->getline($line)) {  # fetch a line 127         $h->close;                               # EOF or an error 128         next; 129       } 130       next unless $bytes > 0;              # skip zero-length line 131       my $result = process_data($line);    # do some processing on the line 132       $line->write($result);               # write result to handle 133     } 134   } 135  =head1 DESCRIPTION 136  This package provides support for sets of nonblocking handles for use 137  in multiplexed applications.  It is used in conjunction with 138  IO::LineBufferedSet, and inherits from IO::SessionData. 139  The IO::LineBufferedSessionData object, hereafter called a "session" 140  for simplicity, supports a small subset of IO::Handle methods, and can 141  be thought of as a smart, nonblocking handle. 142  =head1 CONSTRUCTOR 143  The new() constructor is not normally called by user applications, but 144  by IO::LineBufferedSet. 145  =head1 OBJECT METHODS 146  =over 4 147  =item $bytes = $session->read($scalar, $maxbytes [,$offset]]) 148  The read() method acts like IO::Handle->read(), reading up to 149  C<$maxbytes> bytes into the scalar variable indicated by C<$scalar>. 150  If C<$offset> is provided, the new data will be appended to C<$scalar> 151  at the position indicated. 152  If successful, read() returns the number of bytes read.  On 153  end of file, the method returns numeric 0.  If the read() 154  operation would block, the method returns 0E0 (zero but true), and on 155  other errors returns undef. 156  This is an idiom for handling the possible outcomes: 157    while (1) { 158      my $bytes = $session->read($data,1024); 159      die "I/O error: $!" unless defined $bytes; # error 160      last unless $bytes;                        # eof, leave loop 161      next unless $bytes > 0;                    # would block error 162      process_data($data);                       # otherwise ok 163    } 164  =item $bytes = $session->getline($scalar); 165  This method has the same semantics as read() except that it returns 166  whole lines, observing the current value of C<$/>.  Be very alert for 167  the 0E0 result code (indicating that the operation would block) 168  because these occur whenever a partial line is read. 169  Unlike <> or getline(), the result is placed in C<$scalar>, not 170  returned as the function result. 171  =item $bytes = $session->write($scalar) 172  This method writes the contents of C<$scalar> to the session's 173  internal buffer, from where it is eventually written to the handle. 174  As much of the data as possible is written immediately.  If not all 175  can be written at once, the remainder is written during one or more 176  subsequent calls to wait(). 177  =item $result = $session->close() 178  This method closes the session, and removes itself from the list of 179  sessions monitored by the IO::LineBufferedSet object that owns it. 180  The handle may not actually be closed until later, when 181  pending writes are finished. 182  Do B<not> call the handle's close() method yourself, or pending writes 183  may be lost. 184  The return code indicates whether the session was successfully closed. 185  Note that this returns true on delayed closes, and thus is not of 186  much use in detecting whether the close was actually successful. 187  =item $limit = $session->write_limit([$limit] 188  To prevent the outgoing write buffer from growing without 189  limit, you can call write_limit() to set a cap on its size.  If the 190  number of unwritten bytes exceeds this value, then the I<choke function> 191  will be invoked to perform some action. 192  Called with a single argument, the method sets the write limit. 193  Called with no arguments, returns the current value. Call with 0 to 194  disable the limit. 195  =item $coderef = $session->set_choke([$coderef]) 196  The set_choke() method gets or sets the I<choke function>, which is 197  invoked when the size of the write buffer exceeds the size set by 198  write_limit().  Called with a coderef argument, set_choke() sets the 199  function; otherwise it returns its current value. 200  When the choke function is invoked, it will be called with two 201  arguments consisting of the session object and a flag indicating 202  whether writes should be choked or unchoked.  The function should take 203  whatever action is necessary, and return.  The default choke action is 204  to disallow further reads on the session (by calling readable() with a 205  false value) until the write buffer has returned to acceptable size. 206  Note that choking a session has no effect on the write() method, which 207  can continue to append data to the buffer. 208  =item $session->readable($flag) 209  This method flags the session set that this filehandle should be 210  monitored for reading. C<$flag> is true to allow reads, and false 211  to disallow them. 212  =item $session->writable($flag) 213  This method flags the session set that this filehandle should be 214  monitored for writing. C<$flag> is true to allow writes, and false 215  to disallow them. 216  =back 217  =head1 SEE ALSO 218  L<IO::LineBufferedSessionSet>, L<IO::SessionData>, L<IO::SessionSet >, 219  L<perl> 220  =head1 AUTHOR 221  Lincoln Stein <lstein@cshl.org> 222  =head1 COPYRIGHT 223  Copyright (c) 2000 Lincoln Stein. All rights reserved. This program is 224  free software; you can redistribute it and/or modify it under the same 225  terms as Perl itself. 226  =cut 

   
Top


Network Programming with Perl
Network Programming with Perl
ISBN: 0201615711
EAN: 2147483647
Year: 2000
Pages: 173

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net