Apache-Scoreboard
view release on metacpan or search on metacpan
Scoreboard.xs view on Meta::CPAN
{
/* 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)
Apache2::RequestRec r
SV *
freeze(image)
Apache::Scoreboard image
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);
dptr += psize;
for (i = 0; i < image->server_limit; i++) {
Move(sb->servers[i], dptr, msize, char);
dptr += msize;
}
Move(&sb->global, dptr, sizeof(global_score), char);
OUTPUT:
RETVAL
Apache::Scoreboard
thaw(CLASS, pool, packet)
SV *CLASS
APR::Pool pool
SV *packet
PREINIT:
modperl_scoreboard_t *image;
scoreboard *sb;
int psize, ssize;
char *ptr;
int i;
CODE:
if (!(SvOK(packet) && SvCUR(packet) > (SIZE16*2))) {
XSRETURN_UNDEF;
}
CLASS = CLASS; /* avoid warnings */
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); */
RETVAL = image;
OUTPUT:
RETVAL
SV *
image(CLASS, pool_sv)
SV *CLASS
SV *pool_sv
INIT:
modperl_scoreboard_t *image;
apr_pool_t *pool = mp_xs_sv2_APR__Pool(pool_sv);
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;
CODE:
ps = my_get_scoreboard_process(aTHX_ image, idx);
/* XXX */
if (!ps->quiescing && ps->pid) {
RETVAL = (modperl_parent_score_t *)apr_pcalloc(image->pool,
(sizeof(*RETVAL)));
RETVAL->record = ps;
RETVAL->idx = idx;
RETVAL->image = image;
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
Apache::ScoreboardWorkerScore
worker_score(image, parent_idx, worker_idx)
Apache::Scoreboard image
int parent_idx
int worker_idx
PREINIT:
worker_score *ws;
CODE:
ws = my_get_scoreboard_worker(aTHX_ image, parent_idx, worker_idx);
RETVAL = (modperl_worker_score_t *)apr_pcalloc(image->pool,
(sizeof(*RETVAL)));
RETVAL->parent_idx = parent_idx;
RETVAL->worker_idx = worker_idx;
RETVAL->record = ws;
OUTPUT:
RETVAL
SV *
pids(image)
Apache::Scoreboard image
PREINIT:
AV *av = newAV();
int i;
scoreboard *sb;
CODE:
sb = image->sb;
for (i = 0; i < image->server_limit; i++) {
if (!(sb->parent[i].pid)) {
break;
}
/* fprintf(stderr, "pids: server %d: pid %d\n",
i, (int)(sb->parent[i].pid)); */
av_push(av, newSViv(sb->parent[i].pid));
}
RETVAL = newRV_noinc((SV*)av);
OUTPUT:
RETVAL
# XXX: need to move pid_t => apr_proc_t and work with pid->pid as in
# find_child_by_pid from scoreboard.c
int
parent_idx_by_pid(image, pid)
Apache::Scoreboard image
pid_t pid
PREINIT:
int i;
scoreboard *sb;
CODE:
sb = image->sb;
RETVAL = -1;
for (i = 0; i < image->server_limit; i++) {
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
MODULE = Apache::Scoreboard PACKAGE = Apache::ScoreboardParentScore PREFIX = parent_score_
Apache::ScoreboardParentScore
next(self)
Apache::ScoreboardParentScore self
PREINIT:
int next_idx;
process_score *ps;
modperl_scoreboard_t *image;
CODE:
image = self->image;
next_idx = self->idx + 1;
if (next_idx <= image->server_limit) {
ps = my_get_scoreboard_process(aTHX_ image, next_idx);
}
else {
XSRETURN_UNDEF;
}
if (ps->pid) {
RETVAL = (modperl_parent_score_t *)apr_pcalloc(image->pool,
sizeof(*RETVAL));
RETVAL->record = ps;
RETVAL->idx = next_idx;
RETVAL->image = image;
}
else {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
Apache::ScoreboardWorkerScore
worker_score(self)
Apache::ScoreboardParentScore self
CODE:
RETVAL = (modperl_worker_score_t *)apr_pcalloc(self->image->pool,
sizeof(*RETVAL));
RETVAL->parent_idx = self->idx;
RETVAL->worker_idx = 0;
RETVAL->record = my_get_scoreboard_worker(aTHX_ self->image,
self->idx, 0);
OUTPUT:
RETVAL
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;
}
OUTPUT:
RETVAL
Apache::ScoreboardWorkerScore
next_live_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 (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;
}
}
if (!found) {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
Apache::ScoreboardWorkerScore
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;
}
}
if (!found) {
XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
pid_t
parent_score_pid(self)
Apache::ScoreboardParentScore self
MODULE = Apache::Scoreboard PACKAGE = Apache::ScoreboardWorkerScore PREFIX = worker_score_
void
times(self)
Apache::ScoreboardWorkerScore self
PPCODE:
if (GIMME == G_ARRAY) {
/* same return values as CORE::times() */
EXTEND(sp, 4);
PUSHs(sv_2mortal(newSViv(self->record->times.tms_utime)));
PUSHs(sv_2mortal(newSViv(self->record->times.tms_stime)));
PUSHs(sv_2mortal(newSViv(self->record->times.tms_cutime)));
PUSHs(sv_2mortal(newSViv(self->record->times.tms_cstime)));
}
else {
#ifdef _SC_CLK_TCK
float tick = sysconf(_SC_CLK_TCK);
#else
float tick = HZ;
#endif
if (self->record->access_count) {
/* cpu %, same value mod_status displays */
float RETVAL = (self->record->times.tms_utime +
self->record->times.tms_stime +
self->record->times.tms_cutime +
self->record->times.tms_cstime);
XPUSHs(sv_2mortal(newSVnv((double)RETVAL/tick)));
}
else {
XPUSHs(sv_2mortal(newSViv((0))));
}
}
void
start_time(self)
Apache::ScoreboardWorkerScore self
ALIAS:
stop_time = 1
PREINIT:
apr_time_t tp;
PPCODE:
ix = ix; /* warnings */
tp = (XSANY.any_i32 == 0) ?
self->record->start_time : self->record->stop_time;
SB_TRACE(MP_FUNC, "%s_time: %5" APR_TIME_T_FMT "\n",
(XSANY.any_i32 == 0 ? "start" : "stop"), tp);
{
SB_TRACE(MP_FUNC, "start: %5" APR_TIME_T_FMT "\n"
"stop: %5" APR_TIME_T_FMT "\n"
"last used: %5" APR_TIME_T_FMT "\n",
self->record->start_time,
self->record->stop_time,
self->record->last_used);
}
/* do the same as Time::HiRes::gettimeofday */
if (GIMME == G_ARRAY) {
EXTEND(sp, 2);
PUSHs(sv_2mortal(newSViv(apr_time_sec(tp))));
PUSHs(sv_2mortal(newSViv(apr_time_usec(tp))));
}
else {
EXTEND(sp, 1);
PUSHs(sv_2mortal(newSVnv(apr_time_sec(tp))));
}
long
req_time(self)
Apache::ScoreboardWorkerScore self
CODE:
if (self->record->start_time == 0L) {
RETVAL = 0L;
}
else {
RETVAL = (long)
((self->record->stop_time - self->record->start_time) / 1000);
}
if (RETVAL < 0L || !self->record->access_count) {
RETVAL = 0L;
}
OUTPUT:
RETVAL
SV *
worker_score_status(self)
Apache::ScoreboardWorkerScore self
CODE:
RETVAL = newSV(0);
sv_setnv(RETVAL, (double)self->record->status);
Perl_sv_setpvf(aTHX_ RETVAL, "%c", status_flags[self->record->status]);
SvNOK_on(RETVAL); /* dual-var */
OUTPUT:
RETVAL
# at the moment always gives 0 (blame httpd)
U32
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
unsigned long
worker_score_my_access_count(self)
Apache::ScoreboardWorkerScore self
unsigned long
worker_score_my_bytes_served(self)
Apache::ScoreboardWorkerScore self
unsigned long
worker_score_conn_bytes(self)
Apache::ScoreboardWorkerScore self
unsigned short
worker_score_conn_count(self)
Apache::ScoreboardWorkerScore self
char *
worker_score_client(self)
Apache::ScoreboardWorkerScore self
char *
worker_score_request(self)
Apache::ScoreboardWorkerScore self
char *
worker_score_vhost(self)
Apache::ScoreboardWorkerScore self
apr_uint32_t
worker_score_most_recent(self)
Apache::ScoreboardWorkerScore self
( run in 1.141 second using v1.01-cache-2.11-cpan-13bb782fe5a )