Author: timbo
Date: Tue May 29 07:23:53 2007
New Revision: 9619

Modified:
   dbi/trunk/Changes
   dbi/trunk/lib/DBI/ProfileData.pm
   dbi/trunk/lib/DBI/ProfileDumper.pm

Log:
Added DeleteFiles option to delete files once read.
Locks the data files while reading.


Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes   (original)
+++ dbi/trunk/Changes   Tue May 29 07:23:53 2007
@@ -47,9 +47,9 @@
 
   DBI::ProfileDumper changes:
     Don't write file if there's no profile data.
-    Use full natural precision when saving data (was using %.6f)
+    Uses full natural precision when saving data (was using %.6f)
     Optimized flush_to_disk().
-    Lock the data file while writing.
+    Locks the data file while writing.
     Added $profile->filename method.
     Enabled filename to be a code ref for dynamic names.
   DBI::ProfileDumper::Apache changes:
@@ -58,6 +58,8 @@
     Enabled DBI_PROFILE_APACHE_LOG_DIR for mod_perl 1 as well as 2.
     Added parent pid to default data file name.
   DBI::ProfileData changes:
+    Added DeleteFiles option to delete files once read.
+    Locks the data files while reading.
     Added ability to sort by Path elements.
   dbiprof changes:
     Added --dumpnodes option.

Modified: dbi/trunk/lib/DBI/ProfileData.pm
==============================================================================
--- dbi/trunk/lib/DBI/ProfileData.pm    (original)
+++ dbi/trunk/lib/DBI/ProfileData.pm    Tue May 29 07:23:53 2007
@@ -17,7 +17,7 @@
   # load data from dbi.prof
   $prof = DBI::ProfileData->new(File => "dbi.prof");
 
-  # get a count of the records in the data set
+  # get a count of the records (unique paths) in the data set
   $count = $prof->count();
 
   # sort by longest overall time
@@ -67,8 +67,6 @@
 
 The following methods are supported by DBI::ProfileData objects.
 
-=over 4
-
 =cut
 
 
@@ -76,6 +74,7 @@
 
 use Carp qw(croak);
 use Symbol;
+use Fcntl qw(:flock);
 
 use DBI::Profile qw(dbi_profile_merge);
 
@@ -89,17 +88,33 @@
 sub LAST_AT   () { 6 };
 sub PATH      () { 7 };
 
-=item $prof = DBI::ProfileData->new(File => "dbi.prof")
+=head2 $prof = DBI::ProfileData->new(File => "dbi.prof")
 
-=item $prof = DBI::ProfileData->new(File => "dbi.prof", Filter => sub { ... })
+=head2 $prof = DBI::ProfileData->new(File => "dbi.prof", Filter => sub { ... })
 
-=item $prof = DBI::ProfileData->new(Files => [ "dbi.prof.1", "dbi.prof.2" ])
+=head2 $prof = DBI::ProfileData->new(Files => [ "dbi.prof.1", "dbi.prof.2" ])
 
 Creates a a new DBI::ProfileData object.  Takes either a single file
 through the File option or a list of Files in an array ref.  If
 multiple files are specified then the header data from the first file
 is used.
 
+=head3 Files
+
+Reference to an array of file names to read.
+
+=head3 File
+
+Name of file to read. Takes precedence over C<Files>.
+
+=head3 DeleteFiles
+
+If true, the files are deleted after being read. (Actually the files are
+renamed first which, together with locking, avoids problems if other
+applications are writing to the file.)
+
+=head3 Filter
+
 The C<Filter> parameter can be used to supply a code reference that can
 manipulate the profile data as it is being read. This is most useful for
 editing SQL statements so that slightly different statements in the raw data
@@ -141,6 +156,7 @@
     my $self = {                
                 Files        => [ "dbi.prof" ],
                Filter       => undef,
+                DeleteFiles  => 0,
                 _header      => {},
                 _nodes       => [],
                 _node_lookup => {},
@@ -149,7 +165,7 @@
                };
     bless $self, $pkg;
     
-    # File overrides Files
+    # File (singular) overrides Files (plural)
     $self->{Files} = [ $self->{File} ] if exists $self->{File};
 
     $self->_read_files();
