Author: timbo
Date: Wed Apr 11 08:57:46 2007
New Revision: 9395
Modified:
dbi/trunk/Changes
dbi/trunk/DBI.pm
dbi/trunk/DBI.xs
dbi/trunk/lib/DBD/Gofer/Transport/Base.pm
dbi/trunk/lib/DBD/Gofer/Transport/null.pm
dbi/trunk/lib/DBD/Gofer/Transport/pipeone.pm
dbi/trunk/lib/DBD/Gofer/Transport/stream.pm
dbi/trunk/lib/DBI/Gofer/Execute.pm
dbi/trunk/lib/DBI/Gofer/Transport/Base.pm
dbi/trunk/lib/DBI/Gofer/Transport/pipeone.pm
dbi/trunk/lib/DBI/Gofer/Transport/stream.pm
dbi/trunk/lib/DBI/ProfileDumper.pm
dbi/trunk/lib/DBI/ProfileSubs.pm
Log:
Remove old DBI internal sanity check that's no longer valid (after spending a
few hours banging my head against it)
Change gofer null transport to use base class (for timeout etc handling)
Trap broken pipe and return sensible error message.
Assorted transport cleanups and better error handling/tracing.
Make pipeone and stream transports independent of $\ (perl -l).
Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes (original)
+++ dbi/trunk/Changes Wed Apr 11 08:57:46 2007
@@ -14,9 +14,13 @@
on the basis that if you can alter the code to add go_* attributes
then you can also put your required logic at that place
+Move post-request cleanup into separate method and enable hooks so
+ it can be done after the response has been sent
+
Gofer request flags:
return current executor stats as an attribute - handy for tests
only fetch one result set - handy for Sybase/MSSQL users
+ will accept streamed resultsets
Pedantic policy should force a fresh connect each time - add new policy item
Add attr-passthru to prepare()? ie for gofer cache control
Terminology for client and server ends
Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm (original)
+++ dbi/trunk/DBI.pm Wed Apr 11 08:57:46 2007
@@ -497,7 +497,7 @@
END {
return unless defined &DBI::trace_msg; # return unless bootstrap'd ok
local ($!,$?);
- DBI->trace_msg(" -- DBI::END\n", 2);
+ DBI->trace_msg(sprintf(" -- DBI::END (\$\@: %s, \$!: %s)\n", $@||'',
$!||''), 2);
# Let drivers know why we are calling disconnect_all:
$DBI::PERL_ENDING = $DBI::PERL_ENDING = 1; # avoid typo warning
DBI->disconnect_all() if %DBI::installed_drh;
Modified: dbi/trunk/DBI.xs
==============================================================================
--- dbi/trunk/DBI.xs (original)
+++ dbi/trunk/DBI.xs Wed Apr 11 08:57:46 2007
@@ -695,7 +695,7 @@
level = old_level; /* undef: no change */
else
if (SvTRUE(level_sv)) {
- if (looks_like_number(level_sv) && SvIV(level_sv)>=0)
+ if (looks_like_number(level_sv))
level = SvIV(level_sv); /* number: number */
else { /* string: parse it */
dSP;
@@ -751,7 +751,7 @@
dPERINTERP;
MAGIC *mg;
SV *ohv; /* outer HV after derefing the RV */
- SV *hrv; /* dni inner handle RV-to-HV */
+ SV *hrv; /* dbi inner handle RV-to-HV */
/* enable a raw HV (not ref-to-HV) to be passed in, eg DBIc_MY_H */
ohv = SvROK(orv) ? SvRV(orv) : orv;
@@ -787,14 +787,6 @@
hrv = mg->mg_obj; /* inner hash of tie */
}
- /* extra checks if being paranoid */
- if (DBIS_TRACE_LEVEL && (!SvROK(hrv) || SvTYPE(SvRV(hrv)) != SVt_PVHV)) {
- if (!what)
- return NULL;
- sv_dump(orv);
- croak("panic: %s inner handle %s is not a hash ref (isref=%d, type=%d)",
- what, neatsvpv(hrv,0), SvROK(hrv),
(SvROK(hrv))?SvTYPE(SvRV(hrv)):-1);
- }
return hrv;
}
@@ -2711,7 +2703,7 @@
#endif
if (imp_xxh && DBIc_TYPE(imp_xxh) <= DBIt_DB &&
DBIc_CACHED_KIDS((imp_drh_t*)imp_xxh))
clear_cached_kids(mg->mg_obj, imp_xxh, meth_name, trace_level);
- if (trace_level >= 3)
+ if (trace_level >= 3) {
/* XXX might be better to move this down to after call_depth
has been
* incremented and then also SvREFCNT_dec(mg->mg_obj) to force
an immediate
* DESTROY of the inner handle if there are no other refs to
it.
@@ -2723,6 +2715,7 @@
(dirty?'!':' '), neatsvpv(h,0), neatsvpv(mg->mg_obj,0),
(long)SvREFCNT(SvRV(mg->mg_obj))
);
+ }
/* for now we ignore it since it'll be followed soon by */
/* a destroy of the inner hash and that'll do the real work */
@@ -2730,7 +2723,7 @@
/* pointing (without a refcnt inc) to the scalar that is */
/* being destroyed, so it'll contain random values later. */
if (imp_xxh)
- DBIc_MY_H(imp_xxh) = (void*)SvRV(mg->mg_obj); /* inner (untied)
HV */
+ DBIc_MY_H(imp_xxh) = (HV*)SvRV(mg->mg_obj); /* inner (untied)
HV */
XSRETURN(0);
}
Modified: dbi/trunk/lib/DBD/Gofer/Transport/Base.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer/Transport/Base.pm (original)
+++ dbi/trunk/lib/DBD/Gofer/Transport/Base.pm Wed Apr 11 08:57:46 2007
@@ -31,6 +31,10 @@
local $SIG{ALRM} = sub { die "TIMEOUT\n" } if $to;
my $info = eval {
+ local $SIG{PIPE} = sub {
+ my $extra = ($! eq "Broken pipe") ? "" : " ($!)";
+ die "Unable to send request: Broken pipe$extra\n";
+ };
alarm($to) if $to;
$self->transmit_request_by_transport($request);
};
Modified: dbi/trunk/lib/DBD/Gofer/Transport/null.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer/Transport/null.pm (original)
+++ dbi/trunk/lib/DBD/Gofer/Transport/null.pm Wed Apr 11 08:57:46 2007
@@ -23,24 +23,16 @@
my $executor = DBI::Gofer::Execute->new();
-sub transmit_request {
+sub transmit_request_by_transport {
my ($self, $request) = @_;
- my $frozen_request = $self->freeze_data($request);
+ my $frozen_request = $self->freeze_request($request);
# ...
# the request is magically transported over to ... ourselves
# ...
- # since we're in the same process, we don't want to show the DBI trace
- # enabled for the 'client' because it gets very hard to follow.
- # So control the Gofer 'server' side independently
- # but similar logic as used for DBI_TRACE parsing.
- #my $prev_trace_level = DBI->trace( ($ENV{DBD_GOFER_NULL_TRACE}) ? (split
/=/, $ENV{DBD_GOFER_NULL_TRACE}) : (0));
-
- my $response = $executor->execute_request(
$self->thaw_data($frozen_request,1) );
-
- #DBI->trace($prev_trace_level);
+ my $response = $executor->execute_request(
$self->thaw_request($frozen_request,1) );
# put response 'on the shelf' ready for receive_response()
$self->pending_response( $response );
@@ -49,18 +41,18 @@
}
-sub receive_response {
+sub receive_response_by_transport {
my $self = shift;
my $response = $self->pending_response;
- my $frozen_response = $self->freeze_data($response,1);
+ my $frozen_response = $self->freeze_response($response,1);
# ...
# the response is magically transported back to ... ourselves
# ...
- return $self->thaw_data($frozen_response);
+ return $self->thaw_response($frozen_response);
}
Modified: dbi/trunk/lib/DBD/Gofer/Transport/pipeone.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer/Transport/pipeone.pm (original)
+++ dbi/trunk/lib/DBD/Gofer/Transport/pipeone.pm Wed Apr 11 08:57:46 2007
@@ -70,7 +70,7 @@
my $pid = open3($wfh, $rfh, $efh, @$cmd)
or die "error starting @$cmd: $!\n";
if ($self->trace) {
- $self->trace_msg(sprintf("Started pid $pid: @$cmd {fd: w%d, r%d,
e%d}\n", fileno $wfh, fileno $rfh, fileno $efh),0);
+ $self->trace_msg(sprintf("Started pid $pid: @$cmd {fd: w%d r%d e%d,
ppid=$$}\n", fileno $wfh, fileno $rfh, fileno $efh),0);
}
nonblock($rfh);
nonblock($efh);
@@ -90,20 +90,21 @@
# XXX meant to return a properly shell-escaped string suitable for system
# but its only for debugging so that can wait
my $connection_info = $self->connection_info;
- return join " ", map { "'$_'" } @{$connection_info->{cmd}};
+ return join " ", map { (m/^[-:\w]*$/) ? $_ : "'$_'" }
@{$connection_info->{cmd}};
}
sub transmit_request_by_transport {
my ($self, $request) = @_;
- my $frozen_request = $self->freeze_data($request);
+ my $frozen_request = $self->freeze_request($request);
my $cmd = [ @{$self->go_perl}, qw(-MDBI::Gofer::Transport::pipeone -e
run_one_stdio)];
my $info = $self->start_pipe_command($cmd);
my $wfh = delete $info->{wfh};
# send frozen request
+ local $\;
print $wfh $frozen_request
or warn "error writing to @$cmd: $!\n";
# indicate that there's no more
@@ -117,6 +118,7 @@
sub read_response_from_fh {
my ($self, $fh_actions) = @_;
+ my $trace = $self->trace;
my $info = $self->connection_info || die;
my ($ios) = @{$info}{qw(ios)};
@@ -134,15 +136,20 @@
unless ($rv) { # error (undef) or end of file (0)
my $action;
unless (defined $rv) { # was an error
+ $self->trace_msg("error on handle $fh: $!") if $trace >= 4;
$action = $actions->{error} || $actions->{eof};
++$errors;
- # XXX an error may be a permenant condition of the handle
+ # XXX an error may be a permenent condition of the handle
# if so we'll loop here - not good
}
else {
$action = $actions->{eof};
+ $self->trace_msg("eof on handle $fh") if $trace >= 4;
+ }
+ if ($action->($fh)) {
+ $self->trace_msg("removing $fh from handle set") if $trace
>= 4;
+ $ios->remove($fh);
}
- $action->($fh) && $ios->remove($fh);
next;
}
# action returns true if the response is now complete
@@ -184,7 +191,7 @@
if not $frozen_response; # no output on stdout at all
# XXX need to be able to detect and deal with corruption
- my $response = $self->thaw_data($frozen_response);
+ my $response = $self->thaw_response($frozen_response);
if ($stderr_msg) {
# add stderr messages as warnings (for PrintWarn)
Modified: dbi/trunk/lib/DBD/Gofer/Transport/stream.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer/Transport/stream.pm (original)
+++ dbi/trunk/lib/DBD/Gofer/Transport/stream.pm Wed Apr 11 08:57:46 2007
@@ -11,7 +11,6 @@
use warnings;
use Carp;
-use Fcntl;
use base qw(DBD::Gofer::Transport::pipeone);
@@ -24,9 +23,6 @@
my $persist_all = 5;
my %persist;
-sub nonblock;
-
-
sub _connection_key {
my ($self) = @_;
@@ -41,7 +37,7 @@
$persist = $persist_all if not defined $persist;
my $key = ($persist) ? $self->_connection_key : '';
if ($persist{$key} && $self->_connection_check($persist{$key})) {
- DBI->trace_msg("reusing persistent connection $key\n",0) if
$self->trace >= 1;
+ $self->trace_msg("reusing persistent connection $key\n",0) if
$self->trace >= 1;
return $persist{$key};
}
@@ -60,7 +56,9 @@
my ($self, $connection) = @_;
$connection ||= $self->connection_info;
my $pid = $connection->{pid};
- return (kill 0, $pid);
+ my $ok = (kill 0, $pid);
+ $self->trace_msg("_connection_check: $ok (pid $$)\n",0) if $self->trace;
+ return $ok;
}
@@ -68,9 +66,10 @@
my ($self) = @_;
my $connection = $self->connection_info;
my ($pid, $wfh, $rfh, $efh) = @{$connection}{qw(pid wfh rfh efh)};
+ $self->trace_msg("_connection_kill: closing write handle\n",0) if
$self->trace;
# closing the write file handle should be enough, generally
close $wfh;
- # in code cases in future we may want to be more aggressive
+ # in future we may want to be more aggressive
#close $rfh; close $efh; kill 15, $pid
# but deleting from the persist cache...
delete $persist{ $self->_connection_key };
@@ -99,19 +98,19 @@
unshift @$cmd, qw(ssh -xq), split(' ', $ssh), qw(bash -c), $setup;
}
- DBI->trace_msg("new connection: @$cmd\n",0) if $self->trace;
+ $self->trace_msg("new connection: @$cmd\n",0) if $self->trace;
# XXX add a handshake - some message from DBI::Gofer::Transport::stream
that's
# sent as soon as it starts that we can wait for to report success - and
soak up
# and report useful warnings etc from ssh before we get it? Increases
latency though.
my $connection = $self->start_pipe_command($cmd);
- nonblock($connection->{efh});
return $connection;
}
sub transmit_request_by_transport {
my ($self, $request) = @_;
+ my $trace = $self->trace;
my $connection = $self->connection_info || do {
my $con = $self->_connection_get;
@@ -119,18 +118,22 @@
$con;
};
- my $frozen_request = unpack("H*", $self->freeze_data($request));
- $frozen_request .= "\015\012";
+ my $encoded_request = unpack("H*", $self->freeze_request($request));
+ $encoded_request .= "\015\012";
my $wfh = $connection->{wfh};
+ $self->trace_msg(sprintf("transmit_request_by_transport: to fh %s fd%d\n",
$wfh, fileno($wfh)),0)
+ if $trace >= 4;
+
# send frozen request
- print $wfh $frozen_request # autoflush enabled
+ local $\;
+ print $wfh $encoded_request # autoflush enabled
or do {
# XXX should make new connection and retry
$self->_connection_kill;
die "Error sending request: $!";
};
- $self->trace_msg("Request: $frozen_request\n",0) if $self->trace >= 4;
+ $self->trace_msg("Request sent: $encoded_request\n",0) if $trace >= 4;
return;
}
@@ -138,14 +141,13 @@
sub receive_response_by_transport {
my $self = shift;
+ my $trace = $self->trace;
+ $self->trace_msg("receive_response_by_transport: awaiting response\n",0)
if $trace >= 4;
my $connection = $self->connection_info || die;
my ($pid, $rfh, $efh, $cmd) = @{$connection}{qw(pid rfh efh cmd)};
- # blocks till a newline has been read
- $! = 0;
-
- my $errno;
+ my $errno = 0;
my $frozen_response;
my $stderr_msg;
@@ -166,25 +168,31 @@
# probably exited, possibly with an error to stderr.
# Turn this situation into a reasonably useful DBI error.
if (not $frozen_response) {
- chomp $stderr_msg if $stderr_msg;
- my $msg = sprintf("Error reading from %s (pid %d%s): ",
- $self->cmd_as_string, $pid, (kill 0, $pid) ? "" : ", exited");
- $msg .= $stderr_msg || $errno || "(no error message)";
+ my $msg = "No response received";
+ if (chomp $stderr_msg && $stderr_msg) {
+ $msg .= sprintf ", error reported by \"%s\" (pid %d%s): %s",
+ $self->cmd_as_string,
+ $pid, ((kill 0, $pid) ? "" : ", exited"),
+ $stderr_msg;
+ }
+ else {
+ $msg .= ($errno) ? ", error while reading response: $errno" : "(no
error message)";
+ }
die "$msg\n";
}
- $self->trace_msg("Response: $frozen_response\n",0)
- if $self->trace >= 4;
+ $self->trace_msg("Response received: $frozen_response\n",0)
+ if $trace >= 4;
$self->trace_msg("Gofer stream stderr message: $stderr_msg\n",0)
- if $stderr_msg && $self->trace;
+ if $stderr_msg && $trace;
# XXX need to be able to detect and deal with corruption
- my $response = $self->thaw_data(pack("H*",$frozen_response));
+ my $response = $self->thaw_response(pack("H*",$frozen_response));
if ($stderr_msg) {
# add stderr messages as warnings (for PrintWarn)
- $response->add_err(0, $stderr_msg, undef, $self->trace)
+ $response->add_err(0, $stderr_msg, undef, $trace)
# but ignore warning from old version of blib
unless $stderr_msg =~ /^Using .*blib/ && "@$cmd" =~ /-Mblib/;
}
@@ -198,16 +206,6 @@
return $self->SUPER::transport_timedout(@_);
}
-
-# nonblock($fh) puts filehandle into nonblocking mode
-sub nonblock {
- my $fh = shift;
- my $flags = fcntl($fh, F_GETFL, 0)
- or croak "Can't get flags for filehandle $fh: $!";
- fcntl($fh, F_SETFL, $flags | O_NONBLOCK)
- or croak "Can't make filehandle $fh nonblocking: $!";
-}
-
1;
__END__
Modified: dbi/trunk/lib/DBI/Gofer/Execute.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Execute.pm (original)
+++ dbi/trunk/lib/DBI/Gofer/Execute.pm Wed Apr 11 08:57:46 2007
@@ -18,10 +18,17 @@
our $VERSION = sprintf("0.%06d", q$Revision$ =~ /(\d+)/o);
-our $local_log = $ENV{DBI_GOFER_TRACE} || $ENV{DBI_GOFER_LOCAL_LOG};
our @all_dbh_methods = sort map { keys %$_ } $DBI::DBI_methods{db},
$DBI::DBI_methods{common};
our %all_dbh_methods = map { $_ => DBD::_::db->can($_) } @all_dbh_methods;
+our $local_log = $ENV{DBI_GOFER_LOCAL_LOG}; # do extra logging to stderr
+
+# set trace for server-side gofer
+# Could use DBI_TRACE env var when it's an unrelated separate process
+# but using DBI_GOFER_TRACE makes testing easier for subprocesses (eg stream)
+DBI->trace(split /=/, $ENV{DBI_GOFER_TRACE}, 2) if $ENV{DBI_GOFER_TRACE};
+
+
__PACKAGE__->mk_accessors(qw(
check_connect
default_connect_dsn
@@ -104,12 +111,6 @@
);
-# set trace for server-side gofer
-# Could use DBI_TRACE env var when it's a separate process
-# but using DBI_GOFER_TRACE makes testing easier (e.g., with null transport)
-DBI->trace(split /=/, $ENV{DBI_GOFER_TRACE}, 2) if $ENV{DBI_GOFER_TRACE};
-
-
sub _connect {
my ($self, $request) = @_;
Modified: dbi/trunk/lib/DBI/Gofer/Transport/Base.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Transport/Base.pm (original)
+++ dbi/trunk/lib/DBI/Gofer/Transport/Base.pm Wed Apr 11 08:57:46 2007
@@ -23,7 +23,8 @@
));
-sub _init_trace { $ENV{DBI_GOFER_TRACE} || 0 }
+# see also $ENV{DBI_GOFER_TRACE} in DBI::Gofer::Execute
+sub _init_trace { (split(/=/,$ENV{DBI_GOFER_TRACE}||0))[0] }
sub new {
@@ -31,14 +32,20 @@
$args->{trace} ||= $class->_init_trace;
my $self = bless {}, $class;
$self->$_( $args->{$_} ) for keys %$args;
+ $self->trace_msg("$class->new({ @{[ %$args ]} })\n") if $self->trace;
return $self;
}
-sub freeze_data {
- my ($self, $data, $skip_trace) = @_;
- $self->_dump("freezing ".ref($data), $data)
+sub freeze_request { return shift->_freeze_data("request", @_) }
+sub freeze_response { return shift->_freeze_data("response", @_) }
+sub thaw_request { return shift->_thaw_data("request", @_) }
+sub thaw_response { return shift->_thaw_data("response", @_) }
+
+sub _freeze_data {
+ my ($self, $what, $data, $skip_trace) = @_;
+ $self->_dump("freezing $self->{trace} ".ref($data), $data)
if !$skip_trace and $self->trace;
local $Storable::forgive_me = 1; # for CODE refs etc
my $frozen = eval { nfreeze($data) };
@@ -49,17 +56,18 @@
return $frozen;
}
-sub thaw_data {
- my ($self, $frozen_data, $skip_trace) = @_;
+sub _thaw_data {
+ my ($self, $what, $frozen_data, $skip_trace) = @_;
my $data = eval { thaw($frozen_data) };
if ($@) {
chomp(my $err = $@);
- my $msg = "Error thawing object: $err";
- Carp::cluck("$msg - stack trace:"); # XXX disable later
- $self->_dump("thaw failed for", $frozen_data);
+ # remove extra noise from Storable
+ $err =~ s{ at \S+?/Storable.pm \(autosplit into
\S+?/Storable/thaw.al\) line \d+(, \S+ line \d+)?}{};
+ my $msg = sprintf "Error thawing $what: %s (data=%s)", $err,
DBI::neat($frozen_data,50);
+ Carp::cluck("$msg, pid $$ stack trace follows:"); # XXX if
$self->trace;
die $msg;
}
- $self->_dump("thawing ".ref($data), $data)
+ $self->_dump("thawing $self->{trace} ".ref($data), $data)
if !$skip_trace and $self->trace;
return $data;
}
Modified: dbi/trunk/lib/DBI/Gofer/Transport/pipeone.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Transport/pipeone.pm (original)
+++ dbi/trunk/lib/DBI/Gofer/Transport/pipeone.pm Wed Apr 11 08:57:46 2007
@@ -22,13 +22,13 @@
sub run_one_stdio {
- my $self = DBI::Gofer::Transport::pipeone->new();
+ my $transport = DBI::Gofer::Transport::pipeone->new();
my $frozen_request = do { local $/; <STDIN> };
- my $response = $executor->execute_request(
$self->thaw_data($frozen_request) );
+ my $response = $executor->execute_request(
$transport->thaw_request($frozen_request) );
- my $frozen_response = $self->freeze_data($response);
+ my $frozen_response = $transport->freeze_response($response);
print $frozen_response;
}
Modified: dbi/trunk/lib/DBI/Gofer/Transport/stream.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Transport/stream.pm (original)
+++ dbi/trunk/lib/DBI/Gofer/Transport/stream.pm Wed Apr 11 08:57:46 2007
@@ -22,21 +22,24 @@
sub run_stdio_hex {
- my $self = DBI::Gofer::Transport::stream->new();
+ my $transport = DBI::Gofer::Transport::stream->new();
local $| = 1;
- #warn "STARTED $$";
+ DBI->trace_msg("$0 started (pid $$)\n");
- while ( my $frozen_request = <STDIN> ) {
- $frozen_request =~ s/\015?\012$//;
+ local $/;
+ local $\ = "\012";
+ while ( defined( my $encoded_request = <STDIN> ) ) {
+ $encoded_request =~ s/\015?\012$//;
- my $request = $self->thaw_data( pack "H*", $frozen_request );
+ my $request = $transport->thaw_request( pack "H*", $encoded_request );
my $response = $executor->execute_request( $request );
- my $frozen_response = unpack "H*", $self->freeze_data($response);
+ my $encoded_response = unpack "H*",
$transport->freeze_response($response);
- print $frozen_response, "\015\012"; # autoflushed due to $|=1
+ print $encoded_response, "\015\012"; # autoflushed due to $|=1
}
+ DBI->trace_msg("$0 ending (pid $$)\n");
}
1;
Modified: dbi/trunk/lib/DBI/ProfileDumper.pm
==============================================================================
--- dbi/trunk/lib/DBI/ProfileDumper.pm (original)
+++ dbi/trunk/lib/DBI/ProfileDumper.pm Wed Apr 11 08:57:46 2007
@@ -192,7 +192,7 @@
$self->write_data($fh, $self->{Data}, 1);
- close($fh) or croak("Unable to close '$self->{File}': $!");
+ close($fh) or croak("Error closing '$self->{File}': $!");
$self->empty();
}
Modified: dbi/trunk/lib/DBI/ProfileSubs.pm
==============================================================================
--- dbi/trunk/lib/DBI/ProfileSubs.pm (original)
+++ dbi/trunk/lib/DBI/ProfileSubs.pm Wed Apr 11 08:57:46 2007
@@ -22,9 +22,10 @@
use warnings;
-# would be good to refactor these regex into separate subs or find some other
-# way to compose them in various combinations into multiple subs
-# The final subs always been to be vert fast.
+# would be good to refactor these regex into separate subs and find some
+# way to compose them in various combinations into multiple subs.
+# Perhaps via AUTOLOAD where \&auto_X_Y_Z creates a sub that does X, Y, and Z.
+# The final subs always need to be very fast.
#
sub norm_std_n3 {