You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by Stas Bekman <st...@stason.org> on 2002/03/15 19:04:48 UTC
[patch] Apache::Scoreboard
This is a big patch porting Apache::Scoreboard to work with 2.0, with all
the tests working under the latest prefork and worker mpms on perl5.7.3.
Haven't tested it yet with 5.6.1.
Docs are coming. The scoreboard has changed a bit in 2.0 mainly because of
the threads. I've changed a few APIs and struct names and added a few new
APIs.
I've Apache::VMonitor almost perfectly working with it. It works but
still needs a few tweaks, since now we have threads and procs, so it
should be smart to work with both and present a usable monitor :)
Index: src/modules/perl/modperl_apache_includes.h
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_apache_includes.h,v
retrieving revision 1.9
diff -u -r1.9 modperl_apache_includes.h
--- src/modules/perl/modperl_apache_includes.h 29 Jan 2002 05:32:39 -0000 1.9
+++ src/modules/perl/modperl_apache_includes.h 15 Mar 2002 17:47:14 -0000
@@ -51,5 +51,6 @@
#include "util_filter.h"
#include "util_script.h"
+#include "scoreboard.h"
#endif /* MODPERL_APACHE_INCLUDES_H */
Index: src/modules/perl/modperl_types.h
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_types.h,v
retrieving revision 1.56
diff -u -r1.56 modperl_types.h
--- src/modules/perl/modperl_types.h 21 Feb 2002 01:45:34 -0000 1.56
+++ src/modules/perl/modperl_types.h 15 Mar 2002 17:47:14 -0000
@@ -231,4 +231,24 @@
char *path_info;
} modperl_uri_t;
+/* scoreboard */
+typedef struct {
+ scoreboard *sb;
+ apr_pool_t *pool;
+} modperl_scoreboard_t;
+
+typedef struct {
+ worker_score record;
+ int parent_idx;
+ int worker_idx;
+} modperl_worker_score_t;
+
+typedef struct {
+ process_score record;
+ int idx;
+ scoreboard *sb;
+ apr_pool_t *pool;
+} modperl_parent_score_t;
+
+
#endif /* MODPERL_TYPES_H */
Index: t/conf/extra.conf.in
===================================================================
RCS file: /home/cvs/modperl-2.0/t/conf/extra.conf.in,v
retrieving revision 1.2
diff -u -r1.2 extra.conf.in
--- t/conf/extra.conf.in 26 Feb 2002 19:12:04 -0000 1.2
+++ t/conf/extra.conf.in 15 Mar 2002 17:47:14 -0000
@@ -13,3 +13,12 @@
PerlResponseHandler ModPerl::Registry
PerlOptions +ParseHeaders
</Directory>
+
+# debug
+ExtendedStatus On
+
+ PerlModule Apache::Scoreboard
+ <Location /scoreboard>
+ SetHandler perl-script
+ PerlHandler Apache::Scoreboard::send
+ </Location>
Index: xs/maps/apache_functions.map
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/maps/apache_functions.map,v
retrieving revision 1.45
diff -u -r1.45 apache_functions.map
--- xs/maps/apache_functions.map 10 Mar 2002 00:14:23 -0000 1.45
+++ xs/maps/apache_functions.map 15 Mar 2002 17:47:15 -0000
@@ -324,16 +324,22 @@
ap_close_piped_log
ap_open_piped_log
-!MODULE=Apache::Scoreboard
+MODULE=Apache::Scoreboard
ap_exists_scoreboard_image
ap_sync_scoreboard_image
-ap_update_child_status
+-ap_update_child_status_from_indexes
+-ap_reopen_scoreboard
+-ap_init_scoreboard
+-ap_calc_scoreboard_size
+-ap_create_sb_handle
-ap_time_process_request
-ap_create_scoreboard
ap_cleanup_scoreboard
ap_increment_counts
- ap_get_parent_scoreboard
- ap_get_servers_scoreboard
+ ap_get_scoreboard_worker
+ ap_get_scoreboard_process
+ ap_get_scoreboard_global
!MODULE=Apache::Hooks
ap_location_walk
Index: xs/maps/apache_types.map
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/maps/apache_types.map,v
retrieving revision 1.6
diff -u -r1.6 apache_types.map
--- xs/maps/apache_types.map 10 Sep 2001 06:42:51 -0000 1.6
+++ xs/maps/apache_types.map 15 Mar 2002 17:47:15 -0000
@@ -26,8 +26,10 @@
ap_mgmt_type_e | IV
ap_mgmt_value | UNDEFINED
ap_scoreboard_e | IV
+struct scoreboard | UNDEFINED
struct process_score | UNDEFINED
struct worker_score | UNDEFINED
+struct global_score | UNDEFINED
struct ap_pod_t | UNDEFINED
ap_unix_identity_t | UNDEFINED
Index: xs/maps/modperl_functions.map
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/maps/modperl_functions.map,v
retrieving revision 1.35
diff -u -r1.35 modperl_functions.map
--- xs/maps/modperl_functions.map 29 Jan 2002 17:11:06 -0000 1.35
+++ xs/maps/modperl_functions.map 15 Mar 2002 17:47:15 -0000
@@ -98,3 +98,53 @@
MODULE=Apache::SubProcess
# ap_subprocess_ won't work
modperl_spawn_proc_prog | MPXS_ | ... | spawn_proc_prog
+
+MODULE=Apache::Scoreboard PACKAGE=Apache::Scoreboard BOOT=1
+ mpxs_Apache__Scoreboard_send
+ mpxs_Apache__Scoreboard_freeze
+ mpxs_Apache__Scoreboard_thaw
+ mpxs_Apache__Scoreboard_image
+ mpxs_Apache__Scoreboard_parent_score | | self, idx=0
+ mpxs_Apache__Scoreboard_worker_score
+ mpxs_Apache__Scoreboard_pids
+ mpxs_Apache__Scoreboard_thread_numbers
+ mpxs_Apache__Scoreboard_parent_idx_by_pid
+ apr_uint32_t:DEFINE_up_time | | modperl_scoreboard_t *:self
+
+ mpxs_Apache__Scoreboard_add
+ mpxs_Apache__Scoreboard_print
+ mpxs_Apache__Scoreboard_add_sv
+ mpxs_Apache__Scoreboard_add_sv_sv
+ mpxs_Apache__Scoreboard_add_subst
+ mpxs_Apache__Scoreboard_subst_sp | | ...
+
+MODULE=Apache::Scoreboard PACKAGE=Apache::ScoreboardParentScore
+ mpxs_Apache__ScoreboardParentScore_next
+ mpxs_Apache__ScoreboardParentScore_worker_score
+ mpxs_Apache__ScoreboardParentScore_next_worker_score
+ mpxs_Apache__ScoreboardParentScore_next_live_worker_score
+ mpxs_Apache__ScoreboardParentScore_next_active_worker_score
+ pid_t :DEFINE_pid | | modperl_parent_score_t *:mps
+
+MODULE=Apache::Scoreboard PACKAGE=Apache::ScoreboardWorkerScore
+DEFINE_times | MPXS_Apache__ScoreboardWorkerScore_times | ...
+DEFINE_start_time | MPXS_Apache__ScoreboardWorkerScore_start_time | ...
+DEFINE_stop_time | MPXS_Apache__ScoreboardWorkerScore_stop_time | ...
+ mpxs_Apache__ScoreboardWorkerScore_req_time
+ mpxs_Apache__ScoreboardWorkerScore_status
+ apr_uint32_t :DEFINE_most_recent | | modperl_worker_score_t *:self
+ unsigned long:DEFINE_access_count | | modperl_worker_score_t *:self
+ unsigned long:DEFINE_bytes_served | | modperl_worker_score_t *:self
+ unsigned long:DEFINE_my_access_count | | modperl_worker_score_t *:self
+ unsigned long:DEFINE_my_bytes_served | | modperl_worker_score_t *:self
+ unsigned long:DEFINE_conn_bytes | | modperl_worker_score_t *:self
+ unsigned long:DEFINE_conn_count | | modperl_worker_score_t *:self
+ char * :DEFINE_client | | modperl_worker_score_t *:self
+ char * :DEFINE_request | | modperl_worker_score_t *:self
+ char * :DEFINE_vhost | | modperl_worker_score_t *:self
+
+
+!MODULE=Apache::Scoreboard PACKAGE=Apache::ScoreboardGlobalScore
+
+
+
Index: xs/maps/modperl_types.map
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/maps/modperl_types.map,v
retrieving revision 1.3
diff -u -r1.3 modperl_types.map
--- xs/maps/modperl_types.map 19 Apr 2001 21:26:44 -0000 1.3
+++ xs/maps/modperl_types.map 15 Mar 2002 17:47:15 -0000
@@ -2,6 +2,10 @@
struct modperl_filter_t | Apache::OutputFilter
+struct modperl_scoreboard_t | Apache::Scoreboard
+struct modperl_worker_score_t | Apache::ScoreboardWorkerScore
+struct modperl_parent_score_t | Apache::ScoreboardParentScore
+
########## Perl types ##########
SV * | SV
--- /dev/null Thu Jan 1 07:30:00 1970
+++ xs/Apache/Scoreboard/Apache__Scoreboard.h Sat Mar 16 01:52:55 2002
@@ -0,0 +1,586 @@
+#include "scoreboard.h"
+#include "ap_mpm.h"
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+/* XXX: When documenting don't forget to add the new 'vhost' accessor */
+/* and port accessor if it gets added (need to add it here too) */
+
+int server_limit, thread_limit;
+
+static char status_flags[SERVER_NUM_STATUS];
+
+#define mpxs_Apache__Scoreboard_up_time(image) \
+ (apr_uint32_t)((apr_time_now() - image->sb->global->restart_time) / APR_USEC_PER_SEC);
+
+#define mpxs_Apache__ScoreboardWorkerScore_most_recent(mws) \
+ (apr_uint32_t)((apr_time_now() - mws->record.last_used) / APR_USEC_PER_SEC);
+
+#define mpxs_Apache__ScoreboardWorkerScore_access_count(mws) mws->record.access_count
+#define mpxs_Apache__ScoreboardWorkerScore_bytes_served(mws) mws->record.bytes_served
+#define mpxs_Apache__ScoreboardWorkerScore_my_access_count(mws) mws->record.my_access_count
+#define mpxs_Apache__ScoreboardWorkerScore_my_bytes_served(mws) mws->record.my_bytes_served
+#define mpxs_Apache__ScoreboardWorkerScore_conn_bytes(mws) mws->record.conn_bytes
+#define mpxs_Apache__ScoreboardWorkerScore_conn_count(mws) mws->record.conn_count
+#define mpxs_Apache__ScoreboardWorkerScore_client(mws) mws->record.client
+#define mpxs_Apache__ScoreboardWorkerScore_request(mws) mws->record.request
+#define mpxs_Apache__ScoreboardWorkerScore_vhost(mws) mws->record.vhost
+
+#define mpxs_Apache__ScoreboardParentScore_pid(ps) ps->record.pid
+
+/* a worker that have served/serves at least one request and isn't
+ * dead yet */
+#define LIVE_WORKER(ws) ws.access_count != 0 || \
+ ws.status != SERVER_DEAD
+
+/* a worker that does something at this very moment */
+#define ACTIVE_WORKER(ws) ws.access_count != 0 || \
+ (ws.status != SERVER_DEAD && ws.status != SERVER_READY)
+
+#define REMOTE_SCOREBOARD_TYPE "application/x-httpd-scoreboard"
+
+#ifndef Move
+#define Move(s,d,n,t) (void)memmove((char*)(d),(char*)(s), (n) * sizeof(t))
+#endif
+#ifndef Copy
+#define Copy(s,d,n,t) (void)memcpy((char*)(d),(char*)(s), (n) * sizeof(t))
+#endif
+
+#define SIZE16 2
+
+static void pack16(unsigned char *s, int p)
+{
+ short ashort = htons(p);
+ Move(&ashort, s, SIZE16, unsigned char);
+}
+
+static unsigned short unpack16(unsigned char *s)
+{
+ unsigned short ashort;
+ Copy(s, &ashort, SIZE16, char);
+ return ntohs(ashort);
+}
+
+
+static void status_flags_init(void)
+{
+ status_flags[SERVER_DEAD] = '.';
+ status_flags[SERVER_READY] = '_';
+ status_flags[SERVER_STARTING] = 'S';
+ status_flags[SERVER_BUSY_READ] = 'R';
+ status_flags[SERVER_BUSY_WRITE] = 'W';
+ status_flags[SERVER_BUSY_KEEPALIVE] = 'K';
+ 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 mpxs_Apache__Scoreboard_BOOT(pTHX)
+{
+ HV *stash;
+
+/* 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();
+
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
+
+ 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));
+
+}
+
+#define WRITE_BUFF(buf, size, r) \
+ if (ap_rwrite(buf, size, r) < 0) { return APR_EGENERAL; }
+
+static MP_INLINE
+int mpxs_Apache__Scoreboard_send(request_rec *r)
+{
+ int i, psize, ssize, tsize;
+ char buf[SIZE16*2];
+ char *ptr = buf;
+
+ for (i = 0; i < server_limit; i++) {
+ if (!ap_scoreboard_image->parent[i].pid) {
+ break;
+ }
+ }
+
+ psize = i * sizeof(process_score);
+ ssize = i * sizeof(worker_score);
+ tsize = psize + ssize + sizeof(global_score) + sizeof(buf);
+
+ pack16(ptr, psize);
+ ptr += SIZE16;
+ pack16(ptr, ssize);
+
+ ap_set_content_length(r, tsize);
+ r->content_type = REMOTE_SCOREBOARD_TYPE;
+
+ if (!r->header_only) {
+ WRITE_BUFF(&buf[0], sizeof(buf), r);
+ WRITE_BUFF(&ap_scoreboard_image->parent[0], psize, r);
+ WRITE_BUFF(&ap_scoreboard_image->servers[0], ssize, r);
+ WRITE_BUFF(&ap_scoreboard_image->global, sizeof(global_score), r);
+ }
+
+ return APR_SUCCESS;
+}
+
+static MP_INLINE
+SV *mpxs_Apache__Scoreboard_freeze(pTHX_ modperl_scoreboard_t *image)
+{
+ int i, psize, ssize, tsize;
+ char buf[SIZE16*2];
+ char *dptr, *data, *ptr = buf;
+ scoreboard *sb = image->sb;
+ SV *retval;
+
+ for (i = 0; i < server_limit; i++) {
+ if (!sb->parent[i].pid) {
+ break;
+ }
+ }
+
+ psize = i * sizeof(process_score);
+ ssize = i * sizeof(worker_score);
+ tsize = psize + ssize + sizeof(global_score) + sizeof(buf);
+ fprintf(stderr, "sizes %d, %d, %d, %d, %d, %d\n", i, psize, ssize, sizeof(global_score) , sizeof(buf), tsize);
+
+ data = (char *)apr_palloc(image->pool, tsize);
+
+ pack16(ptr, psize);
+ ptr += SIZE16;
+ pack16(ptr, ssize);
+
+ /* fill the data buffer with the data we want to freeze */
+ dptr = data;
+ Move(buf, dptr, sizeof(buf), char);
+ dptr += sizeof(buf);
+ Move(&sb->parent[0], dptr, psize, char);
+ dptr += psize;
+ Move(&sb->servers[0], dptr, ssize, char);
+ dptr += ssize;
+ Move(&sb->global, dptr, sizeof(global_score), char);
+
+ /* an equivalent C function can return 'data', in case of XS it'll
+ * try to convert char *data to PV, using strlen(), which will
+ * lose data, since it won't continue past the first \0
+ * char. Therefore in this case we explicitly return SV* and using
+ * newSVpvn(data, tsize) to tell the exact size */
+ retval = newSVpvn(data, tsize);
+ return retval;
+
+
+}
+
+
+static MP_INLINE
+SV *mpxs_Apache__Scoreboard_thaw(pTHX_ SV *Class, apr_pool_t *pool, SV *packet)
+{
+ modperl_scoreboard_t *image;
+ scoreboard *sb;
+ int psize, ssize;
+ char *ptr;
+
+ if (!(SvOK(packet) && SvCUR(packet) > (SIZE16*2))) {
+ return &PL_sv_undef;
+ }
+
+ image = (modperl_scoreboard_t *)apr_palloc(pool, sizeof(*image));
+ sb = (scoreboard *)apr_palloc(pool, sizeof(scoreboard));
+ sb->parent = (process_score *)apr_palloc(pool, sizeof(process_score *));
+ sb->servers = (worker_score **)apr_palloc(pool, server_limit * sizeof(worker_score));
+ sb->global = (global_score *)apr_palloc(pool, sizeof(global_score *));
+
+ ptr = SvPVX(packet);
+ psize = unpack16(ptr);
+ ptr += SIZE16;
+ ssize = unpack16(ptr);
+ ptr += SIZE16;
+
+ Move(ptr, &sb->parent[0], psize, char);
+ ptr += psize;
+ Move(ptr, &sb->servers[0], ssize, char);
+ ptr += ssize;
+ Move(ptr, &sb->global, sizeof(global_score), char);
+
+ image->pool = pool;
+ image->sb = sb;
+
+ return SvREFCNT_inc(mp_xs_Apache__Scoreboard_2obj(image));
+}
+
+static MP_INLINE
+modperl_scoreboard_t *mpxs_Apache__Scoreboard_image(pTHX_ SV *Class, apr_pool_t *pool)
+{
+ modperl_scoreboard_t *image;
+
+ image = (modperl_scoreboard_t *)apr_palloc(pool, sizeof(*image));
+
+ if (ap_exists_scoreboard_image()) {
+ image->sb = ap_scoreboard_image;
+ image->pool = pool;
+ }
+ else {
+ Perl_croak(aTHX_ "ap_scoreboard_image doesn't exist");
+ }
+
+ return image;
+
+}
+
+static MP_INLINE
+modperl_parent_score_t *mpxs_Apache__Scoreboard_parent_score(modperl_scoreboard_t *self, int idx)
+{
+ modperl_parent_score_t *mps;
+
+ if (self->sb->parent[idx].pid) {
+ mps = (modperl_parent_score_t *)apr_pcalloc(self->pool, (sizeof(*mps)));
+ mps->record = self->sb->parent[idx];
+ mps->idx = idx;
+ mps->sb = self->sb;
+ mps->pool = self->pool;
+ return mps;
+ }
+
+ return NULL;
+}
+
+static MP_INLINE
+modperl_worker_score_t *mpxs_Apache__Scoreboard_worker_score(pTHX_ modperl_scoreboard_t *self,
+ int parent_idx,
+ int worker_idx)
+{
+ modperl_worker_score_t *mws;
+ mws = (modperl_worker_score_t *)apr_pcalloc(self->pool, (sizeof(*mws)));
+
+ mws->record = self->sb->servers[parent_idx][worker_idx];
+ mws->parent_idx = parent_idx;
+ mws->worker_idx = worker_idx;
+
+ return mws;
+}
+
+
+static MP_INLINE
+SV *mpxs_Apache__Scoreboard_pids(pTHX_ modperl_scoreboard_t *self)
+{
+ AV *av = newAV();
+ int i;
+ scoreboard *sb = self->sb;
+
+ for (i = 0; i < 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));
+ }
+
+ return newRV_noinc((SV*)av);
+
+}
+
+/* XXX: need to move pid_t => apr_proc_t and work with pid->pid as in
+ * find_child_by_pid from scoreboard.c */
+static MP_INLINE
+int mpxs_Apache__Scoreboard_parent_idx_by_pid(pTHX_ modperl_scoreboard_t *self, pid_t pid)
+{
+ int i;
+ scoreboard *sb = self->sb;
+
+ for (i = 0; i < server_limit; i++) {
+ if (sb->parent[i].pid == pid) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/* return the thread numbers for a certain process idx */
+static MP_INLINE
+SV *mpxs_Apache__Scoreboard_thread_numbers(pTHX_ modperl_scoreboard_t *self, int parent_idx)
+{
+ AV *av = newAV();
+ int i;
+ scoreboard *sb = self->sb;
+
+ for (i = 0; i < thread_limit; ++i) {
+ // if (sb->servers[parent_idx][i].thread_num == NULL) {
+ // break;
+ // }
+ 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));
+ }
+
+ return newRV_noinc((SV*)av);
+
+}
+
+
+
+
+
+
+/* *** ParentScore *** */
+
+static MP_INLINE
+SV *mpxs_Apache__ScoreboardParentScore_next(pTHX_ modperl_parent_score_t *self)
+{
+ modperl_parent_score_t *next;
+ SV *retval = NULL;
+ int next_idx = self->idx + 1;
+
+ if (self->sb->parent[next_idx].pid) {
+ next = (modperl_parent_score_t *)apr_pcalloc(self->pool, sizeof(*next));
+ next->record = self->sb->parent[next_idx];
+ next->idx = next_idx;
+ next->sb = self->sb;
+ next->pool = self->pool;
+ retval = mp_xs_Apache__ScoreboardParentScore_2obj(next);
+ }
+
+ return retval ? SvREFCNT_inc(retval) : &PL_sv_undef;
+
+}
+
+static MP_INLINE
+modperl_worker_score_t *mpxs_Apache__ScoreboardParentScore_worker_score(modperl_parent_score_t *self)
+{
+ modperl_worker_score_t *mws;
+ mws = (modperl_worker_score_t *)apr_pcalloc(self->pool, sizeof(*mws));
+ mws->record = self->sb->servers[self->idx][0];
+ mws->parent_idx = self->idx;
+ mws->worker_idx = 0;
+ return mws;
+}
+
+
+
+static MP_INLINE
+SV *mpxs_Apache__ScoreboardParentScore_next_worker_score(pTHX_ modperl_parent_score_t *self,
+ modperl_worker_score_t *mws)
+{
+ modperl_worker_score_t *next;
+ SV *retval = NULL;
+ int next_idx = mws->worker_idx + 1;
+
+ if (next_idx < thread_limit) {
+ next = (modperl_worker_score_t *)apr_pcalloc(self->pool, sizeof(*next));
+ next->record = self->sb->servers[mws->parent_idx][next_idx];
+ next->parent_idx = mws->parent_idx;
+ next->worker_idx = next_idx;
+ retval = mp_xs_Apache__ScoreboardWorkerScore_2obj(next);
+ }
+
+ return retval ? SvREFCNT_inc(retval) : &PL_sv_undef;
+}
+
+static MP_INLINE
+SV *mpxs_Apache__ScoreboardParentScore_next_live_worker_score(pTHX_ modperl_parent_score_t *self,
+ modperl_worker_score_t *mws)
+{
+ modperl_worker_score_t *next;
+ SV *retval = NULL;
+ int next_idx = mws->worker_idx;
+
+ while (++next_idx < thread_limit) {
+ if (LIVE_WORKER(self->sb->servers[mws->parent_idx][next_idx])) {
+ next = (modperl_worker_score_t *)apr_pcalloc(self->pool, sizeof(*next));
+ next->record = self->sb->servers[mws->parent_idx][next_idx];
+ next->parent_idx = mws->parent_idx;
+ next->worker_idx = next_idx;
+ retval = mp_xs_Apache__ScoreboardWorkerScore_2obj(next);
+ break;
+ }
+ }
+
+ return retval ? SvREFCNT_inc(retval) : &PL_sv_undef;
+
+}
+
+static MP_INLINE
+SV *mpxs_Apache__ScoreboardParentScore_next_active_worker_score(pTHX_ modperl_parent_score_t *self,
+ modperl_worker_score_t *mws)
+{
+ modperl_worker_score_t *next;
+ SV *retval = NULL;
+ int next_idx = mws->worker_idx;
+
+ while (++next_idx < thread_limit) {
+ if (ACTIVE_WORKER(self->sb->servers[mws->parent_idx][next_idx])) {
+ next = (modperl_worker_score_t *)apr_pcalloc(self->pool, sizeof(*next));
+ next->record = self->sb->servers[mws->parent_idx][next_idx];
+ next->parent_idx = mws->parent_idx;
+ next->worker_idx = next_idx;
+ retval = mp_xs_Apache__ScoreboardWorkerScore_2obj(next);
+ break;
+ }
+ }
+
+ return retval ? SvREFCNT_inc(retval) : &PL_sv_undef;
+
+}
+
+
+/* *** WorkerScore *** */
+
+static XS(MPXS_Apache__ScoreboardWorkerScore_times)
+{
+ dXSARGS;
+ modperl_worker_score_t *self;
+
+ if (items != 1) {
+ Perl_croak(aTHX_ "usage: $worker_score->times");
+ }
+ self = mp_xs_sv2_Apache__ScoreboardWorkerScore(ST(0));
+
+ SP -= items;
+
+ 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))));
+ }
+ }
+
+ PUTBACK;
+}
+
+
+static XS(MPXS_Apache__ScoreboardWorkerScore_start_time)
+{
+ dXSARGS;
+ modperl_worker_score_t *self;
+ apr_time_t tp;
+
+ if (items != 1) {
+ Perl_croak(aTHX_ "usage: $worker_score->start_time");
+ }
+ self = mp_xs_sv2_Apache__ScoreboardWorkerScore(ST(0));
+
+ SP -= items;
+
+ tp = self->record.start_time;
+ /* fprintf(stderr, "start_time: %5" APR_TIME_T_FMT "\n", tp); */
+
+ /* do the same as Time::HiRes::gettimeofday */
+ if (GIMME == G_ARRAY) {
+ EXTEND(sp, 2);
+ PUSHs(sv_2mortal(newSViv(tp / APR_USEC_PER_SEC)));
+ PUSHs(sv_2mortal(newSViv(tp / APR_USEC_PER_SEC - tp % APR_USEC_PER_SEC )));
+ }
+ else {
+ EXTEND(sp, 1);
+ PUSHs(sv_2mortal(newSVnv((double)tp / APR_USEC_PER_SEC )));
+ }
+
+ PUTBACK;
+}
+
+/* XXX: this should be merged back into
+ * mpxs_Apache__Scoreboard_WorkerScore_start_time as an ALIAS when
+ * WrapXS provides it
+ */
+static XS(MPXS_Apache__ScoreboardWorkerScore_stop_time)
+{
+ dXSARGS;
+ modperl_worker_score_t *self;
+ apr_time_t tp;
+
+ if (items != 1) {
+ Perl_croak(aTHX_ "usage: $worker_score->stop_time");
+ }
+ self = mp_xs_sv2_Apache__ScoreboardWorkerScore(ST(0));
+
+ SP -= items;
+
+ tp = self->record.stop_time;
+ /* fprintf(stderr, "stop_time: %5" APR_TIME_T_FMT "\n", tp); */
+
+ /* do the same as Time::HiRes::gettimeofday */
+ if (GIMME == G_ARRAY) {
+ EXTEND(sp, 2);
+ PUSHs(sv_2mortal(newSViv(tp / APR_USEC_PER_SEC)));
+ PUSHs(sv_2mortal(newSViv(tp / APR_USEC_PER_SEC - tp % APR_USEC_PER_SEC )));
+ }
+ else {
+ EXTEND(sp, 1);
+ PUSHs(sv_2mortal(newSVnv((double)tp / APR_USEC_PER_SEC )));
+ }
+
+ PUTBACK;
+}
+
+static MP_INLINE
+long mpxs_Apache__ScoreboardWorkerScore_req_time(modperl_worker_score_t *self)
+{
+ long req_time;
+ if (self->record.start_time == 0L) {
+ req_time = 0L;
+ }
+ else {
+ req_time = (long)
+ ((self->record.stop_time - self->record.start_time) / 1000);
+ }
+ if (req_time < 0L || !self->record.access_count) {
+ req_time = 0L;
+ }
+
+ return req_time;
+
+}
+
+static MP_INLINE
+SV *mpxs_Apache__ScoreboardWorkerScore_status(pTHX_ modperl_worker_score_t *self)
+{
+ SV *sv = newSV(0);
+ sv_setnv(sv, (double)self->record.status);
+ sv_setpvf(sv, "%c", status_flags[self->record.status]);
+ SvNOK_on(sv); /* dual-var */
+ return sv;
+}
+
+/* Apache::ScoreboardGlobalScore functions */
+
--- /dev/null Thu Jan 1 07:30:00 1970
+++ xs/Apache/Scoreboard/Scoreboard_pm Thu Mar 14 00:44:51 2002
@@ -0,0 +1,56 @@
+use strict;
+use constant DEBUG => 0;
+
+my $ua;
+
+sub http_fetch {
+ my($self, $url) = @_;
+
+ require LWP::UserAgent;
+ unless ($ua) {
+ no strict 'vars';
+ $ua = LWP::UserAgent->new;
+ $ua->agent(join '/', __PACKAGE__, $VERSION);
+ }
+
+ my $request = HTTP::Request->new('GET', $url);
+ my $response = $ua->request($request);
+ unless ($response->is_success) {
+ warn "request failed: ", $response->status_line if DEBUG;
+ return undef;
+ }
+
+ my $type = $response->header('Content-type');
+ unless ($type eq Apache::Scoreboard::REMOTE_SCOREBOARD_TYPE) {
+ warn "invalid scoreboard Content-type: $type" if DEBUG;
+ return undef;
+ }
+
+ $response->content;
+}
+
+sub fetch {
+ my($self, $pool, $url) = @_;
+ $self->thaw($pool, $self->http_fetch($url));
+}
+
+sub fetch_store {
+ my($self, $url, $file) = @_;
+ $self->store($self->http_fetch($url), $file);
+}
+
+sub store {
+ my($self, $frozen_image, $file) = @_;
+ open my $fh, ">$file" or die "open $file: $!";
+ print $fh $frozen_image;
+ close $fh;
+}
+
+sub retrieve {
+ my($self, $pool, $file) = @_;
+ open my $fh, $file or die "open $file: $!";
+ local $/;
+ my $data = <$fh>;
+ close $fh;
+ $self->thaw($pool, $data);
+}
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://ticketmaster.com http://apacheweek.com
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: [patch] Apache::Scoreboard
Posted by Doug MacEachern <do...@covalent.net>.
On Tue, 26 Mar 2002, Stas Bekman wrote:
> So you want me to rewrite it in pure xs, right?
yeah.
> it won't work with WrapXS if it's not in the root.
right. from what i have seen, WrapXS is more of a burden for
Apache::Scoreboard than a help. so pure xs makes more sense here.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: [patch] Apache::Scoreboard
Posted by Stas Bekman <st...@stason.org>.
Doug MacEachern wrote:
> you could make it self contained in modperl-2.0/Apache-Scoreboard for the
> moment, the same way ModPerl-Registry is self contained. we can always
> move them later if needed.
So you want me to rewrite it in pure xs, right? it won't work with
WrapXS if it's not in the root.
__________________________________________________________________
Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org http://ticketmaster.com
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: [patch] Apache::Scoreboard
Posted by Doug MacEachern <do...@covalent.net>.
you could make it self contained in modperl-2.0/Apache-Scoreboard for the
moment, the same way ModPerl-Registry is self contained. we can always
move them later if needed.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: [patch] Apache::Scoreboard
Posted by Stas Bekman <st...@stason.org>.
Doug MacEachern wrote:
> two issues with this patch:
>
> - as i mentioned, the code for sending the scoreboard image doesn't belong
> tied to modperl, as it can be used in a server without modperl. there
> should be a mod_scoreboard_send.c that can be compiled with apxs without
> any perl stuff. it could then export an optional function for the perl
> wrapper to call the send function.
Of course, this is just temporary until the new home will be found.
I was thinking about putting this functionality into mod_status, instead
creating a new module. After all it already has a mode in which it
responds with something similar to an image.
> - looking at the patch, seems that WrapXS is more trouble than a help
> here. that is, normally WrapXS takes care of many things for you, but in
> this case it looks like too much extra effort is happening. there is so
> much mpxs_Apache__Scoreboard_* and _pm and DEFINE_* and MPXS_*'s that
> make the code harder to read and more difficult to maintain than if
> everything was done in a standard xs module without WrapXS.
Well, the interface is not much different from Apache::Scoreboard for
1.x, so no surprises here.
> i'm thinking at the very least, the code should be moved to a
> self-contained Apache-Scoreboard subdirectory, using standard xs.
> and given that mod_scoreboard_send.c should be usable without modperl,
> perhaps this stuff should not be part of the modperl core, but its own
> package like 1.x. thoughts?
Sure, this can be done. Though I'm really not interested in expanding
the ownership of the privately owned CPAN modules, but rather try to
move all my works somewhere where other people can fix problems if I'm
not around. So if the modules that I've developed or ported can be
hosted at apache.org cvs or elsewhere that's cool with me. I'll still be
the active developer/maintainer of these.
BTW, Doug, you can do the same for a bunch of the 1.x modules you own at
CPAN. I believe that putting the sources under public control will make
a better progress on these sources. Apache::Scoreboard comes to mind.
Just a thought.
So how about creating a new repository modperl-2.0-modules or
modperl-modules-2.0 and put Apache-Scoreboard there. Probably move
Apache-Test and ModPerl-Registry there too. That will allow us to keep
the core small, and still have a bunch of modules installable from one
directory. So we may end up distributing modperl-2.x and
modperl-modules-2.x and a combined version.
One concern is whether these modules can use WrapXS, it is going to be a
problem to split them away till Gerald will come back with a standalone
version.
__________________________________________________________________
Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org http://ticketmaster.com
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: [patch] Apache::Scoreboard
Posted by Doug MacEachern <do...@covalent.net>.
two issues with this patch:
- as i mentioned, the code for sending the scoreboard image doesn't belong
tied to modperl, as it can be used in a server without modperl. there
should be a mod_scoreboard_send.c that can be compiled with apxs without
any perl stuff. it could then export an optional function for the perl
wrapper to call the send function.
- looking at the patch, seems that WrapXS is more trouble than a help
here. that is, normally WrapXS takes care of many things for you, but in
this case it looks like too much extra effort is happening. there is so
much mpxs_Apache__Scoreboard_* and _pm and DEFINE_* and MPXS_*'s that
make the code harder to read and more difficult to maintain than if
everything was done in a standard xs module without WrapXS.
i'm thinking at the very least, the code should be moved to a
self-contained Apache-Scoreboard subdirectory, using standard xs.
and given that mod_scoreboard_send.c should be usable without modperl,
perhaps this stuff should not be part of the modperl core, but its own
package like 1.x. thoughts?
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org