#include "db_config.h"
#include "db_int.h"
#ifdef HAVE_STATISTICS
static int __repmgr_print_all __P((ENV *, u_int32_t));
static int __repmgr_print_sites __P((ENV *));
static int __repmgr_print_stats __P((ENV *, u_int32_t));
static int __repmgr_stat __P((ENV *, DB_REPMGR_STAT **, u_int32_t));
int
__repmgr_stat_pp(dbenv, statp, flags)
DB_ENV *dbenv;
DB_REPMGR_STAT **statp;
u_int32_t flags;
{
ENV *env;
int ret;
env = dbenv->env;
ENV_REQUIRES_CONFIG_XX(
env, rep_handle, "DB_ENV->repmgr_stat", DB_INIT_REP);
if ((ret = __db_fchk(env,
"DB_ENV->repmgr_stat", flags, DB_STAT_CLEAR)) != 0)
return (ret);
return (__repmgr_stat(env, statp, flags));
}
static int
__repmgr_stat(env, statp, flags)
ENV *env;
DB_REPMGR_STAT **statp;
u_int32_t flags;
{
DB_REP *db_rep;
DB_REPMGR_STAT *copy, *stats;
uintmax_t tmp;
int ret;
db_rep = env->rep_handle;
stats = &db_rep->region->mstat;
*statp = NULL;
if ((ret = __os_umalloc(env, sizeof(DB_REPMGR_STAT), ©)) != 0)
return (ret);
memcpy(copy, stats, sizeof(*stats));
if (LF_ISSET(DB_STAT_CLEAR)) {
tmp = stats->st_max_elect_threads;
memset(stats, 0, sizeof(DB_REPMGR_STAT));
stats->st_max_elect_threads = tmp;
}
*statp = copy;
return (0);
}
int
__repmgr_stat_print_pp(dbenv, flags)
DB_ENV *dbenv;
u_int32_t flags;
{
ENV *env;
int ret;
env = dbenv->env;
ENV_REQUIRES_CONFIG_XX(
env, rep_handle, "DB_ENV->repmgr_stat_print", DB_INIT_REP);
if ((ret = __db_fchk(env, "DB_ENV->repmgr_stat_print",
flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
return (ret);
return (__repmgr_stat_print(env, flags));
}
int
__repmgr_stat_print(env, flags)
ENV *env;
u_int32_t flags;
{
u_int32_t orig_flags;
int ret;
orig_flags = flags;
LF_CLR(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM);
if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
if ((ret = __repmgr_print_stats(env, orig_flags)) == 0)
ret = __repmgr_print_sites(env);
if (flags == 0 || ret != 0)
return (ret);
}
if (LF_ISSET(DB_STAT_ALL) &&
(ret = __repmgr_print_all(env, orig_flags)) != 0)
return (ret);
return (0);
}
static int
__repmgr_print_stats(env, flags)
ENV *env;
u_int32_t flags;
{
DB_REPMGR_STAT *sp;
int ret;
if ((ret = __repmgr_stat(env, &sp, flags)) != 0)
return (ret);
__db_dl(env, "Number of PERM messages not acknowledged",
(u_long)sp->st_perm_failed);
__db_dl(env, "Number of messages queued due to network delay",
(u_long)sp->st_msgs_queued);
__db_dl(env, "Number of messages discarded due to queue length",
(u_long)sp->st_msgs_dropped);
__db_dl(env, "Number of existing connections dropped",
(u_long)sp->st_connection_drop);
__db_dl(env, "Number of failed new connection attempts",
(u_long)sp->st_connect_fail);
__db_dl(env, "Number of currently active election threads",
(u_long)sp->st_elect_threads);
__db_dl(env, "Election threads for which space is reserved",
(u_long)sp->st_max_elect_threads);
__os_ufree(env, sp);
return (0);
}
static int
__repmgr_print_sites(env)
ENV *env;
{
DB_REPMGR_SITE *list;
DB_MSGBUF mb;
u_int count, i;
int ret;
if ((ret = __repmgr_site_list(env->dbenv, &count, &list)) != 0)
return (ret);
if (count == 0)
return (0);
__db_msg(env, "%s", DB_GLOBAL(db_line));
__db_msg(env, "DB_REPMGR site information:");
DB_MSGBUF_INIT(&mb);
for (i = 0; i < count; ++i) {
__db_msgadd(env, &mb, "%s (eid: %d, port: %u",
list[i].host, list[i].eid, list[i].port);
if (list[i].status != 0)
__db_msgadd(env, &mb, ", %sconnected",
list[i].status == DB_REPMGR_CONNECTED ? "" : "dis");
__db_msgadd(env, &mb, ", %speer",
F_ISSET(&list[i], DB_REPMGR_ISPEER) ? "" : "non-");
__db_msgadd(env, &mb, ")");
DB_MSGBUF_FLUSH(env, &mb);
}
__os_ufree(env, list);
return (0);
}
static int
__repmgr_print_all(env, flags)
ENV *env;
u_int32_t flags;
{
COMPQUIET(env, NULL);
COMPQUIET(flags, 0);
return (0);
}
#else
int
__repmgr_stat_pp(dbenv, statp, flags)
DB_ENV *dbenv;
DB_REPMGR_STAT **statp;
u_int32_t flags;
{
COMPQUIET(statp, NULL);
COMPQUIET(flags, 0);
return (__db_stat_not_built(dbenv->env));
}
int
__repmgr_stat_print_pp(dbenv, flags)
DB_ENV *dbenv;
u_int32_t flags;
{
COMPQUIET(flags, 0);
return (__db_stat_not_built(dbenv->env));
}
#endif
int
__repmgr_site_list(dbenv, countp, listp)
DB_ENV *dbenv;
u_int *countp;
DB_REPMGR_SITE **listp;
{
DB_REP *db_rep;
REP *rep;
DB_REPMGR_SITE *status;
ENV *env;
DB_THREAD_INFO *ip;
REPMGR_SITE *site;
size_t array_size, total_size;
int eid, locked, ret;
u_int count, i;
char *name;
env = dbenv->env;
db_rep = env->rep_handle;
ret = 0;
ENV_NOT_CONFIGURED(
env, db_rep->region, "DB_ENV->repmgr_site_list", DB_INIT_REP);
if (REP_ON(env)) {
rep = db_rep->region;
LOCK_MUTEX(db_rep->mutex);
locked = TRUE;
ENV_ENTER(env, ip);
if (rep->siteinfo_seq > db_rep->siteinfo_seq)
ret = __repmgr_sync_siteaddr(env);
ENV_LEAVE(env, ip);
if (ret != 0)
goto err;
} else {
rep = NULL;
locked = FALSE;
}
*countp = 0;
*listp = NULL;
for (i = 0, count = 0, total_size = 0; i < db_rep->site_cnt; i++) {
site = &db_rep->sites[i];
if ((int)i == db_rep->self_eid || site->membership == 0)
continue;
total_size += strlen(site->net_addr.host) + 1;
count++;
}
if (count == 0)
goto err;
array_size = sizeof(DB_REPMGR_SITE) * count;
total_size += array_size;
if ((ret = __os_umalloc(env, total_size, &status)) != 0)
goto err;
name = (char *)((u_int8_t *)status + array_size);
for (eid = 0, i = 0; eid < (int)db_rep->site_cnt; eid++) {
site = &db_rep->sites[eid];
if (eid == db_rep->self_eid || site->membership == 0)
continue;
status[i].eid = rep ? eid : DB_EID_INVALID;
status[i].host = name;
(void)strcpy(name, site->net_addr.host);
name += strlen(name) + 1;
status[i].port = site->net_addr.port;
status[i].flags = 0;
if (FLD_ISSET(site->config, DB_REPMGR_PEER))
F_SET(&status[i], DB_REPMGR_ISPEER);
if (db_rep->selector == NULL)
status[i].status = 0;
else if (site->state != SITE_CONNECTED)
status[i].status = DB_REPMGR_DISCONNECTED;
else if ((site->ref.conn.in != NULL &&
IS_READY_STATE(site->ref.conn.in->state)) ||
(site->ref.conn.out != NULL &&
IS_READY_STATE(site->ref.conn.out->state)))
status[i].status = DB_REPMGR_CONNECTED;
else
status[i].status = DB_REPMGR_DISCONNECTED;
i++;
}
*countp = count;
*listp = status;
err: if (locked)
UNLOCK_MUTEX(db_rep->mutex);
return (ret);
}