AcePerl

 view release on metacpan or  search on metacpan

Ace/Local.pm  view on Meta::CPAN

		'auto_save' => 1,
		'status' => $nosync ? STATUS_PENDING : STATUS_WAITING,  # initial stuff to read
	       },$class;
}

sub debug {
  my $self = shift;
  my $d = $self->{debug};
  $self->{debug} = shift if @_;
  $d;
}

sub DESTROY {
  my $self = shift;
  return unless kill 0,$self->{'pid'};
  if ($self->auto_save) {
    # save work for the user...
    $self->query('save'); 
    $self->synch;
  }
  $self->query('quit');

  # just for paranoid reasons. shouldn't be necessary
  close $self->{'write'} if $self->{'write'};  
  close $self->{'read'}  if $self->{'read'};
  waitpid($self->{pid},0) if $self->{'pid'};
}

sub encore {
  my $self = shift;
  return $self->status == STATUS_PENDING;
}

sub auto_save {
  my $self = shift;
  $self->{'auto_save'} = $_[0] if defined $_[0];
  return $self->{'auto_save'};
}

sub status {
  return $_[0]->{'status'};
}

sub error {
  my $self = shift;
  return $self->{'error'};
}

sub query {
  my $self = shift;
  my $query = shift;
  warn "query($query)\n" if $self->debug;
  if ($self->debug) {
    my $msg = $query || '';
    warn "\tquery($msg)";
  }

  return undef if $self->{'status'} == STATUS_ERROR;
  do $self->read() until $self->{'status'} != STATUS_PENDING;
  my $wtr = $self->{'write'};
  print $wtr "$query\n";
  $self->{'status'} = STATUS_PENDING;
}

sub low_read {  # hack to accomodate "uninitialized database" warning from tace
  my $self = shift;
  my $rdr = $self->{'read'};
  return undef unless $self->{'status'} == STATUS_PENDING;
  my $rin = '';
  my $data = '';
  vec($rin,fileno($rdr),1)=1;
  unless (select($rin,undef,undef,1)) {
    $self->{'status'} = STATUS_WAITING;
    return undef;
  }
  sysread($rdr,$data,READSIZE);
  return $data;
}

sub read {
  my $self = shift;
  return undef unless $self->{'status'} == STATUS_PENDING;
  my $rdr  = $self->{'read'};
  my $len  = defined $self->{'buffer'} ? length($self->{'buffer'}) : 0;
  my $plen = length($self->{'prompt'});
  my ($result, $bytes, $pos, $searchfrom);

  while (1) {

    # Read the data directly onto the end of the buffer

    $bytes = sysread($rdr, $self->{'buffer'},
		     READSIZE, $len);

    unless ($bytes > 0) {
      $self->{'status'} = STATUS_ERROR;
      return;
    }

    # check for prompt

    # The following checks were implemented using regexps and $' and
    # friends.  I have changed this to use {r}index and substr (a)
    # because they're much faster than regexps and (b) because using
    # $' and $` causes all regexps in a program to execute
    # very slowly due to excessive and unnecessary pre/post-match
    # copying -- tim.cutts@incyte.com 08 Sep 1999

    # Note, don't need to search the whole buffer for the prompt;
    # just need to search the new data and the prompt length from
    # any previous data.

    $searchfrom = ($len <= $plen) ? 0 : ($len - $plen);

    if (($pos = index($self->{'buffer'},
		      $self->{'prompt'},
		      $searchfrom)) > 0) {
      $self->{'status'} = STATUS_WAITING;
      $result = substr($self->{'buffer'}, 0, $pos);
      $self->{'buffer'} = '';
      return $result;
    }

    # return partial results for paragraph breaks

    if (($pos = rindex($self->{'buffer'}, "\n\n")) > 0) {
      $result = substr($self->{'buffer'}, 0, $pos + 2);
      $self->{'buffer'} = substr($self->{'buffer'},
				 $pos + 2);
      return $result;
    }

    $len += $bytes;

  }

  # never get here
}

# just throw away everything
sub synch {
  my $self = shift;
  $self->read() while $self->status == STATUS_PENDING;
}

# expand ~foo syntax
sub _expand_twiddles {
  my $path = shift;
  my ($to_expand,$homedir);
  return $path unless $path =~ m!^~([^/]*)!;

  if ($to_expand = $1) {
    $homedir = (getpwnam($to_expand))[7];
  } else {
    $homedir = (getpwuid($<))[7];
  }
  return $path unless $homedir;

  $path =~ s!^~[^/]*!$homedir!;
  return $path;
}

__END__

=head1 NAME

Ace::Local - use giface, tace or gifaceclient to open a local connection to an Ace database

=head1 SYNOPSIS

  use Ace::Local
  my $ace = Ace::Local->connect(-path=>'/usr/local/acedb/elegans');
  $ace->query('find author Se*');
  die "Query unsuccessful" unless $ace->status;
  $ace->query('show');
  while ($ace->encore) {
    print $ace->read;
  }

=head1 DESCRIPTION

This class is provided for low-level access to local (non-networked)
Ace databases via the I<giface> program.  You will generally not need
to access it directly.  Use Ace.pm instead.

For the sake of completeness, the method can also use the I<aceclient>
program for its access.  However the Ace::AceDB class is more efficient
for this purpose.

=head1 METHODS

=head2 connect()

  $accessor = Ace::Local->connect(-path=>$path_to_database);

Connect to the database at the indicated path using I<giface> and
return a connection object (an "accessor").  I<Giface> must be on the
current search path.  Multiple accessors may be open simultaneously.

Arguments include:

=over 4

=item B<-path>

Path to the database (location of the "wspec/" directory).

=item B<-program>

Used to indicate the location of the desired I<giface> or
I<gifaceclient> executable.  You may also use I<tace> or I<aceclient>,
but in that case the asGIF() functionality will nog work.  Can be used
to override the search path.

=item B<-host>

Used when invoking I<gifaceclient>.  Indicates the host to connect to.

=item B<-port>

Used when invoking I<gifaceclient>.  Indicates the port to connect to.

=item B<-nosync>

Ordinarily Ace::Local synchronizes with the tace/giface prompt,
throwing out all warnings and copyright messages.  If this is set,
Ace::Local will not do so.  In this case you must call the low_read()
method until it returns undef in order to synchronize.

=back

=head2 query()

  $status = $accessor->query('query string');

Send the query string to the server and return a true value if
successful.  You must then call read() repeatedly in order to fetch



( run in 0.611 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )