/*
 * This file implements the ctApacheThreadStatusTable of the
 * COVALENT-APACHE-STATUSv2-MIB module.
 * $Id: apache-status-thread.c 8676 2008-01-17 23:11:17Z ispringer $
 */
/* General includes */
#include <sys/types.h>

/* Apache includes */ 
#include <httpd.h>
#include <scoreboard.h>
#include <ap_mpm.h>

/* SNMP includes */
#include "ucd-snmp-config.h"
#include "asn1.h"
#include "snmp.h"
#include "snmp_api.h"
#include "snmp_impl.h"
#include "snmp_debug.h"
#include "snmp_vars.h"
#include "var_struct.h"
#include <mibgroup/mibII/sysORTable.h>

/* module includes */
#include "covalent-snmp-config.h"
#include "snmpcommon/snmpcommon.h"
#include "apache-status-mib.h"

/* columnar objects of the ctApacheThreadStatusTable */
#define CTAPACHETHREADSTATUSINDEX              1
#define CTAPACHETHREADSTATUSPROCESSID          2
#define CTAPACHETHREADSTATUSTHREADID           3
#define CTAPACHETHREADSTATUSOPERSTATUS         4
#define CTAPACHETHREADSTATUSADMINSTATUS        5
#define CTAPACHETHREADSTATUSACCESSES           6
#define CTAPACHETHREADSTATUSBYTES              7
#define CTAPACHETHREADSTATUSREQUESTS           8
#define CTAPACHETHREADSTATUSREQUESTBYTES       9
#define CTAPACHETHREADSTATUSCONNECTIONBYTES    10
#define CTAPACHETHREADSTATUSCONNECTIONCOUNT    11
#define CTAPACHETHREADSTATUSSTARTTIME          12
#define CTAPACHETHREADSTATUSSTOPTIME           13
#define CTAPACHETHREADSTATUSCLIENT             14
#define CTAPACHETHREADSTATUSREQUEST            15
#define CTAPACHETHREADSTATUSVIRTUALHOST        16

#ifndef SNMP_MIN
#define SNMP_MIN(a,b)   (((a)<(b)) ? (a) : (b))
#endif

#define NEXT    FALSE
#define EXACT   TRUE
#define INDEX   2

#ifdef COVALENT_APACHE_STATUS_MIB
FindVarMethod read_ctApacheThreadStatusEntry;
unsigned char *
read_ctApacheThreadStatusEntry(struct variable *vp,
    oid *name, size_t *length,
    int exact, size_t *var_len, WriteMethod **write_method)
{
process_score *process_info;
int process_index;
worker_score *worker_info;
int thread_index;
/*
server_rec *vh;
*/
int servers_used = 0;
int hard_thread_limit = 0;
int hard_server_limit = 0;
int vpname_orig_len;

    ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED, &servers_used);
    ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &hard_server_limit);
    ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &hard_thread_limit);
    if ((servers_used < 0) || (hard_server_limit < servers_used)) {
        servers_used = hard_server_limit;
    }
    process_index = 0;
    thread_index = 0;
    vpname_orig_len = vp->namelen;
    do {
        process_index++;
        vp->namelen = vpname_orig_len;
        process_index = get_ctApacheProcessStatusIndex(vp, name, length,
                                INDEX, process_index, servers_used);
        if (process_index < 0) {
            return(NULL);
        }
        thread_index = get_ctApacheThreadStatusIndex(vp, name, length,
                                exact, process_index, hard_thread_limit);
    } while (thread_index < 0);

    worker_info = ap_get_scoreboard_worker((process_index - 1),
                                            (thread_index - 1));
    process_info = ap_get_scoreboard_process(process_index - 1);

    if ((worker_info == NULL) || (process_info == NULL)) {
        return(NULL);
    }

    *length = vp->namelen;
    memcpy( (char *)name,(char *)vp->name, *length * sizeof(oid));
    *var_len = sizeof(long_return);
    *write_method = 0;
    switch (vp->magic) {
	case CTAPACHETHREADSTATUSPROCESSID:
            long_return = process_info->pid;
	    return (unsigned char *) &long_return;
        case CTAPACHETHREADSTATUSTHREADID:
            long_return = worker_info->thread_num;
            return (unsigned char *) &long_return;
	case CTAPACHETHREADSTATUSOPERSTATUS:
	    long_return = worker_info->status + 1;
	    return (unsigned char *) &long_return;
	case CTAPACHETHREADSTATUSADMINSTATUS:
	    long_return = 1; /* Always up, otherwise it is not there. */
	    return (unsigned char *) &long_return;
	case CTAPACHETHREADSTATUSACCESSES:
            long_return = worker_info->access_count;
            return (unsigned char *) &long_return;
	case CTAPACHETHREADSTATUSBYTES:
			/* Need to cast to long, since result is Conunter32 */
            long_return = (long) worker_info->bytes_served;
            return (unsigned char *) &long_return;
	case CTAPACHETHREADSTATUSREQUESTS:
            long_return = worker_info->my_access_count;
            return (unsigned char *) &long_return;
	case CTAPACHETHREADSTATUSREQUESTBYTES:
			/* Need to cast to long, since result is Conunter32 */
            long_return = (long) worker_info->my_bytes_served;
            return (unsigned char *) &long_return;
	case CTAPACHETHREADSTATUSCONNECTIONBYTES:
			/* Need to cast to long, since result is Conunter32 */
            long_return = (long) worker_info->conn_bytes;
            return (unsigned char *) &long_return;
	case CTAPACHETHREADSTATUSCONNECTIONCOUNT:
            long_return = worker_info->conn_count;
            return (unsigned char *) &long_return;
/* Currently not implemented correctly!!
	case CTAPACHETHREADSTATUSSTARTTIME:
	    *var_len = sizeof(long_return);
            long_return = worker_info->start_time;
            return (unsigned char *) &long_return;
	case CTAPACHETHREADSTATUSSTOPTIME:
	    *var_len = sizeof(long_return);
            long_return = worker_info->stop_time;
            return (unsigned char *) &long_return;
*/
	case CTAPACHETHREADSTATUSCLIENT:
	    *var_len = strlen(worker_info->client);
	    return (unsigned char *) worker_info->client;
	case CTAPACHETHREADSTATUSREQUEST:
	    *var_len = strlen(worker_info->request);
	    return (unsigned char *) worker_info->request;
	case CTAPACHETHREADSTATUSVIRTUALHOST:
	    long_return = 0;
        /*
		if (process_info->generation == ap_my_generation) {
            vh = worker_info->vhostrec;
            if (vh != NULL) {
                long_return = get_www_service_index(vh);
			}
		}
		*/
	    return (unsigned char *) &long_return;
        default:
            return NULL;
    }
}

