1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2005,2008 Oracle. All rights reserved. 5 * 6 * $Id: repmgr_stat.c,v 1.40 2008/01/08 20:58:48 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#define __INCLUDE_NETWORKING 1 12#include "db_int.h" 13 14#ifdef HAVE_STATISTICS 15static int __repmgr_print_all __P((ENV *, u_int32_t)); 16static int __repmgr_print_sites __P((ENV *)); 17static int __repmgr_print_stats __P((ENV *, u_int32_t)); 18static int __repmgr_stat __P((ENV *, DB_REPMGR_STAT **, u_int32_t)); 19static int __repmgr_stat_print __P((ENV *, u_int32_t)); 20 21/* 22 * __repmgr_stat_pp -- 23 * DB_ENV->repmgr_stat pre/post processing. 24 * 25 * PUBLIC: int __repmgr_stat_pp __P((DB_ENV *, DB_REPMGR_STAT **, u_int32_t)); 26 */ 27int 28__repmgr_stat_pp(dbenv, statp, flags) 29 DB_ENV *dbenv; 30 DB_REPMGR_STAT **statp; 31 u_int32_t flags; 32{ 33 ENV *env; 34 int ret; 35 36 env = dbenv->env; 37 38 ENV_REQUIRES_CONFIG_XX( 39 env, rep_handle, "DB_ENV->repmgr_stat", DB_INIT_REP); 40 41 if ((ret = __db_fchk(env, 42 "DB_ENV->repmgr_stat", flags, DB_STAT_CLEAR)) != 0) 43 return (ret); 44 45 return (__repmgr_stat(env, statp, flags)); 46} 47 48/* 49 * __repmgr_stat -- 50 * ENV->repmgr_stat. 51 */ 52static int 53__repmgr_stat(env, statp, flags) 54 ENV *env; 55 DB_REPMGR_STAT **statp; 56 u_int32_t flags; 57{ 58 DB_REP *db_rep; 59 DB_REPMGR_STAT *stats; 60 int ret; 61 62 db_rep = env->rep_handle; 63 64 *statp = NULL; 65 66 /* Allocate a stat struct to return to the user. */ 67 if ((ret = __os_umalloc(env, sizeof(DB_REPMGR_STAT), &stats)) != 0) 68 return (ret); 69 70 memcpy(stats, &db_rep->region->mstat, sizeof(*stats)); 71 if (LF_ISSET(DB_STAT_CLEAR)) 72 memset(&db_rep->region->mstat, 0, sizeof(DB_REPMGR_STAT)); 73 74 *statp = stats; 75 return (0); 76} 77 78/* 79 * __repmgr_stat_print_pp -- 80 * DB_ENV->repmgr_stat_print pre/post processing. 81 * 82 * PUBLIC: int __repmgr_stat_print_pp __P((DB_ENV *, u_int32_t)); 83 */ 84int 85__repmgr_stat_print_pp(dbenv, flags) 86 DB_ENV *dbenv; 87 u_int32_t flags; 88{ 89 ENV *env; 90 int ret; 91 92 env = dbenv->env; 93 94 ENV_REQUIRES_CONFIG_XX( 95 env, rep_handle, "DB_ENV->repmgr_stat_print", DB_INIT_REP); 96 97 if ((ret = __db_fchk(env, "DB_ENV->repmgr_stat_print", 98 flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0) 99 return (ret); 100 101 return (__repmgr_stat_print(env, flags)); 102} 103 104static int 105__repmgr_stat_print(env, flags) 106 ENV *env; 107 u_int32_t flags; 108{ 109 u_int32_t orig_flags; 110 int ret; 111 112 orig_flags = flags; 113 LF_CLR(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM); 114 if (flags == 0 || LF_ISSET(DB_STAT_ALL)) { 115 if ((ret = __repmgr_print_stats(env, orig_flags)) == 0) 116 ret = __repmgr_print_sites(env); 117 if (flags == 0 || ret != 0) 118 return (ret); 119 } 120 121 if (LF_ISSET(DB_STAT_ALL) && 122 (ret = __repmgr_print_all(env, orig_flags)) != 0) 123 return (ret); 124 125 return (0); 126} 127 128static int 129__repmgr_print_stats(env, flags) 130 ENV *env; 131 u_int32_t flags; 132{ 133 DB_REPMGR_STAT *sp; 134 int ret; 135 136 if ((ret = __repmgr_stat(env, &sp, flags)) != 0) 137 return (ret); 138 139 __db_dl(env, "Number of PERM messages not acknowledged", 140 (u_long)sp->st_perm_failed); 141 __db_dl(env, "Number of messages queued due to network delay", 142 (u_long)sp->st_msgs_queued); 143 __db_dl(env, "Number of messages discarded due to queue length", 144 (u_long)sp->st_msgs_dropped); 145 __db_dl(env, "Number of existing connections dropped", 146 (u_long)sp->st_connection_drop); 147 __db_dl(env, "Number of failed new connection attempts", 148 (u_long)sp->st_connect_fail); 149 150 __os_ufree(env, sp); 151 152 return (0); 153} 154 155static int 156__repmgr_print_sites(env) 157 ENV *env; 158{ 159 DB_REPMGR_SITE *list; 160 u_int count, i; 161 int ret; 162 163 if ((ret = __repmgr_site_list(env->dbenv, &count, &list)) != 0) 164 return (ret); 165 166 if (count == 0) 167 return (0); 168 169 __db_msg(env, "%s", DB_GLOBAL(db_line)); 170 __db_msg(env, "DB_REPMGR site information:"); 171 172 for (i = 0; i < count; ++i) { 173 __db_msg(env, "%s (eid: %d, port: %u, %sconnected)", 174 list[i].host, list[i].eid, list[i].port, 175 list[i].status == DB_REPMGR_CONNECTED ? "" : "dis"); 176 } 177 178 __os_ufree(env, list); 179 180 return (0); 181} 182 183/* 184 * __repmgr_print_all -- 185 * Display debugging replication manager statistics. 186 */ 187static int 188__repmgr_print_all(env, flags) 189 ENV *env; 190 u_int32_t flags; 191{ 192 COMPQUIET(env, NULL); 193 COMPQUIET(flags, 0); 194 return (0); 195} 196 197#else /* !HAVE_STATISTICS */ 198 199int 200__repmgr_stat_pp(dbenv, statp, flags) 201 DB_ENV *dbenv; 202 DB_REPMGR_STAT **statp; 203 u_int32_t flags; 204{ 205 COMPQUIET(statp, NULL); 206 COMPQUIET(flags, 0); 207 208 return (__db_stat_not_built(dbenv->env)); 209} 210 211int 212__repmgr_stat_print_pp(dbenv, flags) 213 DB_ENV *dbenv; 214 u_int32_t flags; 215{ 216 COMPQUIET(flags, 0); 217 218 return (__db_stat_not_built(dbenv->env)); 219} 220#endif 221 222/* 223 * PUBLIC: int __repmgr_site_list __P((DB_ENV *, u_int *, DB_REPMGR_SITE **)); 224 */ 225int 226__repmgr_site_list(dbenv, countp, listp) 227 DB_ENV *dbenv; 228 u_int *countp; 229 DB_REPMGR_SITE **listp; 230{ 231 DB_REP *db_rep; 232 DB_REPMGR_SITE *status; 233 ENV *env; 234 REPMGR_SITE *site; 235 size_t array_size, total_size; 236 u_int count, i; 237 int locked, ret; 238 char *name; 239 240 env = dbenv->env; 241 db_rep = env->rep_handle; 242 if (REPMGR_SYNC_INITED(db_rep)) { 243 LOCK_MUTEX(db_rep->mutex); 244 locked = TRUE; 245 } else 246 locked = FALSE; 247 248 /* Initialize for empty list or error return. */ 249 ret = 0; 250 *countp = 0; 251 *listp = NULL; 252 253 /* First, add up how much memory we need for the host names. */ 254 if ((count = db_rep->site_cnt) == 0) 255 goto err; 256 257 array_size = sizeof(DB_REPMGR_SITE) * count; 258 total_size = array_size; 259 for (i = 0; i < count; i++) { 260 site = &db_rep->sites[i]; 261 262 /* Make room for the NUL terminating byte. */ 263 total_size += strlen(site->net_addr.host) + 1; 264 } 265 266 if ((ret = __os_umalloc(env, total_size, &status)) != 0) 267 goto err; 268 269 /* 270 * Put the storage for the host names after the array of structs. This 271 * way, the caller can free the whole thing in one single operation. 272 */ 273 name = (char *)((u_int8_t *)status + array_size); 274 for (i = 0; i < count; i++) { 275 site = &db_rep->sites[i]; 276 277 status[i].eid = EID_FROM_SITE(site); 278 279 status[i].host = name; 280 (void)strcpy(name, site->net_addr.host); 281 name += strlen(name) + 1; 282 283 status[i].port = site->net_addr.port; 284 status[i].status = site->state == SITE_CONNECTED ? 285 DB_REPMGR_CONNECTED : DB_REPMGR_DISCONNECTED; 286 } 287 288 *countp = count; 289 *listp = status; 290 291err: if (locked) 292 UNLOCK_MUTEX(db_rep->mutex); 293 return (ret); 294} 295