# Copyright 1999-2015. Parallels IP Holdings GmbH. All Rights Reserved.
package Storage::Counter;

#
# This 'filter' counts the size of piped through data and
# reports to the control file descriptor
#

#
# Note: this counter will only work correctly on
# the passed data size < 2^49 bytes (512 Tb) due to
# limited precision of Perl numbers
# (IEEE floating point in fact).
#

use strict;
use IO::Handle;
use POSIX;

use vars qw|$blocksize|;
my $blocksize = 4096;

my $controlFh;

sub init {
  my ($controlFd) = @_;
  $controlFh = IO::Handle->new_from_fd($controlFd, "w")
    or die "Unable to open 'control' filehandle in size counter";
}

sub run {
  my $block;
  my $passSize = 0;

  binmode STDIN;
  binmode STDOUT;

  while (my $blocklen = sysread(STDIN, $block, $blocksize)) {
    $passSize += $blocklen;

    my $offset = 0;
    do {
      my $written = syswrite(STDOUT, $block, $blocklen, $offset);
      if (!defined $written) {
        $controlFh->printf("ERR: %s\n", $!);
        $controlFh->close();
        POSIX::_exit(0);
      }
      $offset += $written;
      $blocklen -= $written;
    } while ($blocklen);
  }

  $controlFh->printf("%.0f", $passSize);
  $controlFh->close();

  POSIX::_exit(0);
}

1;

#
# Test: cat + stat :)
#
# Usage: perl Counter.pm < file
# Expected result: file on the stdout, size of file on the stderr
#
# init(2);
# run();
#
