An easy way to view maintenance logs using a browser using Perl & Mason

stats/index.html:

 < %method title>
  DBServices: Update Statistics Logs
 
 <center>
 <h1>Update Statistics Logs</h1>
 < & ‘../.components/ase/maint_logs.comp’, path => "/dbms/sybase/dba/out", file_part => "update_stats" &>
  </center>

stats/dhandler:

  < %perl>
   my $self = shift;
   
   $self->{once_header} = ”;
   $self->{header} = ”;
   $self->{body} = ”;
   $self->{footer} = ”;
   $self->{current_block} = ”;

   my $log_path = ‘/dbms/sybase/dba/out/’;
   my $file = $m->dhandler_arg;

   $file =~ s/\.html$//;

   if ($file =~ m/\.out$/) {
     if (-f $log_path . $file) {
       my $FH;
       if (open($FH, "< ", $log_path . $file)) {
         while (my $line = < $FH>) {
           $m->print($line);
         }
       } else {
         $m->abort(404);
       }
     } else {
       $m->abort(404);
     }
   } elsif ($file =~ m/\.gz$/) {
     if (-f $log_path . $file) {
       my $gFH;
       use Compress::Zlib;
       if ( my $gFH = gzopen($log_path . $file, "rb") ) {
         while ($gFH->gzreadline($_) > 0 ) {
           $m->print($_);
         }
         $gFH->gzclose;
       } else {
         $m->abort(404);
       }
     } else {
       $m->abort(404);
     }
   }

../.components/ase/maint_logs.comp:

  < %args>
   $path
   $file_part
 
 < %perl>
   use File::Find;
   our $part = $file_part;
   our %log_hash = ();
  sub wanted {
     return unless (/$part/);
     my $file_name = $_;
     if ($file_name =~ /$part\_(.+)\.out$/) {
       $log_hash{$1}{current} = $file_name;
     } elsif ($file_name =~ m/$part\_(.+)\.out\.(\d+)\.gz$/) {
       if ($1 && $2) {
         $log_hash{$1}{archive}{$2} = {
           file_name  => $file_name,
           file_date  => scalar localtime( (stat($File::Find::name))[9] )
         };
       }
     }
   }
   find(\&wanted, $path);
   $m->comp(‘.print_table_head’);
   foreach my $server (sort { lc($a) cmp lc($b) } keys %log_hash) {
     $m->comp(‘.print_table’,
       server     => $server,
       current_log    => $log_hash{$server}{current},
       archive_ref    => \%{ $log_hash{$server}{archive} }
     );
   }
   $m->comp(‘.print_table_tail’);
 
 < %def .print_table_head>
 <table BORDER=1 BORDERCOLOR="BLACK">
   <th>Server</th>
   <th>Current Log</th>
   <th>Archived Logs</th>
 
 < %def .print_table>
   < %args>
     $server
     $current_log
     $archive_ref
   
   <tr>
     <td>< % $server %></td>
     <td>< % sprintf "<a href=’%s’>%s", $current_log . ".html", $current_log %></td>
     <td>< %perl>
         my $str = "";

         foreach my $archive_num (sort { $a < => $b } keys %$archive_ref ) {
           $str .= sprintf "<a href=’%s’>%s</a> (%s)",
             $archive_ref->{$archive_num}{file_name} . ".html",
             $archive_ref->{$archive_num}{file_name},
             $archive_ref->{$archive_num}{file_date};
         }
         $m->print($str);
     </td>
   </tr>
 
 < %def .print_table_tail>
 </table>
Share Button

Perl Problem with filtered Mason code & db connection

Hi,

In chapter 5 (Advanced Features pgs 82,83) of Embedding Perl in HTML with Mason from O’Reilly, the"a simple SQL select expressed in something like a taglib style" example appears to be straight forward.  It is but it doesn’t seem to work too well.

The premise is that the ".components/sql/select" will filter the chunk of html code:

< &| .components/sql/select, query => 'SELECT name, type FROM sysobjects' &>
  <tr>
     <td>%name</td>
     <td>%type</td>
  </tr>

The select returns data correctly but the ".components/sql/select" doesn’t appear to be printing the code hmmmm….  see the very bottom for the answer… I didn’t catch it for awhile but later saw the cause and could have kicked myself.

produced HTML code:

<html>
<head>
  <title> Databases</title>
</head>
<body>
   <table border="1">
 	<tr>
 		<th>Server</th><th>Service Type</th>
	</tr>
    </table>

    <center><img src="/images/seal.png" height="170" width="170"/></center>
</body>
</html>

test.html:

<table border="1">
    <tr>
        <th>Server</th>
        <th>Service Type</th>
    </tr>
    < &| .components/sql/select, query => ‘SELECT name, type FROM sysobjects’ &>
        <tr>
            <td>%name</td>
            <td>%type</td>
        </tr>
    
</table>

.components/sql/select:

    < %args>
        $query
    
    < %init>
        my $sth = $dbh->prepare($query);

        while (my $row = $sth->fetchrow_hashref) {
            my $content = $m->content;

            $content =~ s/%(w+)/$row->{$1}/g;
            $m->print($content);
        }

        $sth->finish;

Solution:

     < %init>
        my $sth = $dbh->prepare($query);

        while (my $row = $sth->fetchrow_hashref) {

should be:

    < %init>
        my $sth = $dbh->prepare($query);

        $sth->execute();  # dang typos in the book Cry

        while (my $row = $sth->fetchrow_hashref) {
Share Button

Using Perl, Mason, mod_perl and DBI: Result sets

I’m new to Mason and am having trouble printing a simple html table pulling data from a table on a database.  I know this has to do with scope but there has to be an easier way other than putting the entire dbms call (including printing the table) within a perl code section.

One thing I have noticed is the apparent lack of any useful information of using Mason with DBI connections.

This is how you do it if you wanted a single file to connect to the dbms and then spit out the result set:

< %shared>
    my %serverDump;

    my $dbh = DBI->connect("dbi:Sybase:server=mydb", ‘info’, ‘infopwd’, { RaiseError => 1, PrintError => 1 } );
    $dbh->do("use sybase_dba");

    my $query = "select serverName, min(dumpdate) from dbLastBackup group by serverName";

    my $sth = $dbh->prepare($query);
    $sth->execute or die "Error: unable to run query! " . $dbh->errstr;
    
<table Border=1>
  % while (my $row = $sth->fetchrow_arrayref ) {

    <tr>
      <td>< % $row->[0] %></td><td>< % $row->[1] %></td>
    </tr>

  % }
</table>

Note, don’t forget to uncomment "PerlSetVar MasonErrorMode fatal".  For some reason, no errors were being sent to the browser. 🙁

 

Share Button