/* We add a 0 as last OID to be filled with the applIndex. Each registration */
/* is by t his implementation limited to only 1 entry.                       */
/* (Makes table implementation like scalars which is simple and allows for   */
/* multiple registrations of Apache)                                         */
static oid ctApacheThreadStatusEntry_oid[] = { 1, 3, 6, 1, 4, 1, 6100, 12, 1, 2, 1};
static struct variable2 ctApacheThreadStatusEntry_variables[] = {
    { CTAPACHETHREADSTATUSPROCESSID, ASN_UNSIGNED, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {2, 0} },
    { CTAPACHETHREADSTATUSTHREADID, ASN_UNSIGNED, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {3, 0} },
    { CTAPACHETHREADSTATUSOPERSTATUS, ASN_INTEGER, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {4, 0} },
    { CTAPACHETHREADSTATUSADMINSTATUS, ASN_INTEGER, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {5, 0} },
    { CTAPACHETHREADSTATUSACCESSES, ASN_COUNTER, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {6, 0} },
    { CTAPACHETHREADSTATUSBYTES, ASN_COUNTER, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {7, 0} },
    { CTAPACHETHREADSTATUSREQUESTS, ASN_COUNTER, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {8, 0} },
    { CTAPACHETHREADSTATUSREQUESTBYTES, ASN_COUNTER, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {9, 0} },
    { CTAPACHETHREADSTATUSCONNECTIONBYTES, ASN_COUNTER, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {10, 0} },
    { CTAPACHETHREADSTATUSCONNECTIONCOUNT, ASN_COUNTER, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {11, 0} },
    { CTAPACHETHREADSTATUSSTARTTIME, ASN_TIMETICKS, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {12, 0} },
    { CTAPACHETHREADSTATUSSTOPTIME, ASN_TIMETICKS, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {13, 0} },
    { CTAPACHETHREADSTATUSCLIENT, ASN_OCTET_STR, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {14, 0} },
    { CTAPACHETHREADSTATUSREQUEST, ASN_OCTET_STR, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {15, 0} },
    { CTAPACHETHREADSTATUSVIRTUALHOST, ASN_UNSIGNED, RONLY,
                                read_ctApacheThreadStatusEntry, 2, {16, 0} }
};

void
init_covalent_apache_status_thread()
{
int appl_index;
int i;

    appl_index = get_appl_index();
    for (i = 0;
         i < (sizeof(ctApacheThreadStatusEntry_variables)/sizeof(struct variable2));
         i++) {
       ctApacheThreadStatusEntry_variables[i].name[1] = appl_index;
    }
    REGISTER_MIB("covalent-apache-status-mib/ctApacheThreadStatusTable",
		ctApacheThreadStatusEntry_variables, variable2,
		ctApacheThreadStatusEntry_oid);
#ifdef USING_MIBII_SYSORTABLE_MODULE
    register_sysORTable(ctApacheThreadStatusEntry_oid, 10,
		"The Covalent Apache Server MIB module");
#endif /* USING_MIBII_SYSORTABLE_MODULE */
}
#endif /* COVALENT_APACHE_SERVER_STATUS_MIB */



