Acme-Ghost

 view release on metacpan or  search on metacpan

lib/Acme/Ghost.pm  view on Meta::CPAN

    my $self = bless {
        name        => $name,
        user        => $user,
        group       => $group,
        uid         => $uid,
        gid         => $gid,
        gids        => $gids,

        # PID
        pidfile     => $args->{pidfile} || File::Spec->catfile(getcwd(), sprintf("%s.pid", $name)),
        _filepid    => undef,

        # Log
        facility    => $args->{facility},
        logfile     => $args->{logfile},
        ident       => $args->{ident} || $name,
        logopt      => $args->{logopt},
        logger      => $args->{logger},
        loglevel    => $args->{loglevel},
        loghandle   => $args->{loghandle},
        _log        => undef,

        # Runtime
        initpid     => $$,  # PID of root process
        ppid        => 0,   # PID before daemonize
        pid         => 0,   # PID daemonized process
        daemonized  => 0,   # 0 - no daemonized; 1 - daemonized
        spirited    => 0,   # 0 - is not spirit; 1 - is spirit (See ::Prefork)

        # Manage
        ok          => 0,   # 1 - Ok. Process is healthy (ok)

lib/Acme/Ghost.pm  view on Meta::CPAN

    $self->{ppid} = $$;

    # Get UID & GID
    my $uid = $self->{uid}; # UID
    my $gids = $self->{gid}; # returns list of groups (gids)
    my $gid = (split /[\s,]+/, $gids)[0]; # First GID
    _debug("!! UID=%s; GID=%s; GIDs=\"%s\"", $uid, $gid, $gids);

    # Pre Init Hook
    $self->preinit;
    $self->{_log} = undef; # Close log handlers before spawn

    # Spawn
    my $pid = _fork();
    if ($pid) {
        _debug("!! Spawned (PID=%s)", $pid);
        if ($safe) { # For internal use only
            $self->{pid} = $pid; # Store child PID to instance
            return $self;
        }
        exit 0; # exit parent process

lib/Acme/Ghost/FilePid.pm  view on Meta::CPAN

    $fp->file("/var/run/file.pid");
    my $pidfile = $fp->file;

Accessor/mutator for the filename used as the pid file.

=head2 load

    $fp->load;

Load owner pid from file.
On success, the object is returned. On failure, C<undef> is
returned.

=head2 owner

    $fp->owner(123);
    my $owner = $fp->owner;

Accessor/mutator for the pid being saved to the pid file.

=head2 pid

lib/Acme/Ghost/FilePid.pm  view on Meta::CPAN

Removes the pid file from disk. Returns true on success, false on
failure.

=head2 running

    my $pid = $fp->running;
    die "Service already running: $pid" if $pid;

Checks to see if the pricess identified in the pid file is still
running. If the process is still running, the pid is returned. Otherwise
C<undef> is returned.

=head2 save

    $fp->save;

Writes the pid file to disk, inserting the pid inside the file.
On success, the object is returned. On failure, C<undef> is
returned.

=head1 HISTORY

See C<Changes> file

=head1 TO DO

See C<TODO> file

lib/Acme/Ghost/FilePid.pm  view on Meta::CPAN

    my $self = shift;
    if (scalar(@_) >= 1) {
        $self->{owner} = shift;
        return $self;
    }
    return $self->{owner};
}
sub running {
    my $self = shift;
    my $owner  = $self->load->owner || 0; # Get PID from file
    my $r = kill(0, $owner) ? $owner : undef;
    $self->{is_running} = $r ? 1 : 0;
    return $r; # Is running?
}
sub remove {
    my $self = shift;
    my $file = $self->file;
    return $self unless -e $file;
    unlink $file;
    $self->owner(0); # Set owner PID to 0
    return $self;

lib/Acme/Ghost/FilePid.pm  view on Meta::CPAN

sub save {
    my $self = shift;
    my $file = $self->file;
    my $pid  = $self->pid || $$;
       $self->owner($pid); # Set owner PID as current PID

    # Save PID to file
    my $fh = IO::File->new($file, "w");
    croak qq/Can't open file "$file": $!/ unless defined $fh;
    $fh->write("$pid\n") or croak qq/Can't write to file "$file": $!/;
    undef $fh; # automatically closes the file

    # Returns self
    return $self;
}
sub load {
    my $self = shift;
    my $file = $self->file;
    return $self unless -e $file;

    # Read file
    my $ret = my $content = '';
    my $fh = IO::File->new($file, "r");
    croak qq/Can't open file "$file": $!/ unless defined $fh;
    while ($ret = $fh->read(my $buf, 255)) { $content .= $buf }
    croak qq/Can't read from file "$file": $!/ unless defined $ret;
    undef $fh; # automatically closes the file

    # Set loaded PID as owner
    chomp $content;
    $self->owner(($content || 0) * 1) if $content =~ /^\d+$/;

    # Returns object
    return $self;
}
sub DESTROY {
    my $self = shift;

lib/Acme/Ghost/Log.pm  view on Meta::CPAN

priority is higher or equal than the configured setting.

Default: C<debug>

See also L<Sys::Syslog/Levels>

=head2 logger

This attribute perfoms to set predefined logger, eg. Mojo::Log

Default: C<undef>

=head2 logopt

This attribute contains zero or more of the options detailed in L<Sys::Syslog/openlog>

Default: C<'ndelay,pid'>

=head1 METHODS

This class implements the following methods

lib/Acme/Ghost/Log.pm  view on Meta::CPAN

    $log      = $log->level('debug');

Active log level, defaults to debug.
Available log levels are C<trace>, C<debug>, C<info>, C<notice>, C<warn>, C<error>,
C<fatal> (C<crit>), C<alert> and C<emerg>, in that order

=head2 logger

    my $logger = $log->logger;

This method returns the logger object or undef if not exists

=head2 notice

    $log->notice('Normal, but significant, condition...');
    $log->notice('Ok', 'then');

Log C<notice> message

=head2 provider

lib/Acme/Ghost/Log.pm  view on Meta::CPAN

);

my $ENCODING = find_encoding('UTF-8') or croak qq/Encoding "UTF-8" not found/;

sub new {
    my $class = shift;
    my $args = @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {};
    $args->{facility}   ||= Sys::Syslog::LOG_USER;
    $args->{ident}      ||= basename($0);
    $args->{logopt}     ||= LOGOPTS;
    $args->{logger}     ||= undef;
    $args->{level}      ||= 'debug';
    $args->{file}       ||= undef;
    $args->{handle}     ||= undef;
    $args->{provider}   = 'unknown';

    # Check level
    croak "Incorrect log level specified" unless exists $MAGIC{$args->{level}};

    # Instance
    my $self = bless {%$args}, $class;

    # Open sys log socket
    if ($args->{logger}) {

lib/Acme/Ghost/Log.pm  view on Meta::CPAN

        return 1;
    }

    return 0 if $self->provider ne "syslog";
    my $lvl = $LOGLEVELS{$level} // Sys::Syslog::LOG_DEBUG;
    Sys::Syslog::syslog($lvl, LOGFORMAT, join(SEPARATOR, @msg));
}

DESTROY {
    my $self = shift;
    undef $self->{handle} if $self->{file};
    Sys::Syslog::closelog() unless $self->logger;
}

1;

__END__

lib/Acme/Ghost/Prefork.pm  view on Meta::CPAN


sub again {
    my $self = shift;
    my %args = @_;

    # Prefork management subsystem
    $self->{pool}               = {}; # pid => {...}
    $self->{running}            = 0; # 0 - not running; 1 - running
    $self->{finished}           = 0; # 1 - marker for spirits and manager stopping
    $self->{gracefully_stop}    = 0; # 1 - marker for gracefully stopping
    $self->{reader}             = undef; # Readable pipe to get messages from spirits
    $self->{writer}             = undef; # Writable pipe to send messages to manager
    $self->{spare}              = $args{spare} || SPARE;
    $self->{spirits}            = $args{spirits} || $args{workers} || SPIRITS;
    $self->{heartbeat_interval} = $args{heartbeat_interval} || HEARTBEAT_INTERVAL;
    $self->{heartbeat_timeout}  = $args{heartbeat_timeout} || HEARTBEAT_TIMEOUT;
    $self->{graceful_timeout}   = $args{graceful_timeout} || GRACEFUL_TIMEOUT;
    $self->{spirit_cb}          = $args{spirit};

    return $self;
}
sub startup {

lib/Acme/Ghost/Prefork.pm  view on Meta::CPAN

    for my $pid (keys %{$self->{pool}}) {
        next unless my $w = $self->{pool}{$pid}; # Get spirit struct

        # No heartbeat (graceful stop)
        if (!$w->{graceful} && ($w->{time} + $interval + $hb_to <= $now)) {
            $log->error("Spirit $pid has no heartbeat ($hb_to seconds), restarting");
            $w->{graceful} = $now;
        }

        # Graceful stop with timeout
        my $graceful = $w->{graceful} ||= $self->{gracefully_stop} ? $now : undef;
        if ($graceful && !$w->{attempt}) {
            $w->{attempt}++;
            $log->info("Stopping spirit $pid gracefully ($gf_to seconds)");
            kill 'QUIT', $pid or $self->_stopped($pid);
        }
        $w->{force} = 1 if $graceful && $graceful + $gf_to <= $now; # The conditions for a graceful stop by timeout were violated

        # Normal stop
        if ($w->{force} || ($self->{finished} && !$graceful)) {
            $log->warn("Stopping spirit $pid immediately");



( run in 0.891 second using v1.01-cache-2.11-cpan-d80b1682f3f )