(O|B|F)  ···   BIOPERL  · BIOJAVA  · BIOPYTHON  · BIOCORBA  · BIOMOBY  · BIODAS   ( Community link  · BIOINFORMATICS.ORG)    
(file) Return to Das.pm CVS log (file) (dir) Up to [biodas] / Bio-Das2

File: [biodas] / Bio-Das2 / Das.pm (download)
Revision: 1.8, Tue Feb 19 23:10:15 2002 UTC (5 months, 1 week ago) by lstein
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +2 -2 lines
fixed dsn call according to James Smith

package Bio::Das;
# $Id: Das.pm,v 1.8 2002/02/19 23:10:15 lstein Exp $

# prototype parallel-fetching Das

use strict;
use Bio::Das::HTTP::Fetch;
use Bio::Das::Request::Dsn;    # bring in dsn  parser
use Bio::Das::Request::Types;  # bring in type parser
use Bio::Das::Request::Dnas;
use Bio::Das::Request::Features;
use Bio::Das::Util 'rearrange';
use Carp;
use IO::Socket;
use IO::Select;
use vars '$VERSION';
$VERSION = 0.60;
sub new {
  my $package = shift;
  my $timeout = shift;
  return bless {
		'sockets'  => {},   # map socket to Bio::Das::HTTP::Fetch objects
		'timeout'  => $timeout,
	       },$package;
}
sub proxy {
  my $self = shift;
  my $d    = $self->{proxy};
  $self->{proxy} = shift if @_;
  $d;
}
sub timeout {
  my $self = shift;
  my $d = $self->{timeout};
  $self->{timeout} = shift if @_;
  $d;
}
sub debug {
  my $self = shift;
  my $d = $self->{debug};
  $self->{debug} = shift if @_;
  $d;
}
# call with list of base names
# will return a list of DSN objects
sub dsn {
  my $self = shift;
#  my @requests = map { Bio::Das::Request::Dsn->new($_) } @_;
  my @requests = Bio::Das::Request::Dsn->new(@_);
  $self->run_requests(\@requests);
}
# call with list of DSN objects, and optionally list of segments and categories
sub types {
  my $self = shift;
  my ($dsn,$segments,$categories) = rearrange([['dsn','dsns'],
					       ['segment','segments'],
					       ['category','categories'],
					      ],@_);
  croak "must provide -dsn argument" unless $dsn;
  my @dsn = ref $dsn ? @$dsn : $dsn;
  my @request;
  for my $dsn (@dsn) {
    push @request,Bio::Das::Request::Types->new(-dsn        => $dsn,
						-segment    => $segments,
						-categories => $categories);
  }
  $self->run_requests(\@request);
}
# call with list of DSN objects, and a list of one or more segments
sub dna {
  my $self = shift;
  my ($dsn,$segments) = rearrange([['dsn','dsns'],
				   ['segment','segments']
				  ],@_);
  croak "must provide -dsn argument" unless $dsn;
  my @dsn = ref $dsn ? @$dsn : $dsn;
  my @request;
  for my $dsn (@dsn) {
    push @request,Bio::Das::Request::Dnas->new(-dsn        => $dsn,
					       -segment    => $segments);
  }
  $self->run_requests(\@request);
}
# call with list of DSNs, and optionally list of segments and categories
sub features {
  my $self = shift;
  my ($dsn,$segments,$types,$categories,$callback) = rearrange([['dsn','dsns'],
								['segment','segments'],
								['type','types'],
								['category','categories'],
								'callback',
							       ],@_);
  croak "must provide -dsn argument" unless $dsn;
  my @dsn = ref $dsn ? @$dsn : $dsn;
  my @request;
  for my $dsn (@dsn) {
    push @request,Bio::Das::Request::Features->new(-dsn        => $dsn,
						   -segments   => $segments,
						   -types      => $types,
						   -categories => $categories,
						   -callback   => $callback);
  }
  $self->run_requests(\@request);
}
sub add_pending {
  my $self    = shift;
  my $fetcher = shift;
  $self->{sockets}{$fetcher->socket} = $fetcher;
}
sub run_requests {
  my $self     = shift;
  my $requests = shift;
  for my $request (@$requests) {
    my $fetcher = Bio::Das::HTTP::Fetch->new(-request => $request,
					     -headers => {'Accept-encoding' => 'gzip'},
					     -proxy   => $self->proxy || '',
					    ) or next;
    $fetcher->debug(1) if $self->debug;
    $self->add_pending($fetcher);
  }
  my $timeout = $self->timeout;
  # create two IO::Select objects to handle writing & reading  
  my $readers = IO::Select->new;
  my $writers = IO::Select->new;
  for my $fetcher (values %{$self->{sockets}}) {
    my $socket = $fetcher->socket;
    $writers->add($socket);
  }
  my $timed_out;
  while ($readers->count or $writers->count) {
    my ($readable,$writable) = IO::Select->select($readers,$writers,undef,$timeout);
    ++$timed_out && last unless $readable || $writable;
    foreach (@$writable) {                      # handle is ready for writing
      my $fetcher = $self->{sockets}{$_};       # recover the HTTP fetcher
      my $result = $fetcher->send_request;      # try to send the request
      $readers->add($_) if $result;             # send successful, so monitor for reading
      $fetcher->request->error($fetcher->error) 
	unless $result;                         # copy the error message
      $writers->remove($_);                     # and remove from list monitored for writing
    }
    foreach (@$readable) {        # handle is ready for reading
      my $fetcher = $self->{sockets}{$_};       # recover the HTTP object
      my $result = $fetcher->read;              # read some data
      unless ($result) {                    # remove if some error occurred
	$fetcher->request->error($fetcher->error) unless defined $result;
	$readers->remove($_);
	delete $self->{sockets}{$_};
      }
    }
  }
  # handle timeouts
  if ($timed_out) {
    while (my ($sock,$f) = each %{$self->{sockets}}) { # list of still-pending requests
      $f->request->error('timeout');
      $readers->remove($sock);
      $writers->remove($sock);
      close $sock;
    }
  }
  delete $self->{sockets};
  return wantarray ? @$requests : $requests->[0];
}
1;

Maintained by Chris Dagdigian, [email protected]
Powered by
ViewCVS 0.9.2