@@ -159,18 +175,33 @@
 # read files into _header and _nodes
 sub _read_files {
     my $self = shift;
-    my $files = $self->{Files};
+    my $files  = $self->{Files};
     my $read_header = 0;
-    
-    foreach my $filename (@$files) {
-        my $fh = gensym;
-        open($fh, $filename)
+  
+    my $fh = gensym;
+    foreach (@$files) {
+        my $filename = $_;
+        if ($self->{DeleteFiles}) {
+            my $newfilename = $filename . ".deleteme";
+            rename($filename, $newfilename)
+                or croak "Can't rename($filename, $newfilename): $!";
+            $filename = $newfilename;
+        }
+        open($fh, "<", $filename)
           or croak("Unable to read profile file '$filename': $!");
-        
-        $self->_read_header($fh, $filename, $read_header ? 0 : 1);
-        $read_header = 1;
-        $self->_read_body($fh, $filename);
-        close($fh);
+
+        # lock the file in case it's still being written to
+        # (we'll be foced to wait till the write is complete)
+        flock($fh, LOCK_SH);
+
+        if (-s $fh) {   # not empty
+            $self->_read_header($fh, $filename, $read_header ? 0 : 1);
+            $read_header = 1;
+            $self->_read_body($fh, $filename);
+        }
+        close($fh); # and release lock
+        unlink $filename or warn "Can't delete '$filename': $!"
+            if $self->{DeleteFiles};
     }
     
     # discard node_lookup now that all files are read
@@ -270,7 +301,7 @@
 
 
 
-=item $copy = $prof->clone();
+=head2 $copy = $prof->clone();
 
 Clone a profile data set creating a new object.
 
@@ -291,7 +322,7 @@
     return $clone;
 }
 
-=item $header = $prof->header();
+=head2 $header = $prof->header();
 
 Returns a reference to a hash of header values.  These are the key
 value pairs included in the header section of the DBI::ProfileDumper
@@ -310,7 +341,7 @@
 sub header { shift->{_header} }
 
 
-=item $nodes = $prof->nodes()
+=head2 $nodes = $prof->nodes()
 
 Returns a reference the sorted nodes array.  Each element in the array
 is a single record in the data set.  The first seven elements are the
@@ -340,7 +371,8 @@
 
 sub nodes { shift->{_nodes} }
 
-=item $count = $prof->count()
+
+=head2 $count = $prof->count()
 
 Returns the number of items in the profile data set.
 
@@ -348,9 +380,10 @@
 
 sub count { scalar @{shift->{_nodes}} }
 
-=item $prof->sort(field => "field")
 
-=item $prof->sort(field => "field", reverse => 1)
+=head2 $prof->sort(field => "field")
+
+=head2 $prof->sort(field => "field", reverse => 1)
 
 Sorts data by the given field.  Available fields are:
 
@@ -407,11 +440,12 @@
     }
 }
 
-=item $count = $prof->exclude(key2 => "disconnect")
 
-=item $count = $prof->exclude(key2 => "disconnect", case_sensitive => 1)
+=head2 $count = $prof->exclude(key2 => "disconnect")
 
-=item $count = $prof->exclude(key1 => qr/^SELECT/i)
+=head2 $count = $prof->exclude(key2 => "disconnect", case_sensitive => 1)
+
+=head2 $count = $prof->exclude(key1 => qr/^SELECT/i)
 
 Removes records from the data set that match the given string or
 regular expression.  This method modifies the data in a permanent
@@ -458,11 +492,11 @@
 }
 
 
-=item $count = $prof->match(key2 => "disconnect")
+=head2 $count = $prof->match(key2 => "disconnect")
 
-=item $count = $prof->match(key2 => "disconnect", case_sensitive => 1)
+=head2 $count = $prof->match(key2 => "disconnect", case_sensitive => 1)
 
-=item $count = $prof->match(key1 => qr/^SELECT/i)
+=head2 $count = $prof->match(key1 => qr/^SELECT/i)
 
 Removes records from the data set that do not match the given string
 or regular expression.  This method modifies the data in a permanent
@@ -508,7 +542,8 @@
     return scalar @$nodes;
 }
 
-=item $Data = $prof->Data()
+
+=head2 $Data = $prof->Data()
 
 Returns the same Data hash structure as seen in DBI::Profile.  This
 structure is not sorted.  The nodes() structure probably makes more
@@ -535,7 +570,8 @@
     return \%Data;
 }
 
-=item $text = $prof->format($nodes->[0])
+
+=head2 $text = $prof->format($nodes->[0])
 
 Formats a single node into a human-readable block of text.
 
@@ -585,7 +621,8 @@
     }
 }
 
-=item $text = $prof->report(number => 10)
+
+=head2 $text = $prof->report(number => 10)
 
 Produces a report with the given number of items.
 
@@ -650,8 +687,6 @@
 
 __END__
 
-=back
-
 =head1 AUTHOR
 
 Sam Tregar <[EMAIL PROTECTED]>

Modified: dbi/trunk/lib/DBI/ProfileDumper.pm
==============================================================================
--- dbi/trunk/lib/DBI/ProfileDumper.pm  (original)
+++ dbi/trunk/lib/DBI/ProfileDumper.pm  Tue May 29 07:23:53 2007
@@ -226,11 +226,11 @@
     if (($self->{_wrote_header}||'') eq $filename) {
         # append more data to the file
         # XXX assumes that Path hasn't changed
-        open($fh, ">>$filename") 
+        open($fh, ">>", $filename) 
           or croak("Unable to open '$filename' for $class output: $!");
     } else {
-        # create new file (overwrite existing)
-        open($fh, ">$filename") 
+        # create new file (or overwrite existing)
+        open($fh, ">", $filename) 
           or croak("Unable to open '$filename' for $class output: $!");
     }
     # lock the file (before checking size and writing the header)

Reply via email to