AcePerl

 view release on metacpan or  search on metacpan

Ace/Local.pm  view on Meta::CPAN

  # Figure out the prompt by reading until we get zero length,
  # then take whatever's at the end.
  unless ($nosync) {
    local($/) = "> ";
    my $data = <$rdr>;
    ($prompt) = $data=~/^(.+> )/m;
    unless ($prompt) {
      $Ace::Error = "$program didn't open correctly";
      return undef;
    }
  }

  return bless {
		'read'   => $rdr,
		'write'  => $wtr,
		'prompt' => $prompt,
		'pid'    => $pid,
		'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

Ace/Local.pm  view on Meta::CPAN

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
the query result.

=head2 read()

Read the result from the last query sent to the server and return it
as a string.  ACE may return the result in pieces, breaking between
whole objects.  You may need to read repeatedly in order to fetch the
entire result.  Canonical example:

  $accessor->query("find Sequence D*");
  die "Got an error ",$accessor->error() if $accessor->status == STATUS_ERROR;
  while ($accessor->status == STATUS_PENDING) {
     $result .= $accessor->read;
  }

=head2 low_read()

Read whatever data's available, or undef if none.  This is only used
by the ace.pl replacement for giface/tace.

=head2 status()

Return the status code from the last operation.  Status codes are
exported by default when you B<use> Ace.pm.  The status codes you may
see are:

  STATUS_WAITING    The server is waiting for a query.
  STATUS_PENDING    A query has been sent and Ace is waiting for
                    you to read() the result.
  STATUS_ERROR      A communications or syntax error has occurred

=head2 error()

May return a more detailed error code supplied by Ace.  Error checking
is not fully implemented.

=head2 encore()

This method will return true after you have performed one or more
read() operations, and indicates that there is more data to read.
B<encore()> is functionally equivalent to:

   $encore = $accessor->status == STATUS_PENDING;

In fact, this is how it's implemented.

=head2 auto_save()

Sets or queries the I<auto_save> variable.  If true, the "save"
command will be issued automatically before the connection to the
database is severed.  The default is true.

Examples:

   $accessor->auto_save(1);
   $flag = $accessor->auto_save;

=head1 SEE ALSO

L<Ace>, L<Ace::Object>, L<Ace::Iterator>, L<Ace::Model>

=head1 AUTHOR

Lincoln Stein <lstein@w3.org> with extensive help from Jean
Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>

Copyright (c) 1997-1998, Lincoln D. Stein

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.  See DISCLAIMER.txt for
disclaimers of warranty.

=cut



( run in 2.399 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )