diff options
Diffstat (limited to 'storage/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/IO.pm')
-rw-r--r-- | storage/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/IO.pm | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/storage/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/IO.pm b/storage/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/IO.pm new file mode 100644 index 00000000000..34f4d0a150d --- /dev/null +++ b/storage/ndb/tools/old_dirs/ndbnet/lib/NDB/Util/IO.pm @@ -0,0 +1,213 @@ +package NDB::Util::IO; + +use strict; +use Carp; + +require NDB::Util::Base; + +use vars qw(@ISA); +@ISA = qw(NDB::Util::Base); + +# constructors + +my $log; + +sub initmodule { + $log = NDB::Util::Log->instance; +} + +NDB::Util::IO->attributes( + readbuf => sub { defined }, + readend => sub { defined }, + writebuf => sub { defined }, + writeend => sub { defined }, + iosize => sub { $_ > 0 }, + timeout => sub { /^\d+$/ }, + fh => sub { ref($_) eq 'GLOB' && defined(fileno($_)) }, +); + +sub desc { + my $io = shift; + my $fileno = $io->hasfh ? fileno($io->getfh) : -1; + return "fd=$fileno"; +} + +sub new { + my $class = shift; + @_ % 2 == 0 or confess 0+@_; + my(%attr) = @_; + my $io = $class->SUPER::new(%attr); + $io->setreadbuf("") + or $log->push, return undef; + $io->setreadend(0) + or $log->push, return undef; + $io->setwritebuf("") + or $log->push, return undef; + $io->setwriteend(0) + or $log->push, return undef; + $io->setiosize(1024) + or $log->push, return undef; + $io->settimeout(0) + or $log->push, return undef; + if (defined($attr{fh})) { + $io->setfh($attr{fh}) + or $log->push, return undef; + } + return $io; +} + +# input / output + +sub read { + my $io = shift; + @_ == 0 or confess 0+@_; + if ($io->getreadend) { + return ""; + } + my $size = $io->getiosize; + my $timeout = $io->hastimeout ? $io->gettimeout : 0; + my $fh = $io->getfh; + my $n; + my $data; + eval { + if ($^O ne 'MSWin32' && $timeout > 0) { + local $SIG{ALRM} = sub { die("timed out\n") }; + alarm($timeout); + $n = sysread($fh, $data, $size); + alarm(0); + } + else { + $n = sysread($fh, $data, $size); + } + }; + if ($@) { + $log->put("read error: $@")->push($io); + return undef; + } + if (! defined($n)) { + $log->put("read failed: $!")->push($io); + return undef; + } + if ($n == 0) { + $io->setreadend(1) + or $log->push, return undef; + $log->put("read EOF")->push($io)->debug; + return ""; + } + (my $show = $data) =~ s!\n!\\n!g; + $log->put("read: $show")->push($io)->debug; + return $data; +} + +sub readbuf { + my $io = shift; + @_ == 0 or confess 0+@_; + my $data = $io->read; + defined($data) or + $log->push, return undef; + if (length($data) == 0) { + return 0; + } + $io->setreadbuf($io->getreadbuf . $data) + or $log->push, return undef; + return 1; +} + +sub readupto { + my $io = shift; + @_ == 1 or confess 0+@_; + my($code) = @_; + ref($code) eq 'CODE' or confess 'oops'; + my $k = &$code($io->getreadbuf); + if (! defined($k)) { + $log->push($io); + return undef; + } + if ($k == 0) { + my $n = $io->readbuf; + defined($n) or + $log->push, return undef; + if ($n == 0) { + if ($io->getreadbuf eq "") { + return ""; + } + $log->put("incomplete input: %s", $io->getreadbuf)->push($io); + return undef; + } + $k = &$code($io->getreadbuf); + if (! defined($k)) { + $log->push($io); + return undef; + } + if ($k == 0) { + return ""; + } + } + my $head = substr($io->getreadbuf, 0, $k); + my $tail = substr($io->getreadbuf, $k); + $io->setreadbuf($tail) + or $log->push, return undef; + return $head; +} + +sub readline { + my $io = shift; + @_ == 0 or confess 0+@_; + my $code = sub { + my $i = index($_[0], "\n"); + return $i < 0 ? 0 : $i + 1; + }; + return $io->readupto($code); +} + +sub write { + my $io = shift; + @_ == 1 or confess 0+@_; + my($data) = @_; + my $timeout = $io->hastimeout ? $io->gettimeout : 0; + my $fh = $io->getfh; + (my $show = $data) =~ s!\n!\\n!g; + $log->put("write: $show")->push($io)->debug; + my $n; + my $size = length($data); + eval { + local $SIG{PIPE} = sub { die("broken pipe\n") }; + if ($^O ne 'MSWin32' && $timeout > 0) { + local $SIG{ALRM} = sub { die("timed out\n") }; + alarm($timeout); + $n = syswrite($fh, $data, $size); + alarm(0); + } + else { + $n = syswrite($fh, $data, $size); + } + }; + if ($@) { + $log->put("write error: $@")->push($io); + return undef; + } + if (! defined($n)) { + $log->put("write failed: $!")->push($io); + return undef; + } + if ($n > $size) { + $log->put("impossible write: $n > $size")->push($io); + return undef; + } + if ($n != $size) { # need not be error + $log->put("short write: $n < $size")->push($io); + } + return $n; +} + +sub close { + my $io = shift; + @_ == 0 or confess 0+@_; + if (! close($io->delfh)) { + $log->put("close failed: $!")->push($io); + return undef; + } + return 1; +} + +1; |