view release on metacpan or search on metacpan
apxs/mod_scoreboard_send.c has been ported to Apache 2.0
Apache::DummyScoreboard was ported to mp2 (this is used to process a
scoreboard outside running Apache).
when freezing/sending don't try to figure out what are the live
servers, since a sequential search doesn't work. if a server went
away, there will be a hole, e.g. if C goes down in ABCDE, we will get
ABXDE and send only AB info. so just send them all
added new methods $image->thread_limit and $image->server_limit and
deprecated the Apache::Const::SERVER_LIMIT and
Apache::Const::THREAD_LIMIT constants, since those are correct and
useful only for the image of the Apache server parsed from within the
running server.
use the passed image object, rather than accessing the global
ap_scoreboard_image. Previously we have switched to use Apache
accessors, instead of accessing the struct directly, but the problem
was that we no longer processed the real image object. So if the
script has acquired a different image (not the one seen by the current
Dummy/DummyScoreboard.pm view on Meta::CPAN
C<Apache::Scoreboard-E<gt>fetch> instead.
=item * C<Apache::Const::SERVER_LIMIT> and C<Apache::Const::THREAD_LIMIT>
At the moment the deprecated constants C<Apache::Const::SERVER_LIMIT>
and C<Apache::Const::THREAD_LIMIT> are hardwired to 0, since the
methods that provide this information are only accessible via a
running Apache (i.e. via C<Apache::Scoreboad> running under mod_perl).
However, you should be using
C<L<$image->server_limit|Apache::Scoreboard/C_server_limit_>> and
C<L<$image->thread_limit|Apache::Scoreboard/C_thread_limit_>>.
=back
=cut
Dummy/dummy.c view on Meta::CPAN
#include "httpd.h"
#include "scoreboard.h"
extern int server_limit, thread_limit;
#define DUMMY_SCOREBOARD
scoreboard *ap_scoreboard_image = NULL;
int ap_exists_scoreboard_image(void)
{
return 0;
}
Makefile.PL view on Meta::CPAN
use strict;
#use warnings;
use warnings FATAL => 'all';
#no warnings 'redefine';
use mod_perl2;
# XXX: need to check that the same perl is used as the one mod_perl
# was built with, otherwise unresolved symbols problems occur:
# e.g. try using mod_perl.so built with blead-perl and build the
# scoreboard with blead-ithreads-perl
#use Apache::Build ();
#my $build = Apache::Build->new;
#use lib qw(../lib ../Apache-Test/lib);
use ModPerl::MM ();
# enable 'make test|clean'
use Apache::TestMM qw(test clean);
# prerequisites
Scoreboard.xs view on Meta::CPAN
#define SB_TRACE modperl_trace
#else
#define SB_TRACE if (0) modperl_trace
#endif
/* scoreboard */
typedef struct {
scoreboard *sb;
apr_pool_t *pool;
int server_limit;
int thread_limit;
} modperl_scoreboard_t;
typedef struct {
worker_score *record;
int parent_idx;
int worker_idx;
} modperl_worker_score_t;
/* XXX: notice that here we reference a struct living in a different
* perl object ($image), so if that object is destroyed earlier we get
Scoreboard.xs view on Meta::CPAN
modperl_scoreboard_t *image;
} modperl_parent_score_t;
typedef modperl_scoreboard_t *Apache__Scoreboard;
typedef modperl_worker_score_t *Apache__ScoreboardWorkerScore;
typedef modperl_parent_score_t *Apache__ScoreboardParentScore;
static char status_flags[SERVER_NUM_STATUS];
#define server_limit(image) image->server_limit
#define thread_limit(image) image->thread_limit
#define scoreboard_up_time(image) \
(apr_uint32_t) apr_time_sec( \
apr_time_now() - image->sb->global->restart_time);
#define parent_score_pid(mps) mps->record->pid
#define worker_score_most_recent(mws) \
(apr_uint32_t) apr_time_sec(apr_time_now() - mws->record->last_used);
/* XXX: as of 20031219, tid is not maintained in scoreboard */
#if APR_HAS_THREADS
#define worker_score_tid(mws) mws->record->tid
#else
#define worker_score_tid(mws) NULL
#endif
#define worker_score_thread_num(mws) mws->record->thread_num
#define worker_score_access_count(mws) mws->record->access_count
#define worker_score_bytes_served(mws) mws->record->bytes_served
#define worker_score_my_access_count(mws) mws->record->my_access_count
#define worker_score_my_bytes_served(mws) mws->record->my_bytes_served
#define worker_score_conn_bytes(mws) mws->record->conn_bytes
#define worker_score_conn_count(mws) mws->record->conn_count
#define worker_score_client(mws) mws->record->client
#define worker_score_request(mws) mws->record->request
#define worker_score_vhost(mws) mws->record->vhost
Scoreboard.xs view on Meta::CPAN
status_flags[SERVER_BUSY_LOG] = 'L';
status_flags[SERVER_BUSY_DNS] = 'D';
status_flags[SERVER_CLOSING] = 'C';
status_flags[SERVER_GRACEFUL] = 'G';
status_flags[SERVER_IDLE_KILL] = 'I';
}
static void constants_init(pTHX)
{
HV *stash;
int server_limit, thread_limit;
/* SERVER_LIMIT and THREAD_LIMIT constants are deprecated, use
* $image->server_limit and $image->thread_limit instead */
#ifndef DUMMY_SCOREBOARD
ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
#else
/* XXX: how can we figure out that data w/o having an access to
* ap_mpm_query? */
server_limit = 0;
thread_limit = 0;
#endif
stash = gv_stashpv("Apache::Const", TRUE);
newCONSTSUB(stash, "SERVER_LIMIT", newSViv(server_limit));
stash = gv_stashpv("Apache::Const", TRUE);
newCONSTSUB(stash, "THREAD_LIMIT", newSViv(thread_limit));
stash = gv_stashpv("Apache::Scoreboard", TRUE);
newCONSTSUB(stash, "REMOTE_SCOREBOARD_TYPE",
newSVpv(REMOTE_SCOREBOARD_TYPE, 0));
}
MP_INLINE
static worker_score *my_get_scoreboard_worker(pTHX_
modperl_scoreboard_t *image,
int x, int y)
{
if (((x < 0) || (image->server_limit < x)) ||
((y < 0) || (image->thread_limit < y))) {
Perl_croak(aTHX_ "worker score [%d][%d] is out of limit", x, y);
}
return &image->sb->servers[x][y];
}
MP_INLINE
static process_score *my_get_scoreboard_process(pTHX_
modperl_scoreboard_t *image,
int x)
{
Scoreboard.xs view on Meta::CPAN
#else
#define MY_WARN ap_log_error(APLOG_MARK, APLOG_ERR, 0, modperl_global_get_server_rec(),
#endif
#if 0
static void debug_dump_sb(modperl_scoreboard_t *image)
{
int i, j;
for (i = 0; i < image->server_limit; i++) {
for (j = 0; j < image->thread_limit; j++) {
worker_score *ws = &image->sb->servers[i][j];
if (ws->access_count) {
MY_WARN
"rcv %02d-%02d: stat: %c cnt: %d\n", i, j,
status_flags[ws->status],
(int)ws->access_count);
}
}
}
}
Scoreboard.xs view on Meta::CPAN
MODULE = Apache::Scoreboard PACKAGE = Apache::Scoreboard PREFIX = scoreboard_
BOOT:
{
/* XXX: this must be performed only once and before other threads are spawned.
* but not sure. could be that need to use local storage.
*
*/
status_flags_init();
constants_init(aTHX);
}
int
scoreboard_send(r)
Scoreboard.xs view on Meta::CPAN
PREINIT:
int psize, ssize, tsize, msize, i;
char buf[SIZE16*4];
char *dptr, *ptr = buf;
scoreboard *sb;
CODE:
sb = image->sb;
psize = sizeof(process_score) * image->server_limit;
msize = sizeof(worker_score) * image->thread_limit;
ssize = msize * image->server_limit;
tsize = psize + ssize + sizeof(global_score) + sizeof(buf);
/* fprintf(stderr, "sizes %d, %d, %d, %d, %d\n",
psize, ssize, sizeof(global_score) , sizeof(buf), tsize); */
pack16(ptr, psize);
ptr += SIZE16;
pack16(ptr, ssize);
ptr += SIZE16;
pack16(ptr, image->server_limit);
ptr += SIZE16;
pack16(ptr, image->thread_limit);
RETVAL = NEWSV(0, tsize);
dptr = SvPVX(RETVAL);
SvCUR_set(RETVAL, tsize+1);
SvPOK_only(RETVAL);
/* fill the data buffer with the data we want to freeze */
Move(&buf[0], dptr, sizeof(buf), char);
dptr += sizeof(buf);
Move(&sb->parent[0], dptr, psize, char);
Scoreboard.xs view on Meta::CPAN
image = (modperl_scoreboard_t *)apr_pcalloc(pool, sizeof(*image));
ptr = SvPVX(packet);
psize = unpack16(ptr);
ptr += SIZE16;
ssize = unpack16(ptr);
ptr += SIZE16;
image->server_limit = unpack16(ptr);
ptr += SIZE16;
image->thread_limit = unpack16(ptr);
ptr += SIZE16;
/* MY_WARN
"recv: sizes server_num=%d, thread_num=%d, psize=%d, "
"ssize=%d\n",
image->server_limit, image->thread_limit, psize, ssize);
*/
sb = (scoreboard *)apr_palloc(pool, sizeof(scoreboard) +
image->server_limit * sizeof(worker_score *));
sb->parent = (process_score *)Copy_pool(pool, ptr, psize, char);
ptr += psize;
sb->servers = (worker_score **)((char*)sb + sizeof(scoreboard));
for (i = 0; i < image->server_limit; i++) {
sb->servers[i] = (worker_score *)Copy_pool(pool, ptr,
image->thread_limit * sizeof(worker_score), char);
ptr += image->thread_limit * sizeof(worker_score);
}
sb->global = (global_score *)Copy_pool(pool, ptr,
sizeof(global_score), char);
image->pool = pool;
image->sb = sb;
/* debug_dump_sb(image); */
Scoreboard.xs view on Meta::CPAN
CODE:
image_sanity_check(aTHX);
image = (modperl_scoreboard_t *)apr_palloc(pool, sizeof(*image));
if (ap_exists_scoreboard_image()) {
image->sb = ap_scoreboard_image;
image->pool = pool;
ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &(image->server_limit));
ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &(image->thread_limit));
}
else {
Perl_croak(aTHX_ "ap_scoreboard_image doesn't exist");
}
RETVAL = sv_setref_pv(NEWSV(0, 0), "Apache::Scoreboard", (void*)image);
/* make sure the pool sticks around as long as this object is alive */
mpxs_add_pool_magic(RETVAL, pool_sv);
CLASS = CLASS; /* avoid warnings */
OUTPUT:
RETVAL
int
server_limit(image)
Apache::Scoreboard image
int
thread_limit(image)
Apache::Scoreboard image
Apache::ScoreboardParentScore
parent_score(image, idx=0)
Apache::Scoreboard image
int idx
PREINIT:
process_score *ps;
Scoreboard.xs view on Meta::CPAN
if (sb->parent[i].pid == pid) {
RETVAL = i;
break;
}
}
OUTPUT:
RETVAL
SV *
thread_numbers(image, parent_idx)
Apache::Scoreboard image
int parent_idx
PREINIT:
AV *av = newAV();
int i;
scoreboard *sb;
CODE:
sb = image->sb;
for (i = 0; i < image->thread_limit; ++i) {
/* fprintf(stderr, "thread_num: server %d, thread %d pid %d\n",
i, sb->servers[parent_idx][i].thread_num,
(int)(sb->parent[parent_idx].pid)); */
av_push(av, newSViv(sb->servers[parent_idx][i].thread_num));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
apr_uint32_t
scoreboard_up_time(image)
Apache::Scoreboard image
Scoreboard.xs view on Meta::CPAN
Apache::ScoreboardWorkerScore
next_worker_score(self, mws)
Apache::ScoreboardParentScore self
Apache::ScoreboardWorkerScore mws
PREINIT:
int next_idx;
CODE:
next_idx = mws->worker_idx + 1;
if (next_idx < self->image->thread_limit) {
RETVAL = (modperl_worker_score_t *)apr_pcalloc(self->image->pool,
sizeof(*RETVAL));
RETVAL->parent_idx = mws->parent_idx;
RETVAL->worker_idx = next_idx;
RETVAL->record = my_get_scoreboard_worker(aTHX_ self->image,
mws->parent_idx, next_idx);
}
else {
XSRETURN_UNDEF;
}
Scoreboard.xs view on Meta::CPAN
Apache::ScoreboardParentScore self
Apache::ScoreboardWorkerScore mws
PREINIT:
int next_idx;
int found = 0;
CODE:
next_idx = mws->worker_idx;
while (++next_idx < self->image->thread_limit) {
worker_score *ws = my_get_scoreboard_worker(aTHX_ self->image,
mws->parent_idx, next_idx);
if (LIVE_WORKER(ws)) {
RETVAL = (modperl_worker_score_t *)apr_pcalloc(self->image->pool,
sizeof(*RETVAL));
RETVAL->record = ws;
RETVAL->parent_idx = mws->parent_idx;
RETVAL->worker_idx = next_idx;
found++;
break;
Scoreboard.xs view on Meta::CPAN
next_active_worker_score(self, mws)
Apache::ScoreboardParentScore self
Apache::ScoreboardWorkerScore mws
PREINIT:
int next_idx;
int found = 0;
CODE:
next_idx = mws->worker_idx;
while (++next_idx < self->image->thread_limit) {
worker_score *ws = my_get_scoreboard_worker(aTHX_ self->image,
mws->parent_idx, next_idx);
if (ACTIVE_WORKER(ws)) {
RETVAL = (modperl_worker_score_t *)apr_pcalloc(self->image->pool,
sizeof(*RETVAL));
RETVAL->record = ws;
RETVAL->parent_idx = mws->parent_idx;
RETVAL->worker_idx = next_idx;
found++;
break;
Scoreboard.xs view on Meta::CPAN
worker_score_tid(self)
Apache::ScoreboardWorkerScore self
CODE:
RETVAL = worker_score_tid(self);
OUTPUT:
RETVAL
int
worker_score_thread_num(self)
Apache::ScoreboardWorkerScore self
unsigned long
worker_score_access_count(self)
Apache::ScoreboardWorkerScore self
unsigned long
worker_score_bytes_served(self)
Apache::ScoreboardWorkerScore self
apxs/send.c view on Meta::CPAN
}
#define WRITE_BUFF(buf, size, r) \
if (ap_rwrite(buf, size, r) < 0) { return APR_EGENERAL; }
static int scoreboard_send(request_rec *r)
{
int psize, ssize, tsize;
char buf[SIZE16*4];
char *ptr = buf;
int server_limit, thread_limit;
/* In httpd-2.x, each content handler is invoked, and is responsible for
checking wether it's enabled or not for a given url. That's different
from how 1.3 used to do it.
*/
if (strcmp(r->handler, HANDLER_NAME)) {
return DECLINED;
}
ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
psize = sizeof(process_score) * server_limit;
ssize = sizeof(worker_score) * server_limit * thread_limit;
tsize = psize + ssize + sizeof(global_score) + sizeof(buf);
pack16(ptr, psize);
ptr += SIZE16;
pack16(ptr, ssize);
ptr += SIZE16;
pack16(ptr, server_limit);
ptr += SIZE16;
pack16(ptr, thread_limit);
#if 0
ap_log_error(APLOG_MARK, APLOG_ERR, 0, modperl_global_get_server_rec(),
"send: sizes server_limit=%d, thread_num=%d, psize=%d, "
"ssize=%d, %d, %d, %d\n",
server_limit, thread_limit, psize, ssize,
sizeof(global_score), sizeof(buf), tsize);
#endif
#if 0
{
int i, j;
for (i = 0; i < server_limit; i++) {
for (j = 0; j < thread_limit; j++) {
worker_score *ws = &ap_scoreboard_image->servers[i][j];
if (ws->access_count) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, modperl_global_get_server_rec(),
"snd %02d-%02d: stat: %c cnt: %d\n", i, j,
status_flags[ws->status],
(int)ws->access_count);
}
}
}
}
lib/Apache/Scoreboard.pm view on Meta::CPAN
my $image = Apache::Scoreboard->fetch("http://localhost/scoreboard");
=head1 DESCRIPTION
Apache keeps track of server activity in a structure known as the
C<scoreboard>. There is a I<slot> in the scoreboard for each child
server and its workers (be it threads or processes), containing
information such as status, access count, bytes served and cpu time,
and much more. This same information is used by C<mod_status> to
provide current server statistics in a human readable
form. C<Apache::Scoreboard> provides the Perl API to access the
scoreboard. C<Apache::VMonitor> is an extended equivalent of
C<mod_status> written in Perl.
lib/Apache/Scoreboard.pm view on Meta::CPAN
=head2 C<thaw>
my $thawed_image = Apache::Scoreboard->thaw($pool, $frozen_image);
thaws a C<L<frozen|/freeze>> image, turning it into the
C<L<Apache::Scoreboard|/The_Apache::Scoreboard_Methods>> object.
=head2 C<thread_limit>
Returns a threads limit per process for the given image.
my $thread_limit = $image->thread_limit;
use this instead of the deprecated C<Apache::Const::THREAD_LIMIT>
constant.
lib/Apache/Scoreboard.pm view on Meta::CPAN
my($tv_sec, $tv_usec) = $worker_score->stop_time;
my $secs = $worker_score->stop_time;
META: as of Apache 2.0.53 it's yet unavailable (needs to be ported)
=head2 C<thread_num>
XXX
=head2 C<tid>
XXX
t/lib/MyTest/Common.pm view on Meta::CPAN
my $vars = $cfg->{vars};
my $store_file = catfile $vars->{documentroot}, "scoreboard";
my $hostport = Apache::TestRequest::hostport($cfg);
my $retrieve_url = "http://$hostport/scoreboard";
my @worker_score_scalar_props =
qw(access_count bytes_served
client conn_bytes conn_count most_recent
my_access_count my_bytes_served request req_time
status thread_num tid);
# vhost is not available outside mod_perl, since it requires a call to
# an Apache method
push @worker_score_scalar_props, "vhost" if $ENV{MOD_PERL};
my @worker_score_dual_ctx_props = qw(
times start_time stop_time
);
my @worker_score_dual_var_props = qw(status);
t/lib/MyTest/Common.pm view on Meta::CPAN
t_debug "iterating over all active workers";
ok $next_active_ok;
### other scoreboard image accessors ###
my @pids = @{ $image->pids };
t_debug "pids: @pids";
ok @pids;
my @thread_numbers = @{ $image->thread_numbers(0) };
t_debug "thread_numbers: @thread_numbers";
ok @thread_numbers;
my $up_time = $image->up_time;
t_debug "up_time: $up_time";
ok $up_time >= 0; # can be 0 if tested too fast
my $worker_score = $image->worker_score(0, 0);
ok $worker_score;
my $pid = $pids[0];
t/lib/MyTest/Common.pm view on Meta::CPAN
sub image_is_ok {
my ($image) = shift;
my $status = 1;
$status = 0 unless $image &&
ref($image) eq 'Apache::Scoreboard' &&
$image->pids &&
$image->worker_score(0, 0)->status &&
$image->parent_score &&
$image->parent_score->worker_score->vhost &&
$image->server_limit &&
$image->thread_limit;
# check that we don't segfault here
#for (my $proc = $image->parent; $proc; $proc = $proc->next) {
# my $pid = $proc->pid;
#}
return $status;
}
# check that all worker_score props return something