Algorithm-Classifier-IsolationForest
view release on metacpan or search on metacpan
lib/Algorithm/Classifier/IsolationForest/App/Command/streamc.pm view on Meta::CPAN
if ( defined( $opt->{'set'} ) && $opt->{'set'} !~ /\A[A-Za-z0-9+\-@_]+\z/ ) {
$self->usage_error( '--set, "'
. $opt->{'set'}
. '", must match /\A[A-Za-z0-9+\-@_]+\z/ (letters, digits, and + - @ _ only)' );
}
my @cmds = grep { $opt->{$_} } qw(ping stats save relearn_threshold);
if ( defined( $opt->{'i'} ) ) {
if ( scalar @cmds ) {
$self->usage_error('-i may not be combined with --ping/--stats/--save/--relearn-threshold');
}
} elsif ( scalar @cmds != 1 ) {
$self->usage_error(
'need either -i (stream mode) or exactly one of --ping, --stats, --save, --relearn-threshold');
}
if ( defined( $opt->{'i'} ) && $opt->{'i'} ne '-' ) {
if ( !-f $opt->{'i'} ) {
$self->usage_error( '-i, "' . $opt->{'i'} . '", is not a file or does not exist' );
} elsif ( !-r $opt->{'i'} ) {
$self->usage_error( '-i, "' . $opt->{'i'} . '", is not readable' );
}
}
if ( defined( $opt->{'o'} ) && !$opt->{'w'} && -e $opt->{'o'} ) {
$self->usage_error( '-o, "' . $opt->{'o'} . '", already exists and -w is not specified' );
}
if ( $opt->{'mode'} !~ /\A(?:prequential|learn|score)\z/ ) {
$self->usage_error( '--mode, "' . $opt->{'mode'} . '", must be prequential, learn, or score' );
}
if ( $opt->{'d'} && $opt->{'jsonl'} ) {
$self->usage_error('-d only applies to CSV input; --jsonl replies are already self-describing');
}
if ( $opt->{'json'} && defined( $opt->{'i'} ) ) {
$self->usage_error('--json only applies to command mode');
}
if ( $opt->{'batch'} < 1 ) {
$self->usage_error( '--batch, "' . $opt->{'batch'} . '", must be >= 1' );
}
if ( $opt->{'timeout'} < 1 ) {
$self->usage_error( '--timeout, "' . $opt->{'timeout'} . '", must be >= 1' );
}
return 1;
} ## end sub validate
sub execute {
my ( $self, $opt, $args ) = @_;
# Lazily required for the same reason streamd does it: App::Cmd loads
# every command module up front, and the rest of the CLI should work
# on a box without JSON::MaybeXS.
eval { require JSON::MaybeXS; 1 }
or die( 'iforest streamc requires JSON::MaybeXS for its wire protocol; install it: ' . $@ );
$JSON = JSON::MaybeXS->new( utf8 => 1, canonical => 1 );
$TIMEOUT = $opt->{'timeout'};
# Resolve the socket exactly as streamd does (keep in sync with it):
# without a set the flag is the socket file; with one it is the base
# run dir holding <set>.sock.
my $socket;
if ( defined $opt->{'set'} ) {
my $run = defined $opt->{'socket'} ? $opt->{'socket'} : '/var/run/iforest_streamd';
$socket = File::Spec->catfile( $run, $opt->{'set'} . '.sock' );
} else {
$socket = defined $opt->{'socket'} ? $opt->{'socket'} : '/var/run/iforest_streamd/streamd.sock';
}
die( '--socket, "'
. $socket
. '", is '
. length($socket)
. ' bytes; Unix socket paths are limited to ~104 bytes -- use a shorter path'
. "\n" )
if length($socket) > 100;
$SOCK = IO::Socket::UNIX->new( Peer => $socket )
or die( 'failed to connect to "'
. $socket . '": '
. $!
. ' -- is streamd running'
. ( defined $opt->{'set'} ? ' with --set ' . $opt->{'set'} : '' ) . '?'
. "\n" );
$SOCK->autoflush(1);
# A daemon dropping us mid-write should surface as the read-side
# "no reply" error, not a silent SIGPIPE death.
local $SIG{PIPE} = 'IGNORE';
return _command( $self, $opt ) if !defined $opt->{'i'};
return _stream( $self, $opt );
} ## end sub execute
#-------------------------------------------------------------------------------
# wire helpers
#-------------------------------------------------------------------------------
# Send one request and wait for its reply. The protocol is strictly one
# reply per request on a single connection, so this can block on the
# answer instead of correlating tags.
#
# Args:
# $msg :: the request as a hashref, ready to encode -- a row/rows
# message or a cmd message.
#
# Returns: the hashref _read_reply returns, holding the raw reply line and
# its decoded form. Dies when the daemon says nothing within --timeout
# seconds or closes the connection first.
#
# Example:
# my $got = _request( { cmd => 'stats' } );
# $got->{reply}{ok}{seen};
sub _request {
my ($msg) = @_;
print {$SOCK} $JSON->encode($msg) . "\n";
my $reply = _read_reply();
( run in 1.614 second using v1.01-cache-2.11-cpan-364913b4093 )