1
/** BEGIN COPYRIGHT BLOCK
2
* This Program is free software; you can redistribute it and/or modify it under
3
* the terms of the GNU General Public License as published by the Free Software
4
* Foundation; version 2 of the License.
6
* This Program is distributed in the hope that it will be useful, but WITHOUT
7
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10
* You should have received a copy of the GNU General Public License along with
11
* this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
12
* Place, Suite 330, Boston, MA 02111-1307 USA.
14
* In addition, as a special exception, Red Hat, Inc. gives You the additional
15
* right to link the code of this Program with code not covered under the GNU
16
* General Public License ("Non-GPL Code") and to distribute linked combinations
17
* including the two, subject to the limitations in this paragraph. Non-GPL Code
18
* permitted under this exception must only link to the code of this Program
19
* through those well defined interfaces identified in the file named EXCEPTION
20
* found in the source code files (the "Approved Interfaces"). The files of
21
* Non-GPL Code may instantiate templates or use macros or inline functions from
22
* the Approved Interfaces without causing the resulting work to be covered by
23
* the GNU General Public License. Only Red Hat, Inc. may make changes or
24
* additions to the list of Approved Interfaces. You must obey the GNU General
25
* Public License in all respects for all of the Program code and other code used
26
* in conjunction with the Program except the Non-GPL Code covered by this
27
* exception. If you modify this file, you may extend this exception to your
28
* version of the file, but you are not obligated to do so. If you do not wish to
29
* provide this exception without modification, you must delete this exception
30
* statement from your version and license this file solely under the GPL without
34
* Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
35
* Copyright (C) 2005 Red Hat, Inc.
36
* All rights reserved.
37
* END COPYRIGHT BLOCK **/
45
#include <sys/types.h>
51
#include <semaphore.h>
67
/* HP-UX doesn't define SEM_FAILED like other platforms, so
68
* we define it ourselves. */
69
#define SEM_FAILED ((sem_t *)(-1))
72
#define SNMP_NUM_SEM_WAITS 10
74
#include "snmp_collator.h"
75
#include "../snmp/ntagt/nslagtcom_nt.h"
77
/* stevross: safe to assume port should be at most 5 digits ? */
79
/* strlen of url portions ie "ldap://:/" */
80
#define URL_CHARS_LEN 9
82
static char *make_ds_url(char *host, int port);
83
#ifdef DEBUG_SNMP_INTERACTION
84
static void print_snmp_interaction_table();
85
#endif /* DEBUG_SNMP_INTERACTION */
86
static int search_interaction_table(char *dsURL, int *isnew);
87
static void loadConfigStats();
88
static Slapi_Entry *getConfigEntry( Slapi_Entry **e );
89
static void freeConfigEntry( Slapi_Entry **e );
90
static void snmp_update_ops_table();
91
static void snmp_update_entries_table();
92
static void snmp_update_interactions_table();
93
static void snmp_update_cache_stats();
94
static void snmp_collator_create_semaphore();
95
static void snmp_collator_sem_wait();
97
/* snmp stats stuff */
98
struct agt_stats_t *stats=NULL;
104
static char *tmpstatsfile = AGT_STATS_FILE;
106
static TCHAR szStatsFile[_MAX_PATH];
107
static TCHAR szTempDir[_MAX_PATH];
108
static HANDLE hParentProcess = NULL;
109
static HANDLE hStatSlot = NULL;
110
static HANDLE hLogFile = INVALID_HANDLE_VALUE;
111
static TCHAR szSpoolRootDir[_MAX_PATH];
113
static char szStatsFile[_MAX_PATH];
114
static char stats_sem_name[_MAX_PATH];
116
static Slapi_Eq_Context snmp_eq_ctx;
117
static int snmp_collator_stopped = 0;
119
/* synchronization stuff */
120
static PRLock *interaction_table_mutex;
121
static sem_t *stats_sem;
124
/***********************************************************************************
126
* int snmp_collator_init()
128
* initializes the global variables used by snmp
130
************************************************************************************/
132
static int snmp_collator_init(){
136
* Create the global SNMP counters
138
g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds = slapi_counter_new();
139
g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds = slapi_counter_new();
140
g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds = slapi_counter_new();
141
g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds = slapi_counter_new();
142
g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors = slapi_counter_new();
143
g_get_global_snmp_vars()->ops_tbl.dsInOps = slapi_counter_new();
144
g_get_global_snmp_vars()->ops_tbl.dsReadOps = slapi_counter_new();
145
g_get_global_snmp_vars()->ops_tbl.dsCompareOps = slapi_counter_new();
146
g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps = slapi_counter_new();
147
g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps = slapi_counter_new();
148
g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps = slapi_counter_new();
149
g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps = slapi_counter_new();
150
g_get_global_snmp_vars()->ops_tbl.dsListOps = slapi_counter_new();
151
g_get_global_snmp_vars()->ops_tbl.dsSearchOps = slapi_counter_new();
152
g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps = slapi_counter_new();
153
g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps = slapi_counter_new();
154
g_get_global_snmp_vars()->ops_tbl.dsReferrals = slapi_counter_new();
155
g_get_global_snmp_vars()->ops_tbl.dsChainings = slapi_counter_new();
156
g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors = slapi_counter_new();
157
g_get_global_snmp_vars()->ops_tbl.dsErrors = slapi_counter_new();
158
g_get_global_snmp_vars()->ops_tbl.dsConnections = slapi_counter_new();
159
g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq = slapi_counter_new();
160
g_get_global_snmp_vars()->ops_tbl.dsBytesRecv = slapi_counter_new();
161
g_get_global_snmp_vars()->ops_tbl.dsBytesSent = slapi_counter_new();
162
g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned = slapi_counter_new();
163
g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned = slapi_counter_new();
164
g_get_global_snmp_vars()->entries_tbl.dsMasterEntries = slapi_counter_new();
165
g_get_global_snmp_vars()->entries_tbl.dsCopyEntries = slapi_counter_new();
166
g_get_global_snmp_vars()->entries_tbl.dsCacheEntries = slapi_counter_new();
167
g_get_global_snmp_vars()->entries_tbl.dsCacheHits = slapi_counter_new();
168
g_get_global_snmp_vars()->entries_tbl.dsSlaveHits = slapi_counter_new();
170
/* Initialize the global interaction table */
171
for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
173
g_get_global_snmp_vars()->int_tbl[i].dsIntIndex = i + 1;
174
strncpy(g_get_global_snmp_vars()->int_tbl[i].dsName, "Not Available",
175
sizeof(g_get_global_snmp_vars()->int_tbl[i].dsName));
176
g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation = 0;
177
g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt = 0;
178
g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess = 0;
179
g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess = 0;
180
g_get_global_snmp_vars()->int_tbl[i].dsFailures = 0;
181
g_get_global_snmp_vars()->int_tbl[i].dsSuccesses = 0;
182
strncpy(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available",
183
sizeof(g_get_global_snmp_vars()->int_tbl[i].dsURL));
186
/* Get the semaphore */
187
snmp_collator_sem_wait();
189
/* Initialize the mmap structure */
190
memset((void *) stats, 0, sizeof(*stats));
192
/* Load header stats table */
193
strncpy(stats->hdr_stats.dsVersion, SLAPD_VERSION_STR,
194
(sizeof(stats->hdr_stats.dsVersion)/sizeof(char)) - 1);
195
stats->hdr_stats.restarted = 0;
196
stats->hdr_stats.startTime = time(0); /* This is a bit off, hope it's ok */
199
/* update the mmap'd tables */
200
snmp_update_ops_table();
201
snmp_update_entries_table();
202
snmp_update_interactions_table();
204
/* Release the semaphore */
207
/* create lock for interaction table */
208
interaction_table_mutex = PR_NewLock();
215
/***********************************************************************************
216
* given the name, whether or not it was successful and the URL updates snmp
217
* interaction table appropriately
220
************************************************************************************/
222
void set_snmp_interaction_row(char *host, int port, int error)
229
/* stevross: our servers don't have a concept of dsName as a distinguished name
230
as specified in the MIB. Make this "Not Available" for now waiting for
231
sometime in the future when we do
235
dsName = "Not Available";
237
dsURL= make_ds_url(host, port);
239
/* lock around here to avoid race condition of two threads trying to update table at same time */
240
PR_Lock(interaction_table_mutex);
241
index = search_interaction_table(dsURL, &isnew);
244
/* fillin the new row from scratch*/
245
g_get_global_snmp_vars()->int_tbl[index].dsIntIndex = index;
246
strncpy(g_get_global_snmp_vars()->int_tbl[index].dsName, dsName,
247
sizeof(g_get_global_snmp_vars()->int_tbl[index].dsName));
248
g_get_global_snmp_vars()->int_tbl[index].dsTimeOfCreation = time(0);
249
g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0);
251
g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0);
252
g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
253
g_get_global_snmp_vars()->int_tbl[index].dsFailures = 0;
254
g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 1;
256
g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = 0;
257
g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 1;
258
g_get_global_snmp_vars()->int_tbl[index].dsFailures = 1;
259
g_get_global_snmp_vars()->int_tbl[index].dsSuccesses = 0;
261
strncpy(g_get_global_snmp_vars()->int_tbl[index].dsURL, dsURL,
262
sizeof(g_get_global_snmp_vars()->int_tbl[index].dsURL));
264
/* just update the appropriate fields */
265
g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt = time(0);
267
g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess = time(0);
268
g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
269
g_get_global_snmp_vars()->int_tbl[index].dsSuccesses += 1;
271
g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess +=1;
272
g_get_global_snmp_vars()->int_tbl[index].dsFailures +=1;
276
PR_Unlock(interaction_table_mutex);
277
/* free the memory allocated for dsURL in call to ds_make_url */
279
slapi_ch_free( (void**)&dsURL );
283
/***********************************************************************************
284
* Given: host and port
285
* Returns: ldapUrl in form of
286
* ldap://host.mcom.com:port/
288
* this should point to root DSE
289
************************************************************************************/
290
static char *make_ds_url(char *host, int port){
294
url = slapi_ch_smprintf("ldap://%s:%d/",host, port);
300
/***********************************************************************************
301
* searches the table for the url specified
302
* If there, returns index to update stats
303
* if, not there returns index of oldest interaction, and isnew flag is set
304
* so caller can rewrite this row
305
************************************************************************************/
307
static int search_interaction_table(char *dsURL, int *isnew)
311
time_t oldestattempt;
312
time_t currentattempt;
314
oldestattempt = g_get_global_snmp_vars()->int_tbl[0].dsTimeOfLastAttempt;
317
for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++){
318
if(!strcmp(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available"))
320
/* found it -- this is new, first time for this row */
323
}else if(!strcmp(g_get_global_snmp_vars()->int_tbl[i].dsURL, dsURL)){
324
/* found it -- it was already there*/
329
/* not found so figure out oldest row */
330
currentattempt = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt;
332
if(currentattempt <= oldestattempt){
334
oldestattempt = currentattempt;
344
#ifdef DEBUG_SNMP_INTERACTION
345
/* for debuging until subagent part working, print contents of interaction table */
346
static void print_snmp_interaction_table()
349
for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
351
fprintf(stderr, " dsIntIndex: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsIntIndex);
352
fprintf(stderr, " dsName: %s \n", g_get_global_snmp_vars()->int_tbl[i].dsName);
353
fprintf(stderr, " dsTimeOfCreation: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation);
354
fprintf(stderr, " dsTimeOfLastAttempt: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt);
355
fprintf(stderr, " dsTimeOfLastSuccess: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess);
356
fprintf(stderr, "dsFailuresSinceLastSuccess: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess);
357
fprintf(stderr, " dsFailures: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsFailures);
358
fprintf(stderr, " dsSuccesses: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsSuccesses);
359
fprintf(stderr, " dsURL: %s \n", g_get_global_snmp_vars()->int_tbl[i].dsURL);
360
fprintf(stderr, "\n");
363
#endif /* DEBUG_SNMP_INTERACTION */
365
/*-------------------------------------------------------------------------
367
* sc_setevent: Sets the specified event (NT only). The input event has
368
* to be created by the subagent during its initialization.
372
*-----------------------------------------------------------------------*/
375
void sc_setevent(char *ev)
378
DWORD err = NO_ERROR;
381
* Set the event handle to force NT SNMP service to call the subagent
382
* DLL to generate a trap. Any error will be ignored as the subagent
383
* may not have been loaded.
385
if ((hTrapEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE,
386
(LPCTSTR) ev)) != NULL)
388
if (SetEvent(hTrapEvent) == FALSE)
389
err = GetLastError();
392
err = GetLastError();
396
fprintf(stderr, "Failed to set trap (error = %d).\n", err);
403
/***********************************************************************************
405
* int snmp_collator_start()
407
* open the memory map and initialize the variables
408
* initializes the global variables used by snmp
410
* starts the collator thread
411
************************************************************************************/
413
int snmp_collator_start()
417
char *statspath = config_get_rundir();
418
char *instdir = config_get_configdir();
419
char *instname = NULL;
422
* Get directory for our stats file
424
if (NULL == statspath) {
425
statspath = slapi_ch_strdup("/tmp");
428
instname = PL_strrstr(instdir, "slapd-");
430
instname = PL_strrstr(instdir, "/");
435
PR_snprintf(szStatsFile, sizeof(szStatsFile), "%s/%s%s",
436
statspath, instname, AGT_STATS_EXTENSION);
437
PR_snprintf(stats_sem_name, sizeof(stats_sem_name), "/%s%s",
438
instname, AGT_STATS_EXTENSION);
439
tmpstatsfile = szStatsFile;
440
slapi_ch_free_string(&statspath);
441
slapi_ch_free_string(&instdir);
443
/* open the memory map */
444
if ((err = agt_mopen_stats(tmpstatsfile, O_RDWR, &hdl) != 0))
446
if (err != EEXIST) /* Ignore if file already exists */
448
slapi_log_error(SLAPI_LOG_FATAL, "snmp collator", "Failed to open stats file (%s) "
449
"(error %d): %s.\n", szStatsFile, err, slapd_system_strerror(err));
454
/* Create semaphore for stats file access */
455
snmp_collator_create_semaphore();
457
/* point stats struct at mmap data */
458
stats = (struct agt_stats_t *) mmap_tbl [hdl].fp;
460
/* initialize stats data */
461
snmp_collator_init();
463
/* Arrange to be called back periodically to update the mmap'd stats file. */
464
snmp_eq_ctx = slapi_eq_repeat(snmp_collator_update, NULL, (time_t)0,
465
SLAPD_SNMP_UPDATE_INTERVAL);
470
/***********************************************************************************
472
* int snmp_collator_stop()
474
* stops the collator thread
475
* closes the memory map
476
* cleans up any needed memory
478
************************************************************************************/
480
int snmp_collator_stop()
484
if (snmp_collator_stopped) {
488
/* Abort any pending events */
489
slapi_eq_cancel(snmp_eq_ctx);
490
snmp_collator_stopped = 1;
492
/* acquire the semaphore */
493
snmp_collator_sem_wait();
495
/* close the memory map */
496
if ((err = agt_mclose_stats(hdl)) != 0)
498
fprintf(stderr, "Failed to close stats file (%s) (error = %d).",
499
AGT_STATS_FILE, err);
502
if (remove(tmpstatsfile) != 0)
504
fprintf(stderr, "Failed to remove (%s) (error = %d).\n",
505
tmpstatsfile, errno);
508
/* close and delete semaphore */
509
sem_close(stats_sem);
510
sem_unlink(stats_sem_name);
513
if (interaction_table_mutex) {
514
PR_DestroyLock(interaction_table_mutex);
518
/* send the event so server down trap gets set on NT */
519
sc_setevent(MAGT_NSEV_SNMPTRAP);
522
/* stevross: I probably need to free stats too... make sure to add that later */
528
* snmp_collator_create_semaphore()
530
* Create a semaphore to synchronize access to the stats file with
531
* the SNMP sub-agent. NSPR doesn't support a trywait function
532
* for semaphores, so we just use POSIX semaphores directly.
535
snmp_collator_create_semaphore()
537
/* First just try to create the semaphore. This should usually just work. */
538
if ((stats_sem = sem_open(stats_sem_name, O_CREAT | O_EXCL, SLAPD_DEFAULT_FILE_MODE, 1)) == SEM_FAILED) {
539
if (errno == EEXIST) {
540
/* It appears that we didn't exit cleanly last time and left the semaphore
541
* around. Recreate it since we don't know what state it is in. */
542
if (sem_unlink(stats_sem_name) != 0) {
543
LDAPDebug( LDAP_DEBUG_ANY, "Failed to delete old semaphore for stats file (%s). "
544
"Error %d (%s).\n", szStatsFile, errno, slapd_system_strerror(errno) );
548
if ((stats_sem = sem_open(stats_sem_name, O_CREAT | O_EXCL, SLAPD_DEFAULT_FILE_MODE, 1)) == SEM_FAILED) {
550
LDAPDebug( LDAP_DEBUG_ANY, "Failed to create semaphore for stats file (%s). Error %d (%s).\n",
551
szStatsFile, errno, slapd_system_strerror(errno) );
555
/* Some other problem occurred creating the semaphore. */
556
LDAPDebug( LDAP_DEBUG_ANY, "Failed to create semaphore for stats file (%s). Error %d.(%s)\n",
557
szStatsFile, errno, slapd_system_strerror(errno) );
562
/* If we've reached this point, everything should be good. */
567
* snmp_collator_sem_wait()
569
* A wrapper used to get the semaphore. We don't want to block,
570
* but we want to retry a specified number of times in case the
571
* semaphore is help by the sub-agent.
574
snmp_collator_sem_wait()
579
if (SEM_FAILED == stats_sem) {
580
LDAPDebug1Arg(LDAP_DEBUG_ANY,
581
"semaphore for stats file (%s) is not available.\n", szStatsFile);
585
for (i=0; i < SNMP_NUM_SEM_WAITS; i++) {
586
if (sem_trywait(stats_sem) == 0) {
590
PR_Sleep(PR_SecondsToInterval(1));
594
/* If we've been unable to get the semaphore, there's
595
* something wrong (likely the sub-agent went out to
596
* lunch). We remove the old semaphore and recreate
597
* a new one to avoid hanging up the server. */
598
sem_close(stats_sem);
599
sem_unlink(stats_sem_name);
600
snmp_collator_create_semaphore();
606
/***********************************************************************************
608
* int snmp_collator_update()
610
* Event callback function that updates the mmap'd stats file
611
* for the SNMP sub-agent. This will use a semaphore while
612
* updating the stats file to prevent the SNMP sub-agent from
613
* reading it in the middle of an update.
615
************************************************************************************/
618
snmp_collator_update(time_t start_time, void *arg)
620
if (snmp_collator_stopped) {
624
/* force an update of the backend cache stats. */
625
snmp_update_cache_stats();
627
/* get the semaphore */
628
snmp_collator_sem_wait();
630
/* just update the update time in the header */
632
stats->hdr_stats.updateTime = time(0);
635
/* update the mmap'd tables */
636
snmp_update_ops_table();
637
snmp_update_entries_table();
638
snmp_update_interactions_table();
640
/* release the semaphore */
645
* snmp_update_ops_table()
647
* Updates the mmap'd operations table. The semaphore
648
* should be acquired before you call this.
651
snmp_update_ops_table()
653
stats->ops_stats.dsAnonymousBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds);
654
stats->ops_stats.dsUnAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
655
stats->ops_stats.dsSimpleAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds);
656
stats->ops_stats.dsStrongAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds);
657
stats->ops_stats.dsBindSecurityErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
658
stats->ops_stats.dsInOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsInOps);
659
stats->ops_stats.dsReadOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReadOps);
660
stats->ops_stats.dsCompareOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);
661
stats->ops_stats.dsAddEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps);
662
stats->ops_stats.dsRemoveEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps);
663
stats->ops_stats.dsModifyEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps);
664
stats->ops_stats.dsModifyRDNOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps);
665
stats->ops_stats.dsListOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsListOps);
666
stats->ops_stats.dsSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSearchOps);
667
stats->ops_stats.dsOneLevelSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps);
668
stats->ops_stats.dsWholeSubtreeSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps);
669
stats->ops_stats.dsReferrals = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
670
stats->ops_stats.dsChainings = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsChainings);
671
stats->ops_stats.dsSecurityErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors);
672
stats->ops_stats.dsErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsErrors);
673
stats->ops_stats.dsConnections = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections);
674
stats->ops_stats.dsConnectionSeq = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq);
675
stats->ops_stats.dsBytesRecv = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv);
676
stats->ops_stats.dsBytesSent = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent);
677
stats->ops_stats.dsEntriesReturned = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
678
stats->ops_stats.dsReferralsReturned = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned);
682
* snmp_update_entries_table()
684
* Updated the mmap'd entries table. The semaphore should
685
* be acquired before you call this.
688
snmp_update_entries_table()
690
stats->entries_stats.dsMasterEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsMasterEntries);
691
stats->entries_stats.dsCopyEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCopyEntries);
692
stats->entries_stats.dsCacheEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries);
693
stats->entries_stats.dsCacheHits = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits);
694
stats->entries_stats.dsSlaveHits = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsSlaveHits);
698
* snmp_update_interactions_table()
700
* Updates the mmap'd interactions table. The semaphore should
701
* be acquired before you call this.
704
snmp_update_interactions_table()
708
for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++) {
709
stats->int_stats[i].dsIntIndex = i;
710
strncpy(stats->int_stats[i].dsName, g_get_global_snmp_vars()->int_tbl[i].dsName,
711
sizeof(stats->int_stats[i].dsName));
712
stats->int_stats[i].dsTimeOfCreation = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation;
713
stats->int_stats[i].dsTimeOfLastAttempt = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt;
714
stats->int_stats[i].dsTimeOfLastSuccess = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess;
715
stats->int_stats[i].dsFailuresSinceLastSuccess = g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess;
716
stats->int_stats[i].dsFailures = g_get_global_snmp_vars()->int_tbl[i].dsFailures;
717
stats->int_stats[i].dsSuccesses = g_get_global_snmp_vars()->int_tbl[i].dsSuccesses;
718
strncpy(stats->int_stats[i].dsURL, g_get_global_snmp_vars()->int_tbl[i].dsURL,
719
sizeof(stats->int_stats[i].dsURL));
724
* snmp_update_cache_stats()
726
* Reads the backend cache stats from the backend monitor entry and
727
* updates the global counter used by the SNMP sub-agent as well as
728
* the SNMP monitor entry.
731
snmp_update_cache_stats()
733
Slapi_Backend *be, *be_next;
735
Slapi_PBlock *search_result_pb = NULL;
736
Slapi_Entry **search_entries;
739
/* set the cache hits/cache entries info */
740
be = slapi_get_first_backend(&cookie);
744
be_next = slapi_get_next_backend(cookie);
746
slapi_ch_free ((void **) &cookie);
748
/* for now, only do it if there is only 1 backend, otherwise don't know
749
* which backend to pick */
753
slapi_sdn_init(&monitordn);
754
be_getmonitordn(be,&monitordn);
756
/* do a search on the monitor dn to get info */
757
search_result_pb = slapi_search_internal( slapi_sdn_get_dn(&monitordn),
763
slapi_sdn_done(&monitordn);
765
slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);
767
if(search_result == 0)
769
slapi_pblock_get( search_result_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
772
/* set the entrycachehits */
773
slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits,
774
slapi_entry_attr_get_ulonglong(search_entries[0], "entrycachehits"));
776
/* set the currententrycachesize */
777
slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries,
778
slapi_entry_attr_get_ulonglong(search_entries[0], "currententrycachesize"));
781
slapi_free_search_results_internal(search_result_pb);
782
slapi_pblock_destroy(search_result_pb);
787
add_counter_to_value(Slapi_Entry *e, const char *type, PRUint64 countervalue)
790
PR_snprintf(value,sizeof(value),"%" NSPRIu64, countervalue);
791
slapi_entry_attr_set_charptr( e, type, value);
795
snmp_as_entry(Slapi_Entry *e)
797
add_counter_to_value(e,"AnonymousBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds));
798
add_counter_to_value(e,"UnAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds));
799
add_counter_to_value(e,"SimpleAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds));
800
add_counter_to_value(e,"StrongAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds));
801
add_counter_to_value(e,"BindSecurityErrors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors));
802
add_counter_to_value(e,"InOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsInOps));
803
add_counter_to_value(e,"ReadOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReadOps));
804
add_counter_to_value(e,"CompareOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsCompareOps));
805
add_counter_to_value(e,"AddEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps));
806
add_counter_to_value(e,"RemoveEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps));
807
add_counter_to_value(e,"ModifyEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps));
808
add_counter_to_value(e,"ModifyRDNOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps));
809
add_counter_to_value(e,"ListOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsListOps));
810
add_counter_to_value(e,"SearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSearchOps));
811
add_counter_to_value(e,"OneLevelSearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps));
812
add_counter_to_value(e,"WholeSubtreeSearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps));
813
add_counter_to_value(e,"Referrals", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferrals));
814
add_counter_to_value(e,"Chainings", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsChainings));
815
add_counter_to_value(e,"SecurityErrors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors));
816
add_counter_to_value(e,"Errors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsErrors));
817
add_counter_to_value(e,"Connections", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections));
818
add_counter_to_value(e,"ConnectionSeq", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq));
819
add_counter_to_value(e,"BytesRecv", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv));
820
add_counter_to_value(e,"BytesSent", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent));
821
add_counter_to_value(e,"EntriesReturned", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned));
822
add_counter_to_value(e,"ReferralsReturned", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned));
823
add_counter_to_value(e,"MasterEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsMasterEntries));
824
add_counter_to_value(e,"CopyEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCopyEntries));
825
add_counter_to_value(e,"CacheEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries));
826
add_counter_to_value(e,"CacheHits", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits));
827
add_counter_to_value(e,"SlaveHits", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsSlaveHits));
833
* Reads the header table SNMP settings and sets them in the mmap'd stats
834
* file. This should be done only when the semaphore is held.
838
Slapi_Entry *entry = NULL;
843
char *contact = NULL;
845
/* Read attributes from SNMP config entry */
846
getConfigEntry( &entry );
847
if ( entry != NULL ) {
848
name = slapi_entry_attr_get_charptr( entry, SNMP_NAME_ATTR );
849
desc = slapi_entry_attr_get_charptr( entry, SNMP_DESC_ATTR );
850
org = slapi_entry_attr_get_charptr( entry, SNMP_ORG_ATTR );
851
loc = slapi_entry_attr_get_charptr( entry, SNMP_LOC_ATTR );
852
contact = slapi_entry_attr_get_charptr( entry, SNMP_CONTACT_ATTR );
853
freeConfigEntry( &entry );
856
/* Load stats into table */
858
PL_strncpyz(stats->hdr_stats.dsName, name, SNMP_FIELD_LENGTH);
862
PL_strncpyz(stats->hdr_stats.dsDescription, desc, SNMP_FIELD_LENGTH);
866
PL_strncpyz(stats->hdr_stats.dsOrganization, org, SNMP_FIELD_LENGTH);
870
PL_strncpyz(stats->hdr_stats.dsLocation, loc, SNMP_FIELD_LENGTH);
873
if ( contact != NULL) {
874
PL_strncpyz(stats->hdr_stats.dsContact, contact, SNMP_FIELD_LENGTH);
878
slapi_ch_free((void **) &name);
879
slapi_ch_free((void **) &desc);
880
slapi_ch_free((void **) &org);
881
slapi_ch_free((void **) &loc);
882
slapi_ch_free((void **) &contact);
886
getConfigEntry( Slapi_Entry **e ) {
889
/* SNMP_CONFIG_DN: no need to be normalized */
890
slapi_sdn_init_normdn_byref( &sdn, SNMP_CONFIG_DN );
891
slapi_search_internal_get_entry( &sdn, NULL, e,
892
plugin_get_default_component_id());
893
slapi_sdn_done( &sdn );
898
freeConfigEntry( Slapi_Entry **e ) {
899
if ( (e != NULL) && (*e != NULL) ) {
900
slapi_entry_free( *e );