Image-DS9

 view release on metacpan or  search on metacpan

lib/Image/DS9.pm  view on Meta::CPAN

        $self->{$_} = delete $attr{$_} foreach grep { exists $def_obj_attrs{$_} } keys %attr;

        _croak( 'unknown attribute(s): %s', join( ', ', sort keys %attr ) )
          if keys %attr;
    }

    sub get_attr {

        my ( $self, $attr ) = @_;

        exists $_->{$attr} && return $_->{$attr} for $self, $self->{xpa_attrs}, $self->{cmd_attrs};

        _croak( 'unknown attribute: %s', $attr );
    }

}

sub DESTROY {
    my $self = shift;
    return unless defined $self->{xpa};

    # xpa may be up, but we may not have found our ds9, so origin will
    # be undefined.
    $self->quit
      if defined $self->{origin}
      && $self->get_attr( 'terminate_on_destroy' ) & $self->{origin};
    $self->{xpa}->Close;
}

#####################################################################

sub nservers {
    my $self = shift;

    my %res = $self->{xpa}->Access( $self->{Server}, 'gs' );

    if ( any { defined $_->{message} } values %res ) {
        $self->{res} = \%res;
        _croak( 'error sending data to server' );
    }

    keys %res;
}

#####################################################################

sub res {
    %{ $_[0]->{res} || {} };
}

#####################################################################

sub wait {    ## no critic(Subroutines::ProhibitBuiltinHomonyms)
    my $self         = shift;
    my $timeout      = shift || $self->{StartTimeOut};
    my $timeinterval = $self->{WaitTimeInterval};

    unless ( $self->nservers ) {
        my $cnt = 0;
        sleep( $timeinterval )
          until ( exists $self->{_process} && !$self->{_process}->alive )
          || $self->nservers >= $self->{min_servers}
          || ( $cnt += $timeinterval ) > $timeout;
    }

    return $self->nservers >= $self->{min_servers};
}

sub _start_server {

    my ( $self, $start_timeout, $query_timeout ) = @_;

    $start_timeout = abs( $start_timeout // $self->get_attr( 'StartTimeOut' ) );
    $query_timeout = abs( $query_timeout // $self->get_attr( 'QueryTimeOut' ) );

    if ( $self->wait( $query_timeout ) ) {
        $self->{origin} = TERMINATE_DS9_ATTACHED;
        return;
    }

    my @cmd = (
        ( is_arrayref( $self->{ds9} ) ? @{ $self->{ds9} } : $self->{ds9} ),
        (
            defined $self->{Server}
            ? ( -title => $self->{Server} )
            : ()
        ),
    );

    my $terminate_on_destroy = $self->get_attr( 'terminate_on_destroy' ) & TERMINATE_DS9_STARTED;

    if ( $self->get_attr( 'daemonize' ) ) {
        require Image::DS9::Daemon;
        $self->{_process} = Image::DS9::Daemon->new( terminate_on_destroy => $terminate_on_destroy, );

        # this craziness is because Proc::Daemon always uses the
        # simplified version of exec which uses the shell to launch
        # processes and we don't want that
        unless ( $self->{_process}->Init ) {
            exec { $cmd[0] } @cmd
              or die( 'error running ', join( ', ', @cmd ) );
        }
    }
    else {
        require Proc::Background;
        $self->{_process} = Proc::Background->new( {
            command       => \@cmd,
            autodie       => 1,
            autoterminate => $terminate_on_destroy,
        } );
    }


    $self->wait( $start_timeout ) or _croak( 'error connecting to ds9: %s', join( q{ }, @cmd ) );

    $self->{origin} = TERMINATE_DS9_STARTED;
}


#####################################################################



( run in 0.528 second using v1.01-cache-2.11-cpan-39bf76dae61 )