monitor.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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.
  5. *
  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.
  9. *
  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.
  13. *
  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
  31. * exception.
  32. *
  33. *
  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 **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* monitor.c - ldbm backend monitor function */
  42. #include "back-ldbm.h"
  43. #include "dblayer.h" /* XXXmcs: not sure this is good to do... */
  44. #include <sys/stat.h>
  45. #define MSET(_attr) do { \
  46. val.bv_val = buf; \
  47. val.bv_len = strlen(buf); \
  48. attrlist_replace(&e->e_attrs, (_attr), vals); \
  49. } while (0)
  50. #define MSETF(_attr, _x) do { \
  51. char tmp_atype[37]; \
  52. PR_snprintf(tmp_atype, sizeof(tmp_atype), _attr, _x); \
  53. MSET(tmp_atype); \
  54. } while (0)
  55. /* DSE callback to monitor stats for a particular instance */
  56. int ldbm_back_monitor_instance_search(Slapi_PBlock *pb, Slapi_Entry *e,
  57. Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
  58. {
  59. ldbm_instance *inst = (ldbm_instance *)arg;
  60. struct ldbminfo *li = NULL;
  61. struct berval val;
  62. struct berval *vals[2];
  63. char buf[BUFSIZ];
  64. u_long hits, tries;
  65. long nentries,maxentries;
  66. size_t size,maxsize;
  67. /* NPCTE fix for bugid 544365, esc 0. <P.R> <04-Jul-2001> */
  68. struct stat astat;
  69. /* end of NPCTE fix for bugid 544365 */
  70. DB_MPOOL_FSTAT **mpfstat = NULL;
  71. int i,j;
  72. char *absolute_pathname = NULL;
  73. /* Get the LDBM Info structure for the ldbm backend */
  74. if (inst->inst_be->be_database == NULL) {
  75. *returncode= LDAP_OPERATIONS_ERROR;
  76. return SLAPI_DSE_CALLBACK_ERROR;
  77. }
  78. li = (struct ldbminfo *)inst->inst_be->be_database->plg_private;
  79. if (li == NULL) {
  80. *returncode= LDAP_OPERATIONS_ERROR;
  81. return SLAPI_DSE_CALLBACK_ERROR;
  82. }
  83. if (inst->inst_be->be_state != BE_STATE_STARTED)
  84. {
  85. *returncode = LDAP_SUCCESS;
  86. return SLAPI_DSE_CALLBACK_OK;
  87. }
  88. vals[0] = &val;
  89. vals[1] = NULL;
  90. /* database name */
  91. PR_snprintf(buf, sizeof(buf), "%s", li->li_plugin->plg_name);
  92. MSET("database");
  93. /* read-only status */
  94. PR_snprintf( buf, sizeof(buf), "%d", inst->inst_be->be_readonly );
  95. MSET("readOnly");
  96. /* fetch cache statistics */
  97. cache_get_stats(&(inst->inst_cache), &hits, &tries,
  98. &nentries, &maxentries, &size, &maxsize);
  99. sprintf(buf, "%lu", hits);
  100. MSET("entryCacheHits");
  101. sprintf(buf, "%lu", tries);
  102. MSET("entryCacheTries");
  103. sprintf(buf, "%lu", (unsigned long)(100.0*(double)hits / (double)(tries > 0 ? tries : 1)));
  104. MSET("entryCacheHitRatio");
  105. sprintf(buf, "%lu", size);
  106. MSET("currentEntryCacheSize");
  107. sprintf(buf, "%lu", maxsize);
  108. MSET("maxEntryCacheSize");
  109. sprintf(buf, "%ld", nentries);
  110. MSET("currentEntryCacheCount");
  111. sprintf(buf, "%ld", maxentries);
  112. MSET("maxEntryCacheCount");
  113. #ifdef DEBUG
  114. {
  115. /* debugging for hash statistics */
  116. char *x;
  117. cache_debug_hash(&(inst->inst_cache), &x);
  118. val.bv_val = x;
  119. val.bv_len = strlen(x);
  120. attrlist_replace(&e->e_attrs, "entrycache-hashtables", vals);
  121. slapi_ch_free((void **)&x);
  122. }
  123. #endif
  124. if (dblayer_memp_stat(li, NULL, &mpfstat) != 0) {
  125. *returncode = LDAP_OPERATIONS_ERROR;
  126. return SLAPI_DSE_CALLBACK_ERROR;
  127. }
  128. for (i = 0;(mpfstat[i] && (mpfstat[i]->file_name != NULL)); i++) {
  129. #ifdef _WIN32
  130. int fpos = 0;
  131. #endif
  132. /* only print out stats on files used by this instance */
  133. if (strlen(mpfstat[i]->file_name) < strlen(inst->inst_dir_name))
  134. continue;
  135. if (strncmp(mpfstat[i]->file_name, inst->inst_dir_name,
  136. strlen(inst->inst_dir_name)) != 0)
  137. continue;
  138. /* Since the filenames are now relative, we need to construct an absolute version
  139. * for the purpose of stat() etc below...
  140. */
  141. slapi_ch_free_string(&absolute_pathname);
  142. absolute_pathname = slapi_ch_smprintf("%s%c%s" , inst->inst_parent_dir_name, get_sep(inst->inst_parent_dir_name), mpfstat[i]->file_name );
  143. /* NPCTE fix for bugid 544365, esc 0. <P.R> <04-Jul-2001> */
  144. /* Hide statistic of deleted files (mainly indexes) */
  145. if (stat(absolute_pathname,&astat))
  146. continue;
  147. /* If the file has been re-created after been deleted
  148. * We should show only statistics for the last instance
  149. * Since SleepyCat returns the statistic of the last open file first,
  150. * we should only display the first statistic record for a given file
  151. */
  152. for (j=0;j<i;j++)
  153. if (!strcmp(mpfstat[i]->file_name,mpfstat[j]->file_name))
  154. break;
  155. if (j<i)
  156. continue;
  157. /* end of NPCTE fix for bugid 544365 */
  158. /* Get each file's stats */
  159. PR_snprintf(buf, sizeof(buf), "%s", mpfstat[i]->file_name);
  160. #ifdef _WIN32
  161. /*
  162. * For NT, switch the last
  163. * backslash to a foward
  164. * slash. - RJP
  165. */
  166. for (fpos = strlen(buf); fpos >= 0; fpos--) {
  167. if (buf[fpos] == '\\') {
  168. buf[fpos] = '/';
  169. break;
  170. }
  171. }
  172. #endif
  173. MSETF("dbFilename-%d", i);
  174. sprintf(buf, "%u", mpfstat[i]->st_cache_hit);
  175. MSETF("dbFileCacheHit-%d", i);
  176. sprintf(buf, "%u", mpfstat[i]->st_cache_miss);
  177. MSETF("dbFileCacheMiss-%d", i);
  178. sprintf(buf, "%u", mpfstat[i]->st_page_in);
  179. MSETF("dbFilePageIn-%d", i);
  180. sprintf(buf, "%u", mpfstat[i]->st_page_out);
  181. MSETF("dbFilePageOut-%d", i);
  182. slapi_ch_free_string(&absolute_pathname);
  183. }
  184. slapi_ch_free_string(&absolute_pathname);
  185. #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR + DB_VERSION_PATCH <= 3204
  186. /* In DB 3.2.4 and earlier, we need to free each element */
  187. for (i = 0; mpfstat[i]; i++)
  188. slapi_ch_free((void **)&mpfstat[i]);
  189. #endif
  190. slapi_ch_free((void **)&mpfstat);
  191. *returncode = LDAP_SUCCESS;
  192. return SLAPI_DSE_CALLBACK_OK;
  193. }
  194. /* monitor global ldbm stats */
  195. int ldbm_back_monitor_search(Slapi_PBlock *pb, Slapi_Entry *e,
  196. Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
  197. {
  198. struct ldbminfo *li = (struct ldbminfo *)arg;
  199. struct berval val;
  200. struct berval *vals[2];
  201. char buf[BUFSIZ];
  202. DB_MPOOL_STAT *mpstat = NULL;
  203. DB_MPOOL_FSTAT **mpfstat = NULL;
  204. u_int32_t cache_tries;
  205. vals[0] = &val;
  206. vals[1] = NULL;
  207. /* database name */
  208. PR_snprintf(buf, sizeof(buf), "%s", li->li_plugin->plg_name);
  209. MSET("database");
  210. /* we have to ask for file stats in order to get correct global stats */
  211. if (dblayer_memp_stat(li, &mpstat, &mpfstat) != 0) {
  212. *returncode = LDAP_OPERATIONS_ERROR;
  213. return SLAPI_DSE_CALLBACK_ERROR;
  214. }
  215. /* cache hits*/
  216. sprintf(buf, "%u", mpstat->st_cache_hit);
  217. MSET("dbCacheHits");
  218. /* cache tries*/
  219. cache_tries = (mpstat->st_cache_miss + mpstat->st_cache_hit);
  220. sprintf(buf, "%u", cache_tries);
  221. MSET("dbCacheTries");
  222. /* cache hit ratio*/
  223. sprintf(buf, "%lu", (unsigned long)(100.0 * (double)mpstat->st_cache_hit / (double)(cache_tries > 0 ? cache_tries : 1) ));
  224. MSET("dbCacheHitRatio");
  225. sprintf(buf, "%u", mpstat->st_page_in);
  226. MSET("dbCachePageIn");
  227. sprintf(buf, "%u", mpstat->st_page_out);
  228. MSET("dbCachePageOut");
  229. sprintf(buf, "%u", mpstat->st_ro_evict);
  230. MSET("dbCacheROEvict");
  231. sprintf(buf, "%u", mpstat->st_rw_evict);
  232. MSET("dbCacheRWEvict");
  233. slapi_ch_free((void **)&mpstat);
  234. if (mpfstat) {
  235. #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR + DB_VERSION_PATCH <= 3204
  236. /* In DB 3.2.4 and earlier, we need to free each element */
  237. int i;
  238. for (i = 0; mpfstat[i]; i++)
  239. slapi_ch_free((void **)&mpfstat[i]);
  240. #endif
  241. slapi_ch_free((void **)&mpfstat);
  242. }
  243. *returncode = LDAP_SUCCESS;
  244. return SLAPI_DSE_CALLBACK_OK;
  245. }
  246. /* monitor global ldbm database stats */
  247. int
  248. ldbm_back_dbmonitor_search(Slapi_PBlock *pb, Slapi_Entry *e,
  249. Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
  250. {
  251. dblayer_private *dbpriv = NULL;
  252. struct ldbminfo *li = NULL;
  253. PR_ASSERT(NULL != arg);
  254. li = (struct ldbminfo*)arg;
  255. dbpriv = (dblayer_private*)li->li_dblayer_private;
  256. PR_ASSERT(NULL != dbpriv);
  257. perfctrs_as_entry( e, dbpriv->perf_private, dbpriv->dblayer_env->dblayer_DB_ENV);
  258. *returncode = LDAP_SUCCESS;
  259. return SLAPI_DSE_CALLBACK_OK;
  260. }