| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifndef _WIN32
- #include <sys/ipc.h>
- #include <sys/msg.h>
- #include <dirent.h>
- #include <semaphore.h>
- #endif
- #include <time.h>
- #include <signal.h>
- #include <string.h>
- #include <errno.h>
- #include "agtmmap.h"
- #include "slap.h"
- #include "prthread.h"
- #include "prlock.h"
- #include "prerror.h"
- #include "prcvar.h"
- #include "plstr.h"
- #ifdef HPUX
- /* HP-UX doesn't define SEM_FAILED like other platforms, so
- * we define it ourselves. */
- #define SEM_FAILED ((sem_t *)(-1))
- #endif
- #define SNMP_NUM_SEM_WAITS 10
- #include "snmp_collator.h"
- #include "../snmp/ntagt/nslagtcom_nt.h"
- /* stevross: safe to assume port should be at most 5 digits ? */
- #define PORT_LEN 5
- /* strlen of url portions ie "ldap://:/" */
- #define URL_CHARS_LEN 9
- static char *make_ds_url(char *host, int port);
- static void print_snmp_interaction_table();
- static int search_interaction_table(char *dsURL, int *isnew);
- static void loadConfigStats();
- static Slapi_Entry *getConfigEntry( Slapi_Entry **e );
- static void freeConfigEntry( Slapi_Entry **e );
- static void snmp_update_ops_table();
- static void snmp_update_entries_table();
- static void snmp_update_interactions_table();
- static void snmp_update_cache_stats();
- static void snmp_collator_create_semaphore();
- static void snmp_collator_sem_wait();
- /* snmp stats stuff */
- struct agt_stats_t *stats=NULL;
- /* mmap stuff */
- static int hdl;
- /* collator stuff */
- static char *tmpstatsfile = AGT_STATS_FILE;
- #ifdef _WIN32
- static TCHAR szStatsFile[_MAX_PATH];
- static TCHAR szTempDir[_MAX_PATH];
- static HANDLE hParentProcess = NULL;
- static HANDLE hStatSlot = NULL;
- static HANDLE hLogFile = INVALID_HANDLE_VALUE;
- static TCHAR szSpoolRootDir[_MAX_PATH];
- #else
- static char szStatsFile[_MAX_PATH];
- static char stats_sem_name[_MAX_PATH];
- #endif /* _WIN32*/
- static Slapi_Eq_Context snmp_eq_ctx;
- static int snmp_collator_stopped = 0;
- /* synchronization stuff */
- static PRLock *interaction_table_mutex;
- static sem_t *stats_sem;
- /***********************************************************************************
- *
- * int snmp_collator_init()
- *
- * initializes the global variables used by snmp
- *
- ************************************************************************************/
- static int snmp_collator_init(){
- int i;
- /*
- * Create the global SNMP counters
- */
- g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsInOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsReadOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsCompareOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsListOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsSearchOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsReferrals = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsChainings = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsErrors = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsConnections = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsBytesRecv = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsBytesSent = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned = slapi_counter_new();
- g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned = slapi_counter_new();
- g_get_global_snmp_vars()->entries_tbl.dsMasterEntries = slapi_counter_new();
- g_get_global_snmp_vars()->entries_tbl.dsCopyEntries = slapi_counter_new();
- g_get_global_snmp_vars()->entries_tbl.dsCacheEntries = slapi_counter_new();
- g_get_global_snmp_vars()->entries_tbl.dsCacheHits = slapi_counter_new();
- g_get_global_snmp_vars()->entries_tbl.dsSlaveHits = slapi_counter_new();
- /* Initialize the global interaction table */
- for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
- {
- g_get_global_snmp_vars()->int_tbl[i].dsIntIndex = i + 1;
- strncpy(g_get_global_snmp_vars()->int_tbl[i].dsName, "Not Available",
- sizeof(g_get_global_snmp_vars()->int_tbl[i].dsName));
- g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation = 0;
- g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt = 0;
- g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess = 0;
- g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess = 0;
- g_get_global_snmp_vars()->int_tbl[i].dsFailures = 0;
- g_get_global_snmp_vars()->int_tbl[i].dsSuccesses = 0;
- strncpy(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available",
- sizeof(g_get_global_snmp_vars()->int_tbl[i].dsURL));
- }
- /* Get the semaphore */
- snmp_collator_sem_wait();
- /* Initialize the mmap structure */
- memset((void *) stats, 0, sizeof(*stats));
- /* Load header stats table */
- strncpy(stats->hdr_stats.dsVersion, SLAPD_VERSION_STR,
- (sizeof(stats->hdr_stats.dsVersion)/sizeof(char)) - 1);
- stats->hdr_stats.restarted = 0;
- stats->hdr_stats.startTime = time(0); /* This is a bit off, hope it's ok */
- loadConfigStats();
- /* update the mmap'd tables */
- snmp_update_ops_table();
- snmp_update_entries_table();
- snmp_update_interactions_table();
- /* Release the semaphore */
- sem_post(stats_sem);
- /* create lock for interaction table */
- interaction_table_mutex = PR_NewLock();
- return 0;
- }
- /***********************************************************************************
- * given the name, whether or not it was successful and the URL updates snmp
- * interaction table appropriately
- *
- *
- ************************************************************************************/
- void set_snmp_interaction_row(char *host, int port, int error)
- {
- int index;
- int isnew;
- char *dsName;
- char *dsURL;
- /* stevross: our servers don't have a concept of dsName as a distinguished name
- as specified in the MIB. Make this "Not Available" for now waiting for
- sometime in the future when we do
- */
-
-
- dsName = "Not Available";
- dsURL= make_ds_url(host, port);
- /* lock around here to avoid race condition of two threads trying to update table at same time */
- PR_Lock(interaction_table_mutex);
- index = search_interaction_table(dsURL, &isnew);
-
- if(isnew){
- /* fillin the new row from scratch*/
- g_get_global_snmp_vars()->int_tbl[index].dsIntIndex = index;
- strncpy(g_get_global_snmp_vars()->int_tbl[index].dsName, dsName,
- sizeof(g_get_global_snmp_vars()->int_tbl[index].dsName));
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfCreation = time(0);
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0);
- if(error == 0){
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0);
- g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
- g_get_global_snmp_vars()->int_tbl[index].dsFailures = 0;
- g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 1;
- }else{
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = 0;
- g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 1;
- g_get_global_snmp_vars()->int_tbl[index].dsFailures = 1;
- g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 0;
- }
- strncpy(g_get_global_snmp_vars()->int_tbl[index].dsURL, dsURL,
- sizeof(g_get_global_snmp_vars()->int_tbl[index].dsURL));
- }else{
- /* just update the appropriate fields */
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0);
- if(error == 0){
- g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0);
- g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
- g_get_global_snmp_vars()->int_tbl[index].dsSuccesses += 1;
- }else{
- g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess +=1;
- g_get_global_snmp_vars()->int_tbl[index].dsFailures +=1;
- }
- }
- PR_Unlock(interaction_table_mutex);
- /* free the memory allocated for dsURL in call to ds_make_url */
- if(dsURL != NULL){
- slapi_ch_free( (void**)&dsURL );
- }
- }
- /***********************************************************************************
- * Given: host and port
- * Returns: ldapUrl in form of
- * ldap://host.mcom.com:port/
- *
- * this should point to root DSE
- ************************************************************************************/
- static char *make_ds_url(char *host, int port){
- char *url;
-
- url = slapi_ch_smprintf("ldap://%s:%d/",host, port);
-
- return url;
- }
- /***********************************************************************************
- * searches the table for the url specified
- * If there, returns index to update stats
- * if, not there returns index of oldest interaction, and isnew flag is set
- * so caller can rewrite this row
- ************************************************************************************/
- static int search_interaction_table(char *dsURL, int *isnew)
- {
- int i;
- int index = 0;
- time_t oldestattempt;
- time_t currentattempt;
-
- oldestattempt = g_get_global_snmp_vars()->int_tbl[0].dsTimeOfLastAttempt;
- *isnew = 1;
-
- for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++){
- if(!strcmp(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available"))
- {
- /* found it -- this is new, first time for this row */
- index = i;
- break;
- }else if(!strcmp(g_get_global_snmp_vars()->int_tbl[i].dsURL, dsURL)){
- /* found it -- it was already there*/
- *isnew = 0;
- index = i;
- break;
- }else{
- /* not found so figure out oldest row */
- currentattempt = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt;
-
- if(currentattempt <= oldestattempt){
- index=i;
- oldestattempt = currentattempt;
- }
- }
- }
-
- return index;
- }
- /* for debuging until subagent part working, print contents of interaction table */
- static void print_snmp_interaction_table()
- {
- int i;
- for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
- {
- fprintf(stderr, " dsIntIndex: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsIntIndex);
- fprintf(stderr, " dsName: %s \n", g_get_global_snmp_vars()->int_tbl[i].dsName);
- fprintf(stderr, " dsTimeOfCreation: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation);
- fprintf(stderr, " dsTimeOfLastAttempt: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt);
- fprintf(stderr, " dsTimeOfLastSuccess: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess);
- fprintf(stderr, "dsFailuresSinceLastSuccess: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess);
- fprintf(stderr, " dsFailures: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsFailures);
- fprintf(stderr, " dsSuccesses: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsSuccesses);
- fprintf(stderr, " dsURL: %s \n", g_get_global_snmp_vars()->int_tbl[i].dsURL);
- fprintf(stderr, "\n");
- }
- }
- /*-------------------------------------------------------------------------
- *
- * sc_setevent: Sets the specified event (NT only). The input event has
- * to be created by the subagent during its initialization.
- *
- * Returns: None
- *
- *-----------------------------------------------------------------------*/
- #ifdef _WIN32
- void sc_setevent(char *ev)
- {
- HANDLE hTrapEvent;
- DWORD err = NO_ERROR;
-
- /*
- * Set the event handle to force NT SNMP service to call the subagent
- * DLL to generate a trap. Any error will be ignored as the subagent
- * may not have been loaded.
- */
- if ((hTrapEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE,
- (LPCTSTR) ev)) != NULL)
- {
- if (SetEvent(hTrapEvent) == FALSE)
- err = GetLastError();
- }
- else
- err = GetLastError();
- if (err != NO_ERROR)
- {
- fprintf(stderr, "Failed to set trap (error = %d).\n", err);
- }
- }
- #endif
- /***********************************************************************************
- *
- * int snmp_collator_start()
- *
- * open the memory map and initialize the variables
- * initializes the global variables used by snmp
- *
- * starts the collator thread
- ************************************************************************************/
- int snmp_collator_start()
- {
- int err;
- char *statspath = config_get_rundir();
- char *instdir = config_get_configdir();
- char *instname = NULL;
- /*
- * Get directory for our stats file
- */
- if (NULL == statspath) {
- statspath = slapi_ch_strdup("/tmp");
- }
- instname = PL_strrstr(instdir, "slapd-");
- if (!instname) {
- instname = PL_strrstr(instdir, "/");
- if (instname) {
- instname++;
- }
- }
- PR_snprintf(szStatsFile, sizeof(szStatsFile), "%s/%s%s",
- statspath, instname, AGT_STATS_EXTENSION);
- PR_snprintf(stats_sem_name, sizeof(stats_sem_name), "/%s%s",
- instname, AGT_STATS_EXTENSION);
- tmpstatsfile = szStatsFile;
- slapi_ch_free_string(&statspath);
- slapi_ch_free_string(&instdir);
- /* open the memory map */
- if ((err = agt_mopen_stats(tmpstatsfile, O_RDWR, &hdl) != 0))
- {
- if (err != EEXIST) /* Ignore if file already exists */
- {
- slapi_log_error(SLAPI_LOG_FATAL, "snmp collator", "Failed to open stats file (%s) "
- "(error %d): %s.\n", szStatsFile, err, slapd_system_strerror(err));
- exit(1);
- }
- }
- /* Create semaphore for stats file access */
- snmp_collator_create_semaphore();
- /* point stats struct at mmap data */
- stats = (struct agt_stats_t *) mmap_tbl [hdl].fp;
- /* initialize stats data */
- snmp_collator_init();
- /* Arrange to be called back periodically to update the mmap'd stats file. */
- snmp_eq_ctx = slapi_eq_repeat(snmp_collator_update, NULL, (time_t)0,
- SLAPD_SNMP_UPDATE_INTERVAL);
- return 0;
- }
- /***********************************************************************************
- *
- * int snmp_collator_stop()
- *
- * stops the collator thread
- * closes the memory map
- * cleans up any needed memory
- *
- ************************************************************************************/
- int snmp_collator_stop()
- {
- int err;
- /* Abort any pending events */
- slapi_eq_cancel(snmp_eq_ctx);
- snmp_collator_stopped = 1;
- /* acquire the semaphore */
- snmp_collator_sem_wait();
- /* close the memory map */
- if ((err = agt_mclose_stats(hdl)) != 0)
- {
- fprintf(stderr, "Failed to close stats file (%s) (error = %d).",
- AGT_STATS_FILE, err);
- }
- if (remove(tmpstatsfile) != 0)
- {
- fprintf(stderr, "Failed to remove (%s) (error = %d).\n",
- tmpstatsfile, errno);
- }
- /* close and delete semaphore */
- sem_close(stats_sem);
- sem_unlink(stats_sem_name);
- /* delete lock */
- PR_DestroyLock(interaction_table_mutex);
- #ifdef _WIN32
- /* send the event so server down trap gets set on NT */
- sc_setevent(MAGT_NSEV_SNMPTRAP);
- #endif
- /* stevross: I probably need to free stats too... make sure to add that later */
-
- return 0;
- }
- /*
- * snmp_collator_create_semaphore()
- *
- * Create a semaphore to synchronize access to the stats file with
- * the SNMP sub-agent. NSPR doesn't support a trywait function
- * for semaphores, so we just use POSIX semaphores directly.
- */
- static void
- snmp_collator_create_semaphore()
- {
- /* First just try to create the semaphore. This should usually just work. */
- if ((stats_sem = sem_open(stats_sem_name, O_CREAT | O_EXCL, SLAPD_DEFAULT_FILE_MODE, 1)) == SEM_FAILED) {
- if (errno == EEXIST) {
- /* It appears that we didn't exit cleanly last time and left the semaphore
- * around. Recreate it since we don't know what state it is in. */
- sem_unlink(stats_sem_name);
- if ((stats_sem = sem_open(stats_sem_name, O_CREAT | O_EXCL, SLAPD_DEFAULT_FILE_MODE, 1)) == SEM_FAILED) {
- /* No dice */
- LDAPDebug( LDAP_DEBUG_ANY, "Failed to create semaphore for stats file (%s). Error %d.\n",
- szStatsFile, errno, 0 );
- exit(1);
- }
- } else {
- /* Some other problem occurred creating the semaphore. */
- LDAPDebug( LDAP_DEBUG_ANY, "Failed to create semaphore for stats file (%s). Error %d.\n",
- szStatsFile, errno, 0 );
- exit(1);
- }
- }
- /* If we've reached this point, everything should be good. */
- return;
- }
- /*
- * snmp_collator_sem_wait()
- *
- * A wrapper used to get the semaphore. We don't want to block,
- * but we want to retry a specified number of times in case the
- * semaphore is help by the sub-agent.
- */
- static void
- snmp_collator_sem_wait()
- {
- int i = 0;
- int got_sem = 0;
- for (i=0; i < SNMP_NUM_SEM_WAITS; i++) {
- if (sem_trywait(stats_sem) == 0) {
- got_sem = 1;
- break;
- }
- PR_Sleep(PR_SecondsToInterval(1));
- }
- if (!got_sem) {
- /* If we've been unable to get the semaphore, there's
- * something wrong (likely the sub-agent went out to
- * lunch). We remove the old semaphore and recreate
- * a new one to avoid hanging up the server. */
- sem_close(stats_sem);
- sem_unlink(stats_sem_name);
- snmp_collator_create_semaphore();
- }
- }
- /***********************************************************************************
- *
- * int snmp_collator_update()
- *
- * Event callback function that updates the mmap'd stats file
- * for the SNMP sub-agent. This will use a semaphore while
- * updating the stats file to prevent the SNMP sub-agent from
- * reading it in the middle of an update.
- *
- ************************************************************************************/
- void
- snmp_collator_update(time_t start_time, void *arg)
- {
- if (snmp_collator_stopped) {
- return;
- }
- /* force an update of the backend cache stats. */
- snmp_update_cache_stats();
- /* get the semaphore */
- snmp_collator_sem_wait();
- /* just update the update time in the header */
- if( stats != NULL){
- stats->hdr_stats.updateTime = time(0);
- }
- /* update the mmap'd tables */
- snmp_update_ops_table();
- snmp_update_entries_table();
- snmp_update_interactions_table();
- /* release the semaphore */
- sem_post(stats_sem);
- }
- /*
- * snmp_update_ops_table()
- *
- * Updates the mmap'd operations table. The semaphore
- * should be acquired before you call this.
- */
- static void
- snmp_update_ops_table()
- {
- stats->ops_stats.dsAnonymousBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds);
- stats->ops_stats.dsUnAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
- stats->ops_stats.dsSimpleAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds);
- stats->ops_stats.dsStrongAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds);
- stats->ops_stats.dsBindSecurityErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
- stats->ops_stats.dsInOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsInOps);
- stats->ops_stats.dsReadOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReadOps);
- stats->ops_stats.dsCompareOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);
- stats->ops_stats.dsAddEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps);
- stats->ops_stats.dsRemoveEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps);
- stats->ops_stats.dsModifyEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps);
- stats->ops_stats.dsModifyRDNOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps);
- stats->ops_stats.dsListOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsListOps);
- stats->ops_stats.dsSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSearchOps);
- stats->ops_stats.dsOneLevelSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps);
- stats->ops_stats.dsWholeSubtreeSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps);
- stats->ops_stats.dsReferrals = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
- stats->ops_stats.dsChainings = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsChainings);
- stats->ops_stats.dsSecurityErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors);
- stats->ops_stats.dsErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsErrors);
- stats->ops_stats.dsConnections = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections);
- stats->ops_stats.dsConnectionSeq = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq);
- stats->ops_stats.dsBytesRecv = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv);
- stats->ops_stats.dsBytesSent = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent);
- stats->ops_stats.dsEntriesReturned = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
- stats->ops_stats.dsReferralsReturned = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned);
- }
- /*
- * snmp_update_entries_table()
- *
- * Updated the mmap'd entries table. The semaphore should
- * be acquired before you call this.
- */
- static void
- snmp_update_entries_table()
- {
- stats->entries_stats.dsMasterEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsMasterEntries);
- stats->entries_stats.dsCopyEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCopyEntries);
- stats->entries_stats.dsCacheEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries);
- stats->entries_stats.dsCacheHits = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits);
- stats->entries_stats.dsSlaveHits = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsSlaveHits);
- }
- /*
- * snmp_update_interactions_table()
- *
- * Updates the mmap'd interactions table. The semaphore should
- * be acquired before you call this.
- */
- static void
- snmp_update_interactions_table()
- {
- int i;
- for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++) {
- stats->int_stats[i].dsIntIndex = i;
- strncpy(stats->int_stats[i].dsName, g_get_global_snmp_vars()->int_tbl[i].dsName,
- sizeof(stats->int_stats[i].dsName));
- stats->int_stats[i].dsTimeOfCreation = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation;
- stats->int_stats[i].dsTimeOfLastAttempt = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt;
- stats->int_stats[i].dsTimeOfLastSuccess = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess;
- stats->int_stats[i].dsFailuresSinceLastSuccess = g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess;
- stats->int_stats[i].dsFailures = g_get_global_snmp_vars()->int_tbl[i].dsFailures;
- stats->int_stats[i].dsSuccesses = g_get_global_snmp_vars()->int_tbl[i].dsSuccesses;
- strncpy(stats->int_stats[i].dsURL, g_get_global_snmp_vars()->int_tbl[i].dsURL,
- sizeof(stats->int_stats[i].dsURL));
- }
- }
- /*
- * snmp_update_cache_stats()
- *
- * Reads the backend cache stats from the backend monitor entry and
- * updates the global counter used by the SNMP sub-agent as well as
- * the SNMP monitor entry.
- */
- static void
- snmp_update_cache_stats()
- {
- Slapi_Backend *be, *be_next;
- char *cookie = NULL;
- Slapi_PBlock *search_result_pb = NULL;
- Slapi_Entry **search_entries;
- int search_result;
- /* set the cache hits/cache entries info */
- be = slapi_get_first_backend(&cookie);
- if (!be)
- return;
- be_next = slapi_get_next_backend(cookie);
- slapi_ch_free ((void **) &cookie);
- /* for now, only do it if there is only 1 backend, otherwise don't know
- * which backend to pick */
- if(be_next == NULL)
- {
- Slapi_DN monitordn;
- slapi_sdn_init(&monitordn);
- be_getmonitordn(be,&monitordn);
-
- /* do a search on the monitor dn to get info */
- search_result_pb = slapi_search_internal( slapi_sdn_get_dn(&monitordn),
- LDAP_SCOPE_BASE,
- "objectclass=*",
- NULL,
- NULL,
- 0);
- slapi_sdn_done(&monitordn);
- slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);
- if(search_result == 0)
- {
- slapi_pblock_get( search_result_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
- &search_entries);
- /* set the entrycachehits */
- slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits,
- slapi_entry_attr_get_ulonglong(search_entries[0], "entrycachehits"));
-
- /* set the currententrycachesize */
- slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries,
- slapi_entry_attr_get_ulonglong(search_entries[0], "currententrycachesize"));
- }
- slapi_free_search_results_internal(search_result_pb);
- slapi_pblock_destroy(search_result_pb);
- }
- }
- static void
- add_counter_to_value(Slapi_Entry *e, const char *type, PRUint64 countervalue)
- {
- char value[40];
- PR_snprintf(value,sizeof(value),"%" NSPRIu64, countervalue);
- slapi_entry_attr_set_charptr( e, type, value);
- }
- void
- snmp_as_entry(Slapi_Entry *e)
- {
- add_counter_to_value(e,"AnonymousBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds));
- add_counter_to_value(e,"UnAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds));
- add_counter_to_value(e,"SimpleAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds));
- add_counter_to_value(e,"StrongAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds));
- add_counter_to_value(e,"BindSecurityErrors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors));
- add_counter_to_value(e,"InOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsInOps));
- add_counter_to_value(e,"ReadOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReadOps));
- add_counter_to_value(e,"CompareOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsCompareOps));
- add_counter_to_value(e,"AddEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps));
- add_counter_to_value(e,"RemoveEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps));
- add_counter_to_value(e,"ModifyEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps));
- add_counter_to_value(e,"ModifyRDNOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps));
- add_counter_to_value(e,"ListOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsListOps));
- add_counter_to_value(e,"SearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSearchOps));
- add_counter_to_value(e,"OneLevelSearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps));
- add_counter_to_value(e,"WholeSubtreeSearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps));
- add_counter_to_value(e,"Referrals", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferrals));
- add_counter_to_value(e,"Chainings", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsChainings));
- add_counter_to_value(e,"SecurityErrors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors));
- add_counter_to_value(e,"Errors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsErrors));
- add_counter_to_value(e,"Connections", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections));
- add_counter_to_value(e,"ConnectionSeq", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq));
- add_counter_to_value(e,"BytesRecv", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv));
- add_counter_to_value(e,"BytesSent", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent));
- add_counter_to_value(e,"EntriesReturned", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned));
- add_counter_to_value(e,"ReferralsReturned", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned));
- add_counter_to_value(e,"MasterEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsMasterEntries));
- add_counter_to_value(e,"CopyEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCopyEntries));
- add_counter_to_value(e,"CacheEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries));
- add_counter_to_value(e,"CacheHits", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits));
- add_counter_to_value(e,"SlaveHits", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsSlaveHits));
- }
- /*
- * loadConfigStats()
- *
- * Reads the header table SNMP settings and sets them in the mmap'd stats
- * file. This should be done only when the semaphore is held.
- */
- static void
- loadConfigStats() {
- Slapi_Entry *entry = NULL;
- char *name = NULL;
- char *desc = NULL;
- char *org = NULL;
- char *loc = NULL;
- char *contact = NULL;
- /* Read attributes from SNMP config entry */
- getConfigEntry( &entry );
- if ( entry != NULL ) {
- name = slapi_entry_attr_get_charptr( entry, SNMP_NAME_ATTR );
- desc = slapi_entry_attr_get_charptr( entry, SNMP_DESC_ATTR );
- org = slapi_entry_attr_get_charptr( entry, SNMP_ORG_ATTR );
- loc = slapi_entry_attr_get_charptr( entry, SNMP_LOC_ATTR );
- contact = slapi_entry_attr_get_charptr( entry, SNMP_CONTACT_ATTR );
- freeConfigEntry( &entry );
- }
- /* Load stats into table */
- if ( name != NULL) {
- PL_strncpyz(stats->hdr_stats.dsName, name, SNMP_FIELD_LENGTH);
- }
- if ( desc != NULL) {
- PL_strncpyz(stats->hdr_stats.dsDescription, desc, SNMP_FIELD_LENGTH);
- }
- if ( org != NULL) {
- PL_strncpyz(stats->hdr_stats.dsOrganization, org, SNMP_FIELD_LENGTH);
- }
- if ( loc != NULL) {
- PL_strncpyz(stats->hdr_stats.dsLocation, loc, SNMP_FIELD_LENGTH);
- }
- if ( contact != NULL) {
- PL_strncpyz(stats->hdr_stats.dsContact, contact, SNMP_FIELD_LENGTH);
- }
- /* Free strings */
- slapi_ch_free((void **) &name);
- slapi_ch_free((void **) &desc);
- slapi_ch_free((void **) &org);
- slapi_ch_free((void **) &loc);
- slapi_ch_free((void **) &contact);
- }
- static Slapi_Entry *
- getConfigEntry( Slapi_Entry **e ) {
- Slapi_DN sdn;
-
- slapi_sdn_init_dn_byref( &sdn, SNMP_CONFIG_DN );
- slapi_search_internal_get_entry( &sdn, NULL, e,
- plugin_get_default_component_id());
- slapi_sdn_done( &sdn );
- return *e;
- }
- static void
- freeConfigEntry( Slapi_Entry **e ) {
- if ( (e != NULL) && (*e != NULL) ) {
- slapi_entry_free( *e );
- *e = NULL;
- }
- }
|