Author: arkurth
Date: Tue Apr 19 14:33:29 2011
New Revision: 1095103

URL: http://svn.apache.org/viewvc?rev=1095103&view=rev
Log:
VCL-452
Updated Linux.pm::get_file_size. It now returns the size used on disk by a file 
which should allow the size of vmdk files to be reported correctly.

Modified:
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=1095103&r1=1095102&r2=1095103&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Tue Apr 19 
14:33:29 2011
@@ -1947,10 +1947,21 @@ sub copy_file {
 =head2 get_file_size
 
  Parameters  : $file_path
- Returns     : integer
+ Returns     : integer or array
  Description : Determines the size of the file specified by the file path
-               argument in bytes. The file path argument may contain wildcards.
-                                       If the path argument is a directory, 0 
will be returned.
+               argument in bytes. The file path argument may be a directory or
+               contain wildcards. Directories are processed recursively.
+               
+               When called in sclar context, the actual bytes used on the disk 
by the file
+               is returned. This correlates to the size reported by the `du`
+               command. This value is not the same as what is reported by the 
`ls`
+               command. This is important when determining the size of
+               compressed files or thinly-provisioned virtual disk images.
+               
+               When called in array context, 3 values are returned:
+               [0] bytes used (`du` size)
+               [1] bytes reserved (`ls` size)
+               [2] file count
 
 =cut
 
@@ -1961,6 +1972,8 @@ sub get_file_size {
                return;
        }
        
+       my $calling_sub = (caller(1))[3] || '';
+       
        # Get the path argument
        my $file_path = shift;
        if (!$file_path) {
@@ -1978,14 +1991,23 @@ sub get_file_size {
        my $computer_node_name = $self->data->get_computer_node_name() || 
return;
        
        # Run stat rather than du because du is not available on VMware ESX
-       my $command = 'stat -c "%F:%s:%b:%B:%n" ' . $escaped_file_path;
+       # -L     Dereference links
+       # %F     File type
+       # %n     File name
+       # %b     Number of blocks allocated (see %B)
+       # %B     The size in bytes of each block reported by %b
+       # %s     Total size, in bytes
+       
+       my $command = 'stat -L -c "%F:%n:%s:%b:%B" ' . $escaped_file_path;
        my ($exit_status, $output) = $self->execute($command);
        if (!defined($output)) {
                notify($ERRORS{'WARNING'}, 0, "failed to run command to 
determine file size on $computer_node_name: $file_path\ncommand: '$command'");
                return;
        }
        elsif (grep(/no such file/i, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "unable to determine size of file 
on $computer_node_name because it does not exist: $file_path, command: 
'$command'");
+               if ($calling_sub !~ /get_file_size/) {
+                       notify($ERRORS{'DEBUG'}, 0, "unable to determine size 
of file on $computer_node_name because it does not exist: $file_path\ncommand: 
'$command'");
+               }
                return;
        }
        elsif (grep(/^stat:/i, @$output)) {
@@ -1994,11 +2016,12 @@ sub get_file_size {
        }
        
        # Loop through the stat output lines
+       my $file_count = 0;
+       my $total_bytes_reserved = 0;
        my $total_bytes_used = 0;
-       my $total_bytes_allocated = 0;
        for my $line (@$output) {
                # Take the stat output line apart
-               my ($type, $file_bytes, $file_blocks, $block_size, $path) = 
split(/:/, $line);
+               my ($type, $path, $file_bytes, $file_blocks, $block_size) = 
split(/:/, $line);
                if (!defined($type) || !defined($file_bytes) || 
!defined($file_blocks) || !defined($block_size) || !defined($path)) {
                        notify($ERRORS{'WARNING'}, 0, "unexpected output 
returned from stat, line: $line\ncommand: $command\noutput:\n" . join("\n", 
@$output));
                        return;
@@ -2006,27 +2029,41 @@ sub get_file_size {
                
                # Add the size to the total if the type is file
                if ($type =~ /file/) {
-                       $total_bytes_allocated += ($file_blocks * $block_size);
-                       $total_bytes_used += $file_bytes;
+                       $file_count++;
+                       
+                       my $file_bytes_allocated = ($file_blocks * $block_size);
+                       
+                       $total_bytes_used += $file_bytes_allocated;
+                       $total_bytes_reserved += $file_bytes;
+                       
+                       #print "$file_count: '$path', used: $file_bytes, 
allocated: $file_bytes_allocated, ($file_blocks * $block_size)\n";
                }
                elsif ($type =~ /directory/) {
                        $path =~ s/[\\\/\*]+$//g;
-                       notify($ERRORS{'DEBUG'}, 0, "recursively retrieving 
size of files under directory: '$path'");
-                       my ($subdirectory_bytes_used, 
$subdirectory_bytes_allocated) = $self->get_file_size("$path/*");
-                       $total_bytes_used += $subdirectory_bytes_used;
-                       $total_bytes_allocated += $subdirectory_bytes_allocated;
+                       #notify($ERRORS{'DEBUG'}, 0, "recursively retrieving 
size of files under directory: '$path'");
+                       my ($subdirectory_bytes_allocated, 
$subdirectory_bytes_used, $subdirectory_file_count) = 
$self->get_file_size("$path/*");
+                       
+                       # Values will be null if there are no files under the 
subdirectory
+                       if (!defined($subdirectory_bytes_allocated)) {
+                               next;
+                       }
+                       
+                       $file_count += $subdirectory_file_count;
+                       $total_bytes_reserved += $subdirectory_bytes_used;
+                       $total_bytes_used += $subdirectory_bytes_allocated;
                }
        }
        
        my $calling_sub = (caller(1))[3] || '';
        if ($calling_sub !~ /get_file_size/) {
                notify($ERRORS{'DEBUG'}, 0, "size of '$file_path' on 
$computer_node_name:\n" .
-                                "used: " . 
get_file_size_info_string($total_bytes_used) . "\n" .
-                                "allocated: " . 
get_file_size_info_string($total_bytes_allocated));
+                                "file count: $file_count\n" .
+                                "reserved: " . 
get_file_size_info_string($total_bytes_reserved) . "\n" .
+                                "used: " . 
get_file_size_info_string($total_bytes_used));
        }
        
        if (wantarray) {
-               return ($total_bytes_used, $total_bytes_allocated);
+               return ($total_bytes_used, $total_bytes_reserved, $file_count);
        }
        else {
                return $total_bytes_used;


Reply via email to