view release on metacpan or search on metacpan
require Ace::Iterator;
require Ace::Object;
eval qq{use Ace::Freesubs}; # XS file, may not be available
# Map database names to objects (to fix file-caching issue)
my %NAME2DB;
# internal cache of objects
my %MEMORY_CACHE;
# *models = \&classes;
sub connect {
my $class = shift;
my ($host,$port,$user,$pass,$path,$program,
$objclass,$timeout,$query_timeout,$database,
$server_type,$url,$u,$p,$cache,$other);
# one-argument single "URL" form
if (@_ == 1) {
return $class->connect(-url=>shift);
($host,$port,$u,$pass,$p,$server_type) = $class->process_url($url)
or croak "Usage: Ace->connect(-host=>\$host,-port=>\$port [,-path=>\$path]\n"
if defined $url;
if ($path) { # local database
$server_type = 'Ace::Local';
} else { # either RPC or socket server
$host ||= 'localhost';
$user ||= $u || '';
$path ||= $p || '';
}
# we've normalized parameters, so do the actual connect
eval "require $server_type" || croak "Module $server_type not loaded: $@";
if ($path) {
$database = $server_type->connect(-path=>$path,%$other);
} else {
$database = $server_type->connect($host,$port,$query_timeout,$user,$pass,%$other);
}
unless ($database) {
$Ace::Error ||= "Couldn't open database";
return;
}
my $contents = {
'database'=> $database,
'host' => $host,
'port' => $port,
'path' => $path,
'class' => $objclass || 'Ace::Object',
'timeout' => $query_timeout,
}
sub reopen {
my $self = shift;
return 1 if $self->ping;
my $class = ref($self->{database});
my $database;
if ($self->{path}) {
$database = $class->connect(-path=>$self->{path},%{$self->other});
} else {
$database = $class->connect($self->{host},$self->{port}, $self->{timeout},
$self->{user},$self->{pass},%{$self->{other}});
}
unless ($database) {
$Ace::Error = "Couldn't open database";
return;
}
$self->{database} = $database;
1;
}
sub class {
my $self = shift;
($user,$host,$port) = ($1,$2,$3);
$server_type = 'Ace::SocketServer';
} elsif (m!^sace://([^:]+):(\d+)$!) { # sace://localhost:2005
($host,$port) = ($1,$2);
$server_type = 'Ace::SocketServer';
} elsif (m!^tace:(/.+)$!) { # tace:/path/to/database
$path = $1;
$server_type = 'Ace::Local';
} elsif (m!^(/.+)$!) { # /path/to/database
$path = $1;
$server_type = 'Ace::Local';
} else {
return;
}
}
# Return the low-level Ace::AceDB object
sub db {
return $_[0]->{'database'};
}
# Fetch a model from the database.
# Since there are limited numbers of models, we cache
# the results internally.
sub model {
my $self = shift;
require Ace::Model;
}
#### END: CACHE AND CARRY CODE ####
# Fetch one or a group of objects from the database
sub fetch {
my $self = shift;
my ($class,$pattern,$count,$offset,$query,$filled,$total,$filltag) =
rearrange(['CLASS',['NAME','PATTERN'],'COUNT','OFFSET','QUERY',
['FILL','FILLED'],'TOTAL','FILLTAG'],@_);
sub show {
my ($self,$class,$pattern,$tag) = @_;
$Ace::Error = '';
return unless $self->count($class,$pattern);
# if we get here, then we've got some data to return.
my @result;
my $ts = $self->{'timestamps'} ? '-T' : '';
$self->{database}->query("show -j $ts $tag");
my $result = $self->read_object;
unless ($result =~ /(\d+) object dumped/m) {
$Ace::Error = 'Unexpected close during show';
return;
}
return grep (!m!^//!,split("\n\n",$result));
}
sub read_object {
my $self = shift;
return unless $self->{database};
my $result;
while ($self->{database}->status == STATUS_PENDING()) {
my $data = $self->{database}->read();
# $data =~ s/\0//g; # get rid of nulls in the buffer
$result .= $data if defined $data;
}
return $result;
}
# do a query, and return the result immediately
sub raw_query {
my ($self,$query,$no_alert,$parse) = @_;
$self->_alert_iterators unless $no_alert;
$self->{database}->query($query, $parse ? ACE_PARSE : () );
return $self->read_object;
}
# return the last error
sub error {
$Ace::Error = shift() if defined($_[0]);
$Ace::Error=~s/\0//g; # get rid of nulls
return $Ace::Error;
}
# close the database
sub close {
my $self = shift;
$self->raw_query('save') if $self->auto_save;
foreach (keys %{$self->{iterators}}) {
$self->_unregister_iterator($_);
}
delete $self->{database};
}
sub DESTROY {
my $self = shift;
return if caller() =~ /^Cache\:\:/;
# do a query, but don't return the result
sub _query {
my ($self,@query) = @_;
$self->_alert_iterators;
$self->{'database'}->query("@query");
}
# return a portion of the active list
sub _list {
my $self = shift;
$tag = '' unless defined $tag;
my $query = "show -j $tag";
$query .= ' -T' if $self->{timestamps};
$query .= " -b $start" if defined $start;
$query .= " -c $count" if defined $count;
$self->{database}->query($query);
while (my @objects = $self->_fetch_chunk) {
push (@result,@objects);
}
# copy tag into a portion of the tree
if ($tag) {
return wantarray ? @result : $result[0];
}
sub _fetch_chunk {
my $self = shift;
return unless $self->{database}->status == STATUS_PENDING();
my $result = $self->{database}->read();
$result =~ s/\0//g; # get rid of &$#&@!! nulls
my @chunks = split("\n\n",$result);
my @result;
foreach (@chunks) {
next if m!^//!;
Ace - Object-Oriented Access to ACEDB Databases
=head1 SYNOPSIS
use Ace;
# open a remote database connection
$db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
-port => 20000100);
# open a local database connection
$local = Ace->connect(-path=>'~acedb/my_ace');
# simple queries
$sequence = $db->fetch(Sequence => 'D12345');
$count = $db->count(Sequence => 'D*');
$ready = $db->fetch_many(-query=>$query);
while ($obj = $ready->next) {
# do something with obj
}
# database cut and paste
$sequence = $db->fetch(Sequence => 'D12345');
$local_db->put($sequence);
@sequences = $db->fetch(Sequence => 'D*');
$local_db->put(@sequences);
print Ace->error;
print $db->error;
=head1 DESCRIPTION
AcePerl provides an interface to the ACEDB object-oriented database.
Both read and write access is provided, and ACE objects are returned
as similarly-structured Perl objects. Multiple databases can be
opened simultaneously.
You will interact with several Perl classes: I<Ace>, I<Ace::Object>,
I<Ace::Iterator>, I<Ace::Model>. I<Ace> is the database accessor, and
can be used to open both remote Ace databases (running aceserver or
gifaceserver), and local ones.
I<Ace::Object> is the superclass for all objects returned from the
database. I<Ace> and I<Ace::Object> are linked: if you retrieve an
Ace::Object from a particular database, it will store a reference to
the database and use it to fetch any subobjects contained within it.
You may make changes to the I<Ace::Object> and have those changes
written into the database. You may also create I<Ace::Object>s from
scratch and store them in the database.
I<Ace::Iterator> is a utility class that acts as a database cursor for
long-running ACEDB queries. I<Ace::Model> provides object-oriented
access to ACEDB's schema.
Internally, I<Ace> uses the I<Ace::Local> class for access to local
databases and I<Ace::AceDB> for access to remote databases.
Ordinarily you will not need to interact directly with either of these
classes.
=head1 CREATING NEW DATABASE CONNECTIONS
=head2 connect() -- multiple argument form
# remote database
$db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
-port => 20000100);
# local (non-server) database
$db = Ace->connect(-path => '/usr/local/acedb);
Use Ace::connect() to establish a connection to a networked or local
AceDB database. To establish a connection to an AceDB server, use the
B<-host> and/or B<-port> arguments. For a local server, use the
B<-port> argument. The database must be up and running on the
indicated host and port prior to connecting to an AceDB server. The
full syntax is as follows:
$db = Ace->connect(-host => $host,
-port => $port,
-path => $database_path,
-program => $local_connection_program
-classmapper => $object_class,
-timeout => $timeout,
-query_timeout => $query_timeout
-cache => {cache parameters},
=item B<-program>
By default AcePerl will use its internal compiled code calls to
establish a connection to Ace servers, and will launch a I<tace>
subprocess to communicate with local Ace databases. The B<-program>
argument allows you to customize this behavior by forcing AcePerl to
use a local program to communicate with the database. This argument
should point to an executable on your system. You may use either a
complete path or a bare command name, in which case the PATH
environment variable will be consulted. For example, you could force
AcePerl to use the I<aceclient> program to connect to the remote host
by connecting this way:
-program=>'aceclient');
=item B<-classmapper>
The optional B<-classmapper> argument (alias B<-class>) points to the
class you would like to return from database queries. It is provided
for your use if you subclass Ace::Object. For example, if you have
created a subclass of Ace::Object called Ace::Object::Graphics, you
can have the database return this subclass by default by connecting
this way:
$db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
-port => 20000100,
-class=>'Ace::Object::Graphics');
does not exist in the hash, a key named _DEFAULT_ will be looked for.
If that does not exist, then Ace will default to Ace::Object.
The value of B<-class> can also be an object or a classname that
implements a class_for() method. This method will receive three
arguments containing the AceDB class name, object ID and database
handle. It should return a string indicating the perl class to
create.
=item B<-timeout>
If you prefer to use a more Smalltalk-like message-passing syntax, you
can open a connection this way too:
$db = connect Ace -host=>'beta.crbm.cnrs-mop.fr',-port=>20000100;
The return value is an Ace handle to use to access the database, or
undef if the connection fails. If the connection fails, an error
message can be retrieved by calling Ace->error.
You may check the status of a connection at any time with ping(). It
will return a true value if the database is still connected. Note
that Ace will timeout clients that have been inactive for any length
of time. Long-running clients should attempt to reestablish their
connection if ping() returns false.
$db->ping() || die "not connected";
rpcace://stein.cshl.org:400000
If not provided, the port defaults to 200005
=item tace:/path/to/database
Open up the local database at F</path/to/database> using tace. Example:
tace:/~acedb/elegans
=item /path/to/database
Same as the previous.
=back
=head2 close() Method
You can explicitly close a database by calling its close() method:
$db->close();
This is not ordinarily necessary because the database will be
automatically close when it -- and all objects retrieved from it -- go
out of scope.
=head2 reopen() Method
The ACeDB socket server can time out. The reopen() method will ping
the server and if it is not answering will reopen the connection. If
the database is live (or could be resurrected), this method returns
true.
=head1 RETRIEVING ACEDB OBJECTS
Once you have established a connection and have an Ace databaes
handle, several methods can be used to query the ACE database to
retrieve objects. You can then explore the objects, retrieve specific
fields from them, or update them using the I<Ace::Object> methods.
Please see L<Ace::Object>.
=head2 fetch() method
-fill=>$fill,
-filltag=>$tag,
-total=>\$total);
@objects = $db->fetch(-query=>$query);
Ace::fetch() retrieves objects from the database based on their class
and name. You may retrieve a single object by requesting its name, or
a group of objects by fetching a name I<pattern>. A pattern contains
one or more wildcard characters, where "*" stands for zero or more
characters, and "?" stands for any single character.
array context, it will return an empty list.
When called with a class and a name pattern in a list context, fetch()
returns the list of objects that match the name. When called with a
pattern in a scalar context, fetch() returns the I<number> of objects
that match without actually retrieving them from the database. Thus,
it is similar to count().
In the examples below, the first line of code will fetch the Sequence
object whose database ID is I<D12345>. The second line will retrieve
all objects matching the pattern I<D1234*>. The third line will
return the count of objects that match the same pattern.
$object = $db->fetch(Sequence => 'D12345');
@objects = $db->fetch(Sequence => 'D1234*');
$cnt = $db->fetch(Sequence =>'D1234*');
A variety of communications and database errors may occur while
processing the request. When this happens, undef or an empty list
will be returned, and a string describing the error can be retrieved
by calling Ace->error.
When retrieving database objects, it is possible to retrieve a
"filled" or an "unfilled" object. A filled object contains the entire
contents of the object, including all tags and subtags. In the case
of certain Sequence objects, this may be a significant amount of data.
Unfilled objects consist just of the object name. They are filled in
from the database a little bit at a time as tags are requested. By
default, fetch() returns the unfilled object. This is usually a
performance win, but if you know in advance that you will be needing
the full contents of the retrieved object (for example, to display
them in a tree browser) it can be more efficient to fetch them in
filled mode. You do this by calling fetch() with the argument of
B<-fill> set to a true value.
The B<-filltag> argument, if provided, asks the database to fill in
the subtree anchored at the indicated tag. This will improve
performance for frequently-accessed subtrees. For example:
@objects = $db->fetch(-name => 'D123*',
-class => 'Sequence',
$object = $db->get($class,$name [,$fill]);
The get() method will return one and only one AceDB object
identified by its class and name. The optional $fill argument can be
used to control how much data is retrieved from the database. If $fill
is absent or undefined, then the method will return a lightweight
"stub" object that is filled with information as requested in a lazy
fashion. If $fill is the number "1" then the retrieved object contains
all the relevant information contained within the database. Any other
true value of $fill will be treated as a tag name: the returned object
will be prefilled with the subtree to the right of that tag.
Examples:
=head2 aql() method
$count = $db->aql($aql_query);
@objects = $db->aql($aql_query);
Ace::aql() will perform an AQL query on the database. In a scalar
context it returns the number of rows returned. In an array context
it returns a list of rows. Each row is an anonymous array containing
the columns returned by the query as an Ace::Object.
If an AQL error is encountered, will return undef or an empty list and
=head2 put() method
$cnt = $db->put($obj1,$obj2,$obj3);
This method will put the list of objects into the database,
overwriting like-named objects if they are already there. This can
be used to copy an object from one database to another, provided that
the models are compatible.
The method returns the count of objects successfully written into the
database. In case of an error, processing will stop at the last
object successfully written and an error message will be placed in
Ace->error();
=head2 parse() method
$object = $db->parse('data to parse');
This will parse the Ace tags contained within the "data to parse"
string, convert it into an object in the databse, and return the
resulting Ace::Object. In case of a parse error, the undefined value
will be returned and a (hopefully informative) description of the
error will be returned by Ace->error().
For example:
=head2 parse_longtext() method
$object = $db->parse($title,$text);
This will parse the long text (which may contain carriage returns and
other funny characters) and place it into the database with the given
title. In case of a parse error, the undefined value will be returned
and a (hopefully informative) description of the error will be
returned by Ace->error(); otherwise, a LongText object will be returned.
For example:
@objects = $db->parse_file('/path/to/file');
@objects = $db->parse_file('/path/to/file',1);
This will call parse() to parse each of the objects found in the
indicated .ace file, returning the list of objects successfully loaded
into the database.
By default, parsing will stop at the first object that causes a parse
error. If you wish to forge on after an error, pass a true value as
the second argument to this method.
=head2 new() method
$object = $db->new($class => $name);
This method creates a new object in the database of type $class and
name $name. If successful, it returns the newly-created object.
Otherwise it returns undef and sets $db->error().
$name may contain sprintf()-style patterns. If one of the patterns is
%d (or a variant), Acedb uses a class-specific unique numbering to return
a unique name. For example:
$paper = $db->new(Paper => 'wgb%06d');
The object is created in the database atomically. There is no chance to rollback as there is
in Ace::Object's object editing methods.
See also the Ace::Object->add() and replace() methods.
=head2 list() method
=head2 count() method
$count = $db->count($class,$pattern);
$count = $db->count(-query=>$query);
This function queries the database for a list of objects matching the
specified class and pattern, and returns the object count. For large
sets of objects this is much more time and memory effective than
fetching the entire list.
The class and name pattern are the same as the list() method above.
-chunksize=>$chunksize);
$obj = $db->fetch_many(-query=>$query);
If you expect to retrieve many objects, you can fetch an iterator
across the data set. This is friendly both in terms of network
bandwidth and memory consumption. It is simple to use:
$i = $db->fetch_many(Sequence,'*'); # all sequences!!!!
while ($obj = $i->next) {
print $obj->asTable;
B<-filled>) argument which retrieves the entire object rather than
just its name. This is efficient on a network with high latency if
you expect to be touching many parts of the object (rather than
just retrieving the value of a few tags).
B<fetch_many()> retrieves objects from the database in groups of a
certain maximum size, 40 by default. This can be tuned using the
optional B<-chunksize> argument. Chunksize is only a hint to the
database. It may return fewer objects per transaction, particularly
if the objects are large.
You may provide raw Ace query string with the B<-query> argument. If
present the B<-name> and B<-class> arguments will be ignored.
-filltag => $filltag,
-total => \$total,
-long => 1,
);
This performs a "grep" on the database, returning all object names or
text that contain the indicated grep pattern. In a scalar context
this call will return the number of matching objects. In an array
context, the list of matching objects are retrieved. There is also a
named-parameter form of the call, which allows you to specify the
number of objects to retrieve, the offset from the beginning of the
$obj = $db->new($class,$name);
$obj = $db->new(-class=>$class,
-name=>$name);
Create a new object in the database with the indicated class and name
and return a pointer to it. Will return undef if the object already
exists in the database. The object isn't actually written into the database
until you call Ace::Object::commit().
=head2 raw_query() method
$r = $db->raw_query('Model');
Send a command to the database and return its unprocessed output.
This method is necessary to gain access to features that are not yet
implemented in this module, such as model browsing and complex
queries.
=head2 classes() method
@classes = $db->classes();
@all_classes = $db->classes(1);
This method returns a list of all the object classes known to the
server. In a list context it returns an array of class names. In a
scalar context, it the number of classes defined in the database.
Ordinarily I<classes()> will return only those classes that are
exposed to the user interface for browsing, the so-called "visible"
classes. Pass a true argument to the call to retrieve non-visible
classes as well.
code
program name of acedb binary
version version of acedb binary
build build date of acedb binary in format Jan 25 2003 16:21:24
database
title name of the database
version version of the database
dbformat database format version number
directory directory in which the database is stored
session session number
user user under which server is running
write whether the server has write access
address global address - not known if this is useful
=head2 title() method
my $title = $db->title
Returns the version of the current database, equivalent
to $db->status->{database}{title};
=head2 version() method
my $version = $db->version;
Returns the version of the current database, equivalent
to $db->status->{database}{version};
=head2 date_style() method
$style = $db->date_style();
$style = $db->date_style('ace');
=head2 timestamps() method
$timestamps_on = $db->timestamps();
$db->timestamps(1);
Whenever a data object is updated, AceDB records the time and date of
the update, and the user ID it was running under. Ordinarily, the
retrieval of timestamp information is suppressed to conserve memory
and bandwidth. To turn on timestamps, call the B<timestamps()> method
with a true value. You can retrieve the current value of the setting
by calling the method with no arguments.
=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:
$db->auto_save(1);
$flag = $db->auto_save;
method call has returned a result value indicating a failure.
For your convenience, you can call error() in any of several ways:
print Ace->error();
print $db->error(); # $db is an Ace database handle
print $obj->error(); # $object is an Ace::Object
There's also a global named $Ace::Error that you are free to use.
=head2 datetime() and date()
This class method gets or sets the debug level. Higher integers
increase verbosity. 0 or undef turns off debug messages.
=head2 name2db()
$db = Ace->name2db($name [,$database])
This class method associates a database URL with an Ace database
object. This is used internally by the Ace::Object class in order to
discover what database they "belong" to.
=head2 cache()
Get or set the Cache::SizeAwareFileCache object, if one has been
created.
of these error codes and their significance.
=item encore()
This method may return true after you have performed one or more
read() operations, and indicates that there is more data to read. You
will not ordinarily have to call this method.
=back
=head1 BUGS
1. The ACE model should be consulted prior to updating the database.
2. There is no automatic recovery from connection errors.
3. Debugging has only one level of verbosity, despite the best
of intentions.
my $d = $DEBUG_LEVEL;
$DEBUG_LEVEL = shift if @_;
$d;
}
# Return true if the database is still connected. This is oddly convoluted
# because there are numerous things that can go wrong, including:
# 1. server has gone away
# 2. server has timed out our connection! (grrrrr)
# 3. communications channel contains unread garbage and is in an inconsistent state
sub ping {
my $self = shift;
local($SIG{PIPE})='IGNORE'; # so we don't get a fatal exception during the check
my $result = $self->raw_query('');
return unless $result; # server has gone away
return if $result=~/broken connection|client time out/; # server has timed us out
return unless $self->{database}->status() == STATUS_WAITING(); #communications oddness
return 1;
}
# Get or set the display style for dates
sub date_style {
my $self = shift;
$self->{'timestamps'} = $_[0] if defined $_[0];
return $self->{'timestamps'};
}
# Add one or more objects to the database
sub put {
my $self = shift;
my @objects = @_;
my $count = 0;
$Ace::Error = '';
foreach my $object (@objects) {
croak "Can't put a non-Ace object into an Ace database"
unless $object->isa('Ace::Object');
croak "Can't put a non-object into a database"
unless $object->isObject;
$object = $object->fetch unless $object->isRoot; # make sure we're putting root object
my $data = $object->asAce;
$data =~ s/\n/; /mg;
my $result = $self->raw_query("parse = $data");
$Ace::Error = $result if $result =~ /sorry|parse error/mi;
return $count if $Ace::Error;
$count++; # bump if succesful
}
return $count;
}
# Parse a single object and return the result as an object
sub parse {
my $self = shift;
my $ace_data = shift;
my @lines = split("\n",$ace_data);
foreach (@lines) { s/;/\\;/; } # protect semicolons
my $query = join("; ",@lines);
my $result = $self->raw_query("parse = $query");
$Ace::Error = $result=~/sorry|parse error/mi ? $result : '';
my @results = $self->_list(1,0);
close ACE;
$Ace::Error = $errors;
return @objects;
}
# Create a new Ace::Object in the indicated database
# (doesn't actually write into database until you do a commit)
sub new {
my $self = shift;
my ($class,$name) = rearrange([qw/CLASS NAME/],@_);
return if $self->fetch($class,$name);
my $obj = $self->class_for($class,$name)->new($class,$name,$self);
# Return a hash of miscellaneous status information from the server
# (to be expanded later)
sub status {
my $self = shift;
my $data = $self->raw_query('status');
study $data;
my %status;
# -Code section
my ($program) = $data=~/Program:\s+(.+)/m;
my ($aceversion) = $data=~/Version:\s+(.+)/m;
my ($build) = $data=~/Build:\s+(.+)/m;
$status{code} = { program=>$program,
version=>$aceversion,
build =>$build};
# -Database section
my ($title) = $data=~/Title:\s+(.+)/m;
my ($name) = $data=~/Name:\s+(.+)/m;
my ($release) = $data=~/Release:\s+(.+)/m;
my ($directory) = $data=~/Directory:\s+(.+)/m;
my ($session) = $data=~/Session:\s+(\d+)/m;
my ($user) = $data=~/User:\s+(.+)/m;
my ($write) = $data=~/Write Access:\s+(.+)/m;
my ($address) = $data=~/Global Address:\s+(\d+)/m;
$status{database} = {
title => $title,
version => $name,
dbformat => $release,
directory => $directory,
session => $session,
write => $write,
address => $address,
};
# other info - not all
my ($classes) = $data=~/classes:\s+(\d+)/;
my ($keys) = $data=~/keys:\s+(\d+)/;
my ($memory) = $data=~/blocks:\s+\d+,\s+allocated \(kb\):\s+(\d+)/;
$status{resources} = {
classes => $classes,
keys => $keys,
memory => $memory * 1024,
};
}
sub title {
my $self = shift;
my $status= $self->status;
$status->{database}{title};
}
sub version {
my $self = shift;
my $status= $self->status;
$status->{database}{version};
}
sub auto_save {
my $self = shift;
if ($self->db && $self->db->can('auto_save')) {
$Ace::Error = '';
# assumption of uniqueness of name is violated by some classes!
# return () unless $self->count($class,$item) == 1;
return unless $self->count($class,$item) >= 1;
# if we get here, then we've got some data to return.
# yes, we're repeating code slightly...
my @result;
my $ts = $self->{'timestamps'} ? '-T' : '';
my $result = $self->raw_query("show -j $ts");
unless ($result =~ /(\d+) object dumped/m) {
$self->raw_query("spush",'no_alert');
unshift @{$self->{iterator_stack}},$iterator;
1; # result code -- CHANGE THIS LATER
}
# horrid method that keeps the database's view of
# iterators in synch with our view
sub _restore_iterator {
my $self = shift;
my $iterator = shift;
: $self->raw_query("spick $i",'no_alert');
if ($result =~ /Keyword spick does not match/) {
# _restore_iterator will now only work for a single iterator (non-reentrantly)
$self->{no_spick}++;
$self->raw_query('spop','no_alert') foreach @$list; # empty database stack
$self->{iterator_stack} = []; # and local copy
return;
}
unless (($result =~ /The stack now holds (\d+) keyset/ && ($1 == (@$list-1) ))
view all matches for this distribution
view release on metacpan or search on metacpan
Changes
Makefile.PL
lib/Acme/123.pm
t/001_load.t
t/002_numbers.t
META.yml Module meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/24.pm view on Meta::CPAN
}
return(\@facts);
}
# Build a database of Jack Bauer facts
sub collect_facts
{
my($self, $file) = @_;
$file ||= './jackbauer.txt';
my $new_facts = $self->random_jackbauer_facts();
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/6502.pm view on Meta::CPAN
Read a 32 bit word at the specified address.
=item C<read_chunk( $start, $end )>
Read a chunk of data from C<$start> to C<$end> - 1 into a string.
=item C<read_str( $addr )>
Read a carriage return terminated (0x0D) string from the
specified address.
lib/Acme/6502.pm view on Meta::CPAN
Write a 32 bit value at the specified address.
=item C<write_chunk( $addr, $string )>
Write a chunk of data to memory.
=back
=head1 DIAGNOSTICS
view all matches for this distribution
view release on metacpan or search on metacpan
t/boilerplate.t
t/manifest.t
t/pod-coverage.t
t/pod.t
t/sum.t
META.yml Module meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
inc/Module/Install/Metadata.pm view on Meta::CPAN
#line 1
package Module::Install::Metadata;
use strict 'vars';
use Module::Install::Base;
use vars qw{$VERSION $ISCORE @ISA};
inc/Module/Install/Metadata.pm view on Meta::CPAN
sub read {
my $self = shift;
$self->include_deps( 'YAML::Tiny', 0 );
require YAML::Tiny;
my $data = YAML::Tiny::LoadFile('META.yml');
# Call methods explicitly in case user has already set some values.
while ( my ( $key, $value ) = each %$data ) {
next unless $self->can($key);
if ( ref $value eq 'HASH' ) {
while ( my ( $module, $version ) = each %$value ) {
$self->can($key)->($self, $module => $version );
}
view all matches for this distribution
view release on metacpan or search on metacpan
inc/Module/Install/Metadata.pm view on Meta::CPAN
#line 1
package Module::Install::Metadata;
use strict 'vars';
use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
inc/Module/Install/Metadata.pm view on Meta::CPAN
sub read {
my $self = shift;
$self->include_deps( 'YAML::Tiny', 0 );
require YAML::Tiny;
my $data = YAML::Tiny::LoadFile('META.yml');
# Call methods explicitly in case user has already set some values.
while ( my ( $key, $value ) = each %$data ) {
next unless $self->can($key);
if ( ref $value eq 'HASH' ) {
while ( my ( $module, $version ) = each %$value ) {
$self->can($key)->($self, $module => $version );
}
inc/Module/Install/Metadata.pm view on Meta::CPAN
$v = $v + 0;
}
return $v;
}
sub add_metadata {
my $self = shift;
my %hash = @_;
for my $key (keys %hash) {
warn "add_metadata: $key is not prefixed with 'x_'.\n" .
"Use appopriate function to add non-private metadata.\n" unless $key =~ /^x_/;
$self->{values}->{$key} = $hash{$key};
}
}
inc/Module/Install/Metadata.pm view on Meta::CPAN
# We need YAML::Tiny to write the MYMETA.yml file
unless ( eval { require YAML::Tiny; 1; } ) {
return 1;
}
# Generate the data
my $meta = $self->_write_mymeta_data or return 1;
# Save as the MYMETA.yml file
print "Writing MYMETA.yml\n";
YAML::Tiny::DumpFile('MYMETA.yml', $meta);
}
inc/Module/Install/Metadata.pm view on Meta::CPAN
# We need JSON to write the MYMETA.json file
unless ( eval { require JSON; 1; } ) {
return 1;
}
# Generate the data
my $meta = $self->_write_mymeta_data or return 1;
# Save as the MYMETA.yml file
print "Writing MYMETA.json\n";
Module::Install::_write(
'MYMETA.json',
JSON->new->pretty(1)->canonical->encode($meta),
);
}
sub _write_mymeta_data {
my $self = shift;
# If there's no existing META.yml there is nothing we can do
return undef unless -f 'META.yml';
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/AjiFry.pm view on Meta::CPAN
=for author to fill in:
A list of known problems with the module, together with some
indication Whether they are likely to be fixed in an upcoming
release. Also a list of restrictions on the features the module
does provide: data types that cannot be handled, performance issues
and the circumstances in which they may arise, practical
limitations on the size of data sets, special cases that are not
(yet) handled, etc.
No bugs have been reported.
Please report any bugs or feature requests to
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/Akashic/Records.pm
t/00-load.t
t/manifest.t
t/pod-coverage.t
t/pod.t
META.yml Module meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
inc/Module/Install/Metadata.pm view on Meta::CPAN
#line 1
package Module::Install::Metadata;
use strict 'vars';
use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
inc/Module/Install/Metadata.pm view on Meta::CPAN
sub read {
my $self = shift;
$self->include_deps( 'YAML::Tiny', 0 );
require YAML::Tiny;
my $data = YAML::Tiny::LoadFile('META.yml');
# Call methods explicitly in case user has already set some values.
while ( my ( $key, $value ) = each %$data ) {
next unless $self->can($key);
if ( ref $value eq 'HASH' ) {
while ( my ( $module, $version ) = each %$value ) {
$self->can($key)->($self, $module => $version );
}
inc/Module/Install/Metadata.pm view on Meta::CPAN
# We need YAML::Tiny to write the MYMETA.yml file
unless ( eval { require YAML::Tiny; 1; } ) {
return 1;
}
# Generate the data
my $meta = $self->_write_mymeta_data or return 1;
# Save as the MYMETA.yml file
print "Writing MYMETA.yml\n";
YAML::Tiny::DumpFile('MYMETA.yml', $meta);
}
inc/Module/Install/Metadata.pm view on Meta::CPAN
# We need JSON to write the MYMETA.json file
unless ( eval { require JSON; 1; } ) {
return 1;
}
# Generate the data
my $meta = $self->_write_mymeta_data or return 1;
# Save as the MYMETA.yml file
print "Writing MYMETA.json\n";
Module::Install::_write(
'MYMETA.json',
JSON->new->pretty(1)->canonical->encode($meta),
);
}
sub _write_mymeta_data {
my $self = shift;
# If there's no existing META.yml there is nothing we can do
return undef unless -f 'META.yml';
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/AlgebraicToRPN.pm
t/00-load.t
t/01-test.t
t/pod-coverage.t
t/pod.t
META.yml Module meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
t/pod-coverage.t
t/pod-encoding.t
t/pod-spelling.t
t/pod-version.t
t/pod.t
META.yml Module YAML meta-data (added by MakeMaker)
META.json Module JSON meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
t/00-load.t
t/manifest.t
t/pod-coverage.t
t/pod.t
xt/boilerplate.t
META.yml Module YAML meta-data (added by MakeMaker)
META.json Module JSON meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/Archive/Mbox.pm view on Meta::CPAN
=head1 SYNOPSIS
Uses Mbox as an archive format, like tar or zip but silly. Creates an mbox
with one message per file or directory. File contents are stored as an
attachment, metadata goes in mail headers.
use Acme::Archive::Mbox;
my $archive = Acme::Archive::Mbox->new();
$archive->add_file('filename');
$archive->add_data('file/name', $contents);
$archive->write('foo.mbox');
...
$archive->read('foo.mbox');
lib/Acme/Archive/Mbox.pm view on Meta::CPAN
my $class = shift;
my $self = { files => [] };
return bless $self,$class;
}
=head2 add_data ($name, $contents, %attr)
Add a file given a filename and contents. (File need not exist on disk)
=cut
sub add_data {
my $self = shift;
my $name = shift;
my $contents = shift;
my %attr = @_;
lib/Acme/Archive/Mbox.pm view on Meta::CPAN
my $mgr = Mail::Box::Manager->new;
my $folder = $mgr->open($mboxname, type => 'mbox', create => 1, access => 'rw') or die "Could not create $mboxname";
for my $file (@{$self->{files}}) {
my $attach = Mail::Message::Body->new( mime_type => 'application/octet-stream',
data => $file->contents,
);
my $message = Mail::Message->build( From => '"Acme::Archive::Mbox" <AAM@example.com>',
To => '"Anyone, really" <anyone@example.com>',
Subject => $file->name,
'X-AAM-uid' => $file->uid,
'X-AAM-gid' => $file->gid,
'X-AAM-mode' => $file->mode,
'X-AAM-mtime' => $file->mtime,
data => 'attached',
attach => $attach, );
$folder->addMessage($message);
}
$folder->write();
$mgr->close($folder);
lib/Acme/Archive/Mbox.pm view on Meta::CPAN
for (qw/uid gid mode mtime/) {
$attr{$_} = $message->get("X-AAM-$_");
}
my $contents = ($message->parts())[1]->decoded();
$self->add_data($name, $contents, %attr);
}
$mgr->close($folder);
}
=head1 AUTHOR
view all matches for this distribution
view release on metacpan or search on metacpan
t/10-instance.t
t/manifest.t
t/pod-coverage.t
t/pod.t
MANIFEST.SKIP
META.yml Module YAML meta-data (added by MakeMaker)
META.json Module JSON meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/AsciiArtFarts.pm
t/00-load.t
t/manifest.t
t/pod-coverage.t
t/pod.t
META.yml Module meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/AsciiArtinator.pm view on Meta::CPAN
behavior of the code. A separate test will be conducted for
every C<test_argvE<lt>NNNE<gt>> parameter passed to the
C<asciiartinate> method. The arguments associated with each
parameter will be passed to the code as command-line arguments.
=item test_input1 => [ @data ], test_input2 => [ @data ], test_input3 => ...
Executes the original and the artinated code and compares the output
to make sure that the artination process did not change the
behavior of the code. A separate test will be conducted for
every C<test_inputE<lt>NNNE<gt>> parameter passed to the
C<asciiartinate> method. The data associated with each
parameter will be passed to the standard input of the code.
=back
view all matches for this distribution
view release on metacpan or search on metacpan
ignore.txt
lib/Acme/AsciiEmoji.pm
LICENSE
Makefile.PL
MANIFEST This list of files
META.json Module JSON meta-data (added by MakeMaker)
META.yml Module YAML meta-data (added by MakeMaker)
README
README.md
t/00-load.t
t/01-emoji.t
t/02-smile.t
view all matches for this distribution
view release on metacpan or search on metacpan
README
t/01-standard-colors.t
t/02-octarine.t
t/03-pod.t
t/04-podcoverage.t
META.yml Module meta-data (added by MakeMaker)
META.json Module JSON meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
t/10_live.t
t/20_bootstrap.t
lib/Acme/AutoLoad.pm
contrib/cwd_guard.pl
contrib/hello_app.cgi
META.yml Module meta-data (added by MakeMaker)
META.json Module JSON meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
README.md
t/00-load.t
t/manifest.t
t/pod-coverage.t
t/pod.t
META.yml Module YAML meta-data (added by MakeMaker)
META.json Module JSON meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
t/00-load.t
t/manifest.t
t/pod-coverage.t
t/pod.t
t/sum.t
META.yml Module YAML meta-data (added by MakeMaker)
META.json Module JSON meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
Makefile.PL
README
lib/Acme/BOPE.pm
t/00-load.t
t/pod.t
META.yml Module meta-data (added by MakeMaker)
view all matches for this distribution
view release on metacpan or search on metacpan
Changes
lib/Acme/Backwards.pm
Makefile.PL
MANIFEST This list of files
META.json Module JSON meta-data (added by MakeMaker)
META.yml Module YAML meta-data (added by MakeMaker)
README
t/00-load.t
t/01-backwards.t
t/02-rof.t
t/manifest.t
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/BadFont.pm
maint/Makefile.PL.include
Makefile.PL
MANIFEST This list of files
t/basic.t
META.yml Module YAML meta-data (added by MakeMaker)
META.json Module JSON meta-data (added by MakeMaker)
README README file (added by Distar)
view all matches for this distribution
view release on metacpan or search on metacpan
0.04 Wed Nov 11 19:23:14 2020
Added links to GitHub repository and issue tracker.
0.03 Sat Aug 20 08:42:51 2011
Missed text of GPL in module (pod) documentation.
Need to use Perl 5.14 for building, else metadata is wrong.
0.02 Fri Aug 19 15:49:05 2011
Updated to GPL 3 configured Module::Build to generate the LICENSE file.
0.01 Wed Aug 17 15:28:15 2011
view all matches for this distribution
view release on metacpan or search on metacpan
MANIFEST.SKIP view on Meta::CPAN
\.#
\.rej$
\..*\.sw.?$
# Avoid OS-specific files/dirs
# Mac OSX metadata
\B\.DS_Store
# Mac OSX SMB mount metadata files
\B\._
# Avoid Devel::Cover and Devel::CoverX::Covered files.
\bcover_db\b
\bcovered\b
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/BeyondPerl/ToSQL.pm view on Meta::CPAN
use Carp;
our $VERSION = 0.01;
our $DEBUG = 0;
my $Dbh; # database handle
my $Type; # rdbm type
END {
$Dbh->disconnect()
}
view all matches for this distribution
view release on metacpan or search on metacpan
lib/Acme/Bitfield.pm view on Meta::CPAN
use feature 'class';
no warnings 'experimental::class';
#
class Acme::Bitfield v1.1.0 {
field $size : reader : param;
field $data : reader : param = "\0" x int( ( $size + 7 ) / 8 );
ADJUST {
$self->_clean;
}
method set_data ($val) {
$data = $val;
$self->_clean; # We can't use the :writer because we must call this
}
# Internal helper to map BitTorrent bit index to vec index
# BT: bit 0 is 0x80, bit 7 is 0x01
# vec: bit 0 is 0x01, bit 7 is 0x80
sub _map ($index) { ( $index & ~7 ) | ( 7 - ( $index & 7 ) ) }
method get ($index) {
return 0 if $index < 0 || $index >= $size;
vec $data, _map($index), 1;
}
method set ($index) {
return if $index < 0 || $index >= $size;
vec( $data, _map($index), 1 ) = 1;
}
method clear ($index) {
return if $index < 0 || $index >= $size;
vec( $data, _map($index), 1 ) = 0;
}
method count () {
return unpack( '%32b*', $data );
}
method is_full () {
return $self->count == $size;
}
method is_empty () {
return $data =~ tr/\0//c ? 0 : 1;
}
method union ($other) {
my $new = __CLASS__->new( size => $size );
$new->set_data( $data|.$other->data );
return $new;
}
method intersection ($other) {
my $new = __CLASS__->new( size => $size );
$new->set_data( $data&.$other->data );
return $new;
}
method difference ($other) {
# Bits set in self but NOT in other
my $new = __CLASS__->new( size => $size );
$new->set_data( $data&.~.$other->data );
return $new;
}
method _clean () {
# internal method to automatically handle data truncation, padding, and bit masking
my $expected_len = int( ( $size + 7 ) / 8 );
if ( length($data) > $expected_len ) {
substr( $data, $expected_len ) = "";
}
elsif ( length($data) < $expected_len ) {
$data .= "\0" x ( $expected_len - length($data) );
}
my $bits_in_last_byte = $size % 8;
if ( $bits_in_last_byte != 0 && $expected_len > 0 ) {
my $mask = ( 0xFF << ( 8 - $bits_in_last_byte ) ) & 0xFF;
substr( $data, -1, 1 ) &.= chr($mask);
}
}
method fill () {
$data = "\xFF" x length($data);
$self->_clean;
}
method find_missing () {
my $index = index( unpack( 'B*', $data ), '0' );
return ( $index >= 0 && $index < $size ) ? $index : ();
}
method inverse () {
my $inverted = __CLASS__->new( size => $size );
$inverted->set_data( ~.$data );
return $inverted;
}
};
#
1;
view all matches for this distribution
view release on metacpan or search on metacpan
Makefile.PL
MANIFEST
README
t/Acme-BlahBlahBlah.t
lib/Acme/BlahBlahBlah.pm
META.yml Module meta-data (added by MakeMaker)
view all matches for this distribution