diff options
Diffstat (limited to '')
-rw-r--r-- | tests/progs/slapd-watcher.c | 823 |
1 files changed, 823 insertions, 0 deletions
diff --git a/tests/progs/slapd-watcher.c b/tests/progs/slapd-watcher.c new file mode 100644 index 0000000..0fed11f --- /dev/null +++ b/tests/progs/slapd-watcher.c @@ -0,0 +1,823 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 1999-2022 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * <http://www.OpenLDAP.org/license.html>. + */ +/* ACKNOWLEDGEMENTS: + * This work was initially developed by Howard Chu for inclusion + * in OpenLDAP Software. + */ + +#include "portable.h" + +#include <stdio.h> + +#include "ac/signal.h" +#include "ac/stdlib.h" +#include "ac/time.h" + +#include "ac/ctype.h" +#include "ac/param.h" +#include "ac/socket.h" +#include "ac/string.h" +#include "ac/unistd.h" +#include "ac/wait.h" +#include "ac/time.h" + +#include "ldap.h" +#include "lutil.h" +#include "lutil_ldap.h" +#include "lber_pvt.h" +#include "ldap_pvt.h" + +#include "slapd-common.h" + +#define SLAP_SYNC_SID_MAX 4095 + +#define HAS_MONITOR 1 +#define HAS_BASE 2 +#define HAS_ENTRIES 4 +#define HAS_SREPL 8 +#define HAS_ALL (HAS_MONITOR|HAS_BASE|HAS_ENTRIES|HAS_SREPL) + + +#define WAS_LATE 0x100 +#define WAS_DOWN 0x200 + +#define MONFILTER "(objectClass=monitorOperation)" + +static const char *default_monfilter = MONFILTER; + +typedef enum { + SLAP_OP_BIND = 0, + SLAP_OP_UNBIND, + SLAP_OP_SEARCH, + SLAP_OP_COMPARE, + SLAP_OP_MODIFY, + SLAP_OP_MODRDN, + SLAP_OP_ADD, + SLAP_OP_DELETE, + SLAP_OP_ABANDON, + SLAP_OP_EXTENDED, + SLAP_OP_LAST +} slap_op_t; + +struct opname { + struct berval rdn; + char *display; +} opnames[] = { + { BER_BVC("cn=Bind"), "Bind" }, + { BER_BVC("cn=Unbind"), "Unbind" }, + { BER_BVC("cn=Search"), "Search" }, + { BER_BVC("cn=Compare"), "Compare" }, + { BER_BVC("cn=Modify"), "Modify" }, + { BER_BVC("cn=Modrdn"), "ModDN" }, + { BER_BVC("cn=Add"), "Add" }, + { BER_BVC("cn=Delete"), "Delete" }, + { BER_BVC("cn=Abandon"), "Abandon" }, + { BER_BVC("cn=Extended"), "Extended" }, + { BER_BVNULL, NULL } +}; + +typedef struct counters { + struct timeval time; + unsigned long entries; + unsigned long ops[SLAP_OP_LAST]; +} counters; + +typedef struct csns { + struct berval *vals; + struct timeval *tvs; +} csns; + +typedef struct activity { + time_t active; + time_t idle; + time_t maxlag; + time_t lag; +} activity; + +typedef struct server { + char *url; + LDAP *ld; + int flags; + int sid; + struct berval monitorbase; + char *monitorfilter; + time_t late; + time_t down; + counters c_prev; + counters c_curr; + csns csn_prev; + csns csn_curr; + activity *times; +} server; + +static void +usage( char *name, char opt ) +{ + if ( opt ) { + fprintf( stderr, "%s: unable to handle option \'%c\'\n\n", + name, opt ); + } + + fprintf( stderr, "usage: %s " + "[-D <dn> [ -w <passwd> ]] " + "[-d <level>] " + "[-O <SASL secprops>] " + "[-R <SASL realm>] " + "[-U <SASL authcid> [-X <SASL authzid>]] " + "[-x | -Y <SASL mech>] " + "[-i <interval>] " + "[-s <sids>] " + "[-c <contextDN>] " + "[-b <baseDN> ] URI[...]\n", + name ); + exit( EXIT_FAILURE ); +} + +struct berval base, cbase; +int interval = 10; +int numservers; +server *servers; +char *monfilter; + +struct berval at_namingContexts = BER_BVC("namingContexts"); +struct berval at_monitorOpCompleted = BER_BVC("monitorOpCompleted"); +struct berval at_olmMDBEntries = BER_BVC("olmMDBEntries"); +struct berval at_contextCSN = BER_BVC("contextCSN"); + +void timestamp(time_t *tt) +{ + struct tm *tm = gmtime(tt); + printf("%d-%02d-%02d %02d:%02d:%02d", + tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +void deltat(time_t *tt) +{ + struct tm *tm = gmtime(tt); + if (tm->tm_mday-1) + printf("%02d+", tm->tm_mday-1); + printf("%02d:%02d:%02d", + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +static char *clearscreen = "\033[H\033[2J"; + +void rotate_stats( server *sv ) +{ + if ( sv->flags & HAS_MONITOR ) + sv->c_prev = sv->c_curr; + if ( sv->flags & HAS_BASE ) { + int i; + + for (i=0; i<numservers; i++) { + if ( sv->csn_curr.vals[i].bv_len ) { + ber_bvreplace(&sv->csn_prev.vals[i], + &sv->csn_curr.vals[i]); + sv->csn_prev.tvs[i] = sv->csn_curr.tvs[i]; + } else { + if ( sv->csn_prev.vals[i].bv_val ) + sv->csn_prev.vals[i].bv_val[0] = '\0'; + } + } + } +} + +void display() +{ + int i, j; + struct timeval now; + time_t now_t; + + gettimeofday(&now, NULL); + now_t = now.tv_sec; + printf("%s", clearscreen); + timestamp(&now_t); + printf("\n"); + + for (i=0; i<numservers; i++) { + printf("\n%s", servers[i].url ); + if ( servers[i].flags & WAS_DOWN ) { + printf(", down@"); + timestamp( &servers[i].down ); + } + if ( servers[i].flags & WAS_LATE ) { + printf(", late@"); + timestamp( &servers[i].late ); + } + printf("\n"); + if ( servers[i].flags & HAS_MONITOR ) { + struct timeval tv; + double rate, duration; + long delta; + printf(" "); + if ( servers[i].flags & HAS_ENTRIES ) + printf(" Entries "); + for ( j = 0; j<SLAP_OP_LAST; j++ ) + printf(" %9s ", opnames[j].display); + printf("\n"); + printf("Num "); + if ( servers[i].flags & HAS_ENTRIES ) + printf("%10lu ", servers[i].c_curr.entries); + for ( j = 0; j<SLAP_OP_LAST; j++ ) + printf("%10lu ", servers[i].c_curr.ops[j]); + printf("\n"); + printf("Num/s "); + tv.tv_usec = now.tv_usec - servers[i].c_prev.time.tv_usec; + tv.tv_sec = now.tv_sec - servers[i].c_prev.time.tv_sec; + if ( tv.tv_usec < 0 ) { + tv.tv_usec += 1000000; + tv.tv_sec--; + } + duration = tv.tv_sec + (tv.tv_usec / (double)1000000); + if ( servers[i].flags & HAS_ENTRIES ) { + delta = servers[i].c_curr.entries - servers[i].c_prev.entries; + rate = delta / duration; + printf("%10.2f ", rate); + } + for ( j = 0; j<SLAP_OP_LAST; j++ ) { + delta = servers[i].c_curr.ops[j] - servers[i].c_prev.ops[j]; + rate = delta / duration; + printf("%10.2f ", rate); + } + printf("\n"); + } + if ( servers[i].flags & HAS_BASE ) { + for (j=0; j<numservers; j++) { + /* skip empty CSNs */ + if (!servers[i].csn_curr.vals[j].bv_len || + !servers[i].csn_curr.vals[j].bv_val[0]) + continue; + printf("contextCSN: %s", servers[i].csn_curr.vals[j].bv_val ); + if (ber_bvcmp(&servers[i].csn_curr.vals[j], + &servers[i].csn_prev.vals[j])) { + /* a difference */ + if (servers[i].times[j].idle) { + servers[i].times[j].idle = 0; + servers[i].times[j].active = 0; + servers[i].times[j].maxlag = 0; + servers[i].times[j].lag = 0; + } +active: + if (!servers[i].times[j].active) + servers[i].times[j].active = now_t; + printf(" actv@"); + timestamp(&servers[i].times[j].active); + } else if ( servers[i].times[j].lag || ( servers[i].flags & WAS_LATE )) { + goto active; + } else { + if (servers[i].times[j].active && !servers[i].times[j].idle) + servers[i].times[j].idle = now_t; + if (servers[i].times[j].active) { + printf(" actv@"); + timestamp(&servers[i].times[j].active); + printf(", idle@"); + timestamp(&servers[i].times[j].idle); + } else { + printf(" idle"); + } + } + if (i != j) { + if (ber_bvcmp(&servers[i].csn_curr.vals[j], + &servers[j].csn_curr.vals[j])) { + struct timeval delta; + int ahead = 0; + time_t deltatt; + delta.tv_sec = servers[j].csn_curr.tvs[j].tv_sec - + servers[i].csn_curr.tvs[j].tv_sec; + delta.tv_usec = servers[j].csn_curr.tvs[j].tv_usec - + servers[i].csn_curr.tvs[j].tv_usec; + if (delta.tv_usec < 0) { + delta.tv_usec += 1000000; + delta.tv_sec--; + } + if (delta.tv_sec < 0) { + delta.tv_sec = -delta.tv_sec; + ahead = 1; + } + deltatt = delta.tv_sec; + if (ahead) + printf(", ahead "); + else + printf(", behind "); + deltat( &deltatt ); + servers[i].times[j].lag = deltatt; + if (deltatt > servers[i].times[j].maxlag) + servers[i].times[j].maxlag = deltatt; + } else { + servers[i].times[j].lag = 0; + printf(", sync'd"); + } + if (servers[i].times[j].maxlag) { + printf(", max delta "); + deltat( &servers[i].times[j].maxlag ); + } + } + printf("\n"); + } + } + if ( !( servers[i].flags & WAS_LATE )) + rotate_stats( &servers[i] ); + } +} + +void get_counters( + LDAP *ld, + LDAPMessage *e, + BerElement *ber, + counters *c ) +{ + int rc; + slap_op_t op = SLAP_OP_BIND; + struct berval dn, bv, *bvals, **bvp = &bvals; + + do { + int done = 0; + for ( rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp ); + rc == LDAP_SUCCESS; + rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp )) { + + if ( bv.bv_val == NULL ) break; + if ( !ber_bvcmp( &bv, &at_monitorOpCompleted ) && bvals ) { + c->ops[op] = strtoul( bvals[0].bv_val, NULL, 0 ); + done = 1; + } + if ( bvals ) { + ber_memfree( bvals ); + bvals = NULL; + } + if ( done ) + break; + } + ber_free( ber, 0 ); + e = ldap_next_entry( ld, e ); + if ( !e ) + break; + ldap_get_dn_ber( ld, e, &ber, &dn ); + op++; + } while ( op < SLAP_OP_LAST ); +} + +int +slap_parse_csn_sid( struct berval *csnp ) +{ + char *p, *q; + struct berval csn = *csnp; + int i; + + p = ber_bvchr( &csn, '#' ); + if ( !p ) + return -1; + p++; + csn.bv_len -= p - csn.bv_val; + csn.bv_val = p; + + p = ber_bvchr( &csn, '#' ); + if ( !p ) + return -1; + p++; + csn.bv_len -= p - csn.bv_val; + csn.bv_val = p; + + q = ber_bvchr( &csn, '#' ); + if ( !q ) + return -1; + + csn.bv_len = q - p; + + i = strtol( p, &q, 16 ); + if ( p == q || q != p + csn.bv_len || i < 0 || i > SLAP_SYNC_SID_MAX ) { + i = -1; + } + + return i; +} + +void get_csns( + csns *c, + struct berval *bvs +) +{ + int i, j; + + /* clear old values if any */ + for (i=0; i<numservers; i++) + if ( c->vals[i].bv_val ) + c->vals[i].bv_val[0] = '\0'; + + for (i=0; bvs[i].bv_val; i++) { + struct lutil_tm tm; + struct lutil_timet tt; + int sid = slap_parse_csn_sid( &bvs[i] ); + for (j=0; j<numservers; j++) + if (sid == servers[j].sid) break; + if (j < numservers) { + ber_bvreplace( &c->vals[j], &bvs[i] ); + lutil_parsetime(bvs[i].bv_val, &tm); + c->tvs[j].tv_usec = tm.tm_nsec / 1000; + lutil_tm2time( &tm, &tt ); + c->tvs[j].tv_sec = tt.tt_sec; + } + } +} + +int +setup_server( struct tester_conn_args *config, server *sv, int first ) +{ + config->uri = sv->url; + tester_init_ld( &sv->ld, config, first ? 0 : TESTER_INIT_NOEXIT ); + if ( !sv->ld ) + return -1; + + sv->flags &= ~HAS_ALL; + { + char *attrs[] = { at_namingContexts.bv_val, at_monitorOpCompleted.bv_val, + at_olmMDBEntries.bv_val, NULL }; + LDAPMessage *res = NULL, *e = NULL; + BerElement *ber = NULL; + LDAP *ld = sv->ld; + struct berval dn, bv, *bvals, **bvp = &bvals; + int j, rc; + + rc = ldap_search_ext_s( ld, "cn=monitor", LDAP_SCOPE_SUBTREE, monfilter, + attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res ); + switch(rc) { + case LDAP_SIZELIMIT_EXCEEDED: + case LDAP_TIMELIMIT_EXCEEDED: + case LDAP_SUCCESS: + gettimeofday( &sv->c_curr.time, 0 ); + sv->flags |= HAS_MONITOR; + for ( e = ldap_first_entry( ld, res ); e; e = ldap_next_entry( ld, e )) { + ldap_get_dn_ber( ld, e, &ber, &dn ); + if ( !strncasecmp( dn.bv_val, "cn=Database", sizeof("cn=Database")-1 ) || + !strncasecmp( dn.bv_val, "cn=Frontend", sizeof("cn=Frontend")-1 )) { + int matched = 0; + for ( rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp ); + rc == LDAP_SUCCESS; + rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp )) { + if ( bv.bv_val == NULL ) break; + if (!ber_bvcmp( &bv, &at_namingContexts ) && bvals ) { + for (j=0; bvals[j].bv_val; j++) { + if ( !ber_bvstrcasecmp( &base, &bvals[j] )) { + matched = 1; + break; + } + } + if (!matched) { + ber_memfree( bvals ); + bvals = NULL; + break; + } + } + if (!ber_bvcmp( &bv, &at_olmMDBEntries )) { + ber_bvreplace( &sv->monitorbase, &dn ); + sv->flags |= HAS_ENTRIES; + sv->c_curr.entries = strtoul( bvals[0].bv_val, NULL, 0 ); + } + ber_memfree( bvals ); + bvals = NULL; + } + } else if (!strncasecmp( dn.bv_val, opnames[0].rdn.bv_val, + opnames[0].rdn.bv_len )) { + get_counters( ld, e, ber, &sv->c_curr ); + break; + } + if ( ber ) + ber_free( ber, 0 ); + } + break; + + case LDAP_NO_SUCH_OBJECT: + /* no cn=monitor */ + break; + + default: + tester_ldap_error( ld, "ldap_search_ext_s(cn=Monitor)", sv->url ); + if ( first ) + exit( EXIT_FAILURE ); + } + ldap_msgfree( res ); + + if ( cbase.bv_val ) { + char *attr2[] = { at_contextCSN.bv_val, NULL }; + rc = ldap_search_ext_s( ld, cbase.bv_val, LDAP_SCOPE_BASE, "(objectClass=*)", + attr2, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res ); + switch(rc) { + case LDAP_SUCCESS: + e = ldap_first_entry( ld, res ); + if ( e ) { + sv->flags |= HAS_BASE; + ldap_get_dn_ber( ld, e, &ber, &dn ); + for ( rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp ); + rc == LDAP_SUCCESS; + rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp )) { + int done = 0; + if ( bv.bv_val == NULL ) break; + if ( bvals ) { + if ( !ber_bvcmp( &bv, &at_contextCSN )) { + get_csns( &sv->csn_curr, bvals ); + done = 1; + } + ber_memfree( bvals ); + bvals = NULL; + if ( done ) + break; + } + } + } + ldap_msgfree( res ); + break; + + default: + tester_ldap_error( ld, "ldap_search_ext_s(baseDN)", sv->url ); + if ( first ) + exit( EXIT_FAILURE ); + } + } + } + + if ( sv->monitorfilter != default_monfilter ) + free( sv->monitorfilter ); + if ( sv->flags & HAS_ENTRIES ) { + int len = sv->monitorbase.bv_len + sizeof("(|(entryDN=)" MONFILTER ")"); + char *ptr = malloc(len); + sprintf(ptr, "(|(entryDN=%s)" MONFILTER ")", sv->monitorbase.bv_val ); + sv->monitorfilter = ptr; + } else if ( sv->flags & HAS_MONITOR ) { + sv->monitorfilter = (char *)default_monfilter; + } + if ( first ) + rotate_stats( sv ); + return 0; +} + +int +main( int argc, char **argv ) +{ + int i, rc, *msg1, *msg2; + char **sids = NULL; + struct tester_conn_args *config; + int first = 1; + + config = tester_init( "slapd-watcher", TESTER_TESTER ); + config->authmethod = LDAP_AUTH_SIMPLE; + + while ( ( i = getopt( argc, argv, "D:O:R:U:X:Y:b:c:d:i:s:w:x" ) ) != EOF ) + { + switch ( i ) { + case 'b': /* base DN for DB entrycount lookups */ + ber_str2bv( optarg, 0, 0, &base ); + if ( !cbase.bv_val ) + cbase = base; + break; + + case 'c': /* base DN for contextCSN lookups */ + ber_str2bv( optarg, 0, 0, &cbase ); + break; + + case 'i': + interval = atoi(optarg); + break; + + case 's': + sids = ldap_str2charray( optarg, "," ); + break; + + default: + if ( tester_config_opt( config, i, optarg ) == LDAP_SUCCESS ) + break; + + usage( argv[0], i ); + break; + } + } + + tester_config_finish( config ); +#ifdef SIGPIPE + (void) SIGNAL(SIGPIPE, SIG_IGN); +#endif + + /* don't clear the screen if debug is enabled */ + if (debug) + clearscreen = "\n\n"; + + numservers = argc - optind; + if ( !numservers ) + usage( argv[0], 0 ); + + if ( sids ) { + for (i=0; sids[i]; i++ ); + if ( i != numservers ) { + fprintf(stderr, "Number of sids doesn't equal number of server URLs\n"); + exit( EXIT_FAILURE ); + } + } + + argv += optind; + argc -= optind; + servers = calloc( numservers, sizeof(server)); + + if ( base.bv_val ) { + monfilter = "(|(entryDN:dnOneLevelMatch:=cn=Databases,cn=Monitor)" MONFILTER ")"; + } else { + monfilter = MONFILTER; + } + + if ( sids || numservers > 1 ) { + for ( i=0; i<numservers; i++ ) + if ( sids ) + servers[i].sid = atoi(sids[i]); + else + servers[i].sid = i+1; + } + + for ( i = 0; i < numservers; i++ ) { + servers[i].url = argv[i]; + servers[i].times = calloc( numservers, sizeof(activity)); + servers[i].csn_curr.vals = calloc( numservers, sizeof(struct berval)); + servers[i].csn_prev.vals = calloc( numservers, sizeof(struct berval)); + servers[i].csn_curr.tvs = calloc( numservers, sizeof(struct timeval)); + servers[i].csn_prev.tvs = calloc( numservers, sizeof(struct timeval)); + } + + msg1 = malloc( numservers * 2 * sizeof(int)); + msg2 = msg1 + numservers; + + for (;;) { + LDAPMessage *res = NULL, *e = NULL; + BerElement *ber = NULL; + struct berval dn, bv, *bvals, **bvp = &bvals; + struct timeval tv; + LDAP *ld; + + for (i=0; i<numservers; i++) { + if ( !servers[i].ld || !(servers[i].flags & WAS_LATE )) { + msg1[i] = 0; + msg2[i] = 0; + } + if ( !servers[i].ld ) { + setup_server( config, &servers[i], first ); + } else { + ld = servers[i].ld; + rc = -1; + if ( servers[i].flags & WAS_DOWN ) + servers[i].flags ^= WAS_DOWN; + if (( servers[i].flags & HAS_MONITOR ) && !msg1[i] ) { + char *attrs[3] = { at_monitorOpCompleted.bv_val }; + if ( servers[i].flags & HAS_ENTRIES ) + attrs[1] = at_olmMDBEntries.bv_val; + rc = ldap_search_ext( ld, "cn=monitor", + LDAP_SCOPE_SUBTREE, servers[i].monitorfilter, + attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msg1[i] ); + if ( rc != LDAP_SUCCESS ) { + tester_ldap_error( ld, "ldap_search_ext(cn=Monitor)", servers[i].url ); + if ( first ) + exit( EXIT_FAILURE ); + else { +server_down1: + ldap_unbind_ext( ld, NULL, NULL ); + servers[i].flags |= WAS_DOWN; + servers[i].ld = NULL; + gettimeofday( &tv, NULL ); + servers[i].down = tv.tv_sec; + msg1[i] = 0; + msg2[i] = 0; + continue; + } + } + } + if (( servers[i].flags & HAS_BASE ) && !msg2[i] ) { + char *attrs[2] = { at_contextCSN.bv_val }; + rc = ldap_search_ext( ld, cbase.bv_val, + LDAP_SCOPE_BASE, "(objectClass=*)", + attrs, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msg2[i] ); + if ( rc != LDAP_SUCCESS ) { + tester_ldap_error( ld, "ldap_search_ext(baseDN)", servers[i].url ); + if ( first ) + exit( EXIT_FAILURE ); + else + goto server_down1; + } + } + if ( rc != -1 ) + gettimeofday( &servers[i].c_curr.time, 0 ); + } + } + + for (i=0; i<numservers; i++) { + ld = servers[i].ld; + if ( msg1[i] ) { + tv.tv_sec = 0; + tv.tv_usec = 250000; + rc = ldap_result( ld, msg1[i], LDAP_MSG_ALL, &tv, &res ); + if ( rc < 0 ) { + tester_ldap_error( ld, "ldap_result(cn=Monitor)", servers[i].url ); + if ( first ) + exit( EXIT_FAILURE ); + else { +server_down2: + ldap_unbind_ext( ld, NULL, NULL ); + servers[i].flags |= WAS_DOWN; + servers[i].ld = NULL; + servers[i].down = servers[i].c_curr.time.tv_sec; + msg1[i] = 0; + msg2[i] = 0; + continue; + } + } + if ( rc == 0 ) { + if ( !( servers[i].flags & WAS_LATE )) + servers[i].late = servers[i].c_curr.time.tv_sec; + servers[i].flags |= WAS_LATE; + continue; + } + if ( servers[i].flags & WAS_LATE ) + servers[i].flags ^= WAS_LATE; + for ( e = ldap_first_entry( ld, res ); e; e = ldap_next_entry( ld, e )) { + ldap_get_dn_ber( ld, e, &ber, &dn ); + if ( !strncasecmp( dn.bv_val, "cn=Database", sizeof("cn=Database")-1 ) || + !strncasecmp( dn.bv_val, "cn=Frontend", sizeof("cn=Frontend")-1 )) { + for ( rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp ); + rc == LDAP_SUCCESS; + rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp )) { + if ( bv.bv_val == NULL ) break; + if ( !ber_bvcmp( &bv, &at_olmMDBEntries )) { + if ( !BER_BVISNULL( &servers[i].monitorbase )) { + servers[i].c_curr.entries = strtoul( bvals[0].bv_val, NULL, 0 ); + } + } + ber_memfree( bvals ); + bvals = NULL; + } + } else if (!strncasecmp( dn.bv_val, opnames[0].rdn.bv_val, + opnames[0].rdn.bv_len )) { + get_counters( ld, e, ber, &servers[i].c_curr ); + break; + } + if ( ber ) + ber_free( ber, 0 ); + } + ldap_msgfree( res ); + } + if ( msg2[i] ) { + tv.tv_sec = 0; + tv.tv_usec = 250000; + rc = ldap_result( ld, msg2[i], LDAP_MSG_ALL, &tv, &res ); + if ( rc < 0 ) { + tester_ldap_error( ld, "ldap_result(baseDN)", servers[i].url ); + if ( first ) + exit( EXIT_FAILURE ); + else + goto server_down2; + } + if ( rc == 0 ) { + if ( !( servers[i].flags & WAS_LATE )) + servers[i].late = servers[i].c_curr.time.tv_sec; + servers[i].flags |= WAS_LATE; + continue; + } + if ( servers[i].flags & WAS_LATE ) + servers[i].flags ^= WAS_LATE; + e = ldap_first_entry( ld, res ); + if ( e ) { + ldap_get_dn_ber( ld, e, &ber, &dn ); + for ( rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp ); + rc == LDAP_SUCCESS; + rc = ldap_get_attribute_ber( ld, e, ber, &bv, bvp )) { + int done = 0; + if ( bv.bv_val == NULL ) break; + if ( bvals ) { + if ( !ber_bvcmp( &bv, &at_contextCSN )) { + get_csns( &servers[i].csn_curr, bvals ); + done = 1; + } + ber_memfree( bvals ); + bvals = NULL; + if ( done ) + break; + } + } + } + ldap_msgfree( res ); + } + } + display(); + sleep(interval); + first = 0; + } + + exit( EXIT_SUCCESS ); +} + |