monitor.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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. PRUint64 hits, tries;
  65. long nentries, maxentries, count;
  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. if(entryrdn_get_switch()) {
  114. /* fetch cache statistics */
  115. cache_get_stats(&(inst->inst_dncache), &hits, &tries,
  116. &nentries, &maxentries, &size, &maxsize);
  117. sprintf(buf, "%" NSPRIu64, hits);
  118. MSET("dnCacheHits");
  119. sprintf(buf, "%" NSPRIu64, tries);
  120. MSET("dnCacheTries");
  121. sprintf(buf, "%lu", (unsigned long)(100.0*(double)hits / (double)(tries > 0 ? tries : 1)));
  122. MSET("dnCacheHitRatio");
  123. sprintf(buf, "%lu", size);
  124. MSET("currentDnCacheSize");
  125. sprintf(buf, "%lu", maxsize);
  126. MSET("maxDnCacheSize");
  127. sprintf(buf, "%ld", nentries);
  128. MSET("currentDnCacheCount");
  129. sprintf(buf, "%ld", maxentries);
  130. MSET("maxDnCacheCount");
  131. }
  132. /* normalized dn cache stats */
  133. if(config_get_ndn_cache_enabled()){
  134. ndn_cache_get_stats(&hits, &tries, &size, &maxsize, &count);
  135. sprintf(buf, "%" NSPRIu64, tries);
  136. MSET("normalizedDnCacheTries");
  137. sprintf(buf, "%" NSPRIu64, hits);
  138. MSET("normalizedDnCacheHits");
  139. sprintf(buf, "%" NSPRIu64, tries - hits);
  140. MSET("normalizedDnCacheMisses");
  141. sprintf(buf, "%lu", (unsigned long)(100.0*(double)hits / (double)(tries > 0 ? tries : 1)));
  142. MSET("normalizedDnCacheHitRatio");
  143. sprintf(buf, "%lu", size);
  144. MSET("currentNormalizedDnCacheSize");
  145. if(maxsize == 0){
  146. sprintf(buf, "%d", -1);
  147. } else {
  148. sprintf(buf, "%lu", maxsize);
  149. }
  150. MSET("maxNormalizedDnCacheSize");
  151. sprintf(buf, "%ld", count);
  152. MSET("currentNormalizedDnCacheCount");
  153. }
  154. #ifdef DEBUG
  155. {
  156. /* debugging for hash statistics */
  157. char *x;
  158. cache_debug_hash(&(inst->inst_cache), &x);
  159. val.bv_val = x;
  160. val.bv_len = strlen(x);
  161. attrlist_replace(&e->e_attrs, "entrycache-hashtables", vals);
  162. slapi_ch_free((void **)&x);
  163. }
  164. #endif
  165. if (dblayer_memp_stat(li, NULL, &mpfstat) != 0) {
  166. *returncode = LDAP_OPERATIONS_ERROR;
  167. return SLAPI_DSE_CALLBACK_ERROR;
  168. }
  169. for (i = 0;(mpfstat[i] && (mpfstat[i]->file_name != NULL)); i++) {
  170. #ifdef _WIN32
  171. int fpos = 0;
  172. #endif
  173. /* only print out stats on files used by this instance */
  174. if (strlen(mpfstat[i]->file_name) < strlen(inst->inst_dir_name))
  175. continue;
  176. if (strncmp(mpfstat[i]->file_name, inst->inst_dir_name,
  177. strlen(inst->inst_dir_name)) != 0)
  178. continue;
  179. /* Since the filenames are now relative, we need to construct an absolute version
  180. * for the purpose of stat() etc below...
  181. */
  182. slapi_ch_free_string(&absolute_pathname);
  183. absolute_pathname = slapi_ch_smprintf("%s%c%s" , inst->inst_parent_dir_name, get_sep(inst->inst_parent_dir_name), mpfstat[i]->file_name );
  184. /* NPCTE fix for bugid 544365, esc 0. <P.R> <04-Jul-2001> */
  185. /* Hide statistic of deleted files (mainly indexes) */
  186. if (stat(absolute_pathname,&astat))
  187. continue;
  188. /* If the file has been re-created after been deleted
  189. * We should show only statistics for the last instance
  190. * Since SleepyCat returns the statistic of the last open file first,
  191. * we should only display the first statistic record for a given file
  192. */
  193. for (j=0;j<i;j++)
  194. if (!strcmp(mpfstat[i]->file_name,mpfstat[j]->file_name))
  195. break;
  196. if (j<i)
  197. continue;
  198. /* end of NPCTE fix for bugid 544365 */
  199. /* Get each file's stats */
  200. PR_snprintf(buf, sizeof(buf), "%s", mpfstat[i]->file_name);
  201. #ifdef _WIN32
  202. /*
  203. * For NT, switch the last
  204. * backslash to a foward
  205. * slash. - RJP
  206. */
  207. for (fpos = strlen(buf); fpos >= 0; fpos--) {
  208. if (buf[fpos] == '\\') {
  209. buf[fpos] = '/';
  210. break;
  211. }
  212. }
  213. #endif
  214. MSETF("dbFilename-%d", i);
  215. sprintf(buf, "%u", mpfstat[i]->st_cache_hit);
  216. MSETF("dbFileCacheHit-%d", i);
  217. sprintf(buf, "%u", mpfstat[i]->st_cache_miss);
  218. MSETF("dbFileCacheMiss-%d", i);
  219. sprintf(buf, "%u", mpfstat[i]->st_page_in);
  220. MSETF("dbFilePageIn-%d", i);
  221. sprintf(buf, "%u", mpfstat[i]->st_page_out);
  222. MSETF("dbFilePageOut-%d", i);
  223. slapi_ch_free_string(&absolute_pathname);
  224. }
  225. slapi_ch_free_string(&absolute_pathname);
  226. #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR + DB_VERSION_PATCH <= 3204
  227. /* In DB 3.2.4 and earlier, we need to free each element */
  228. for (i = 0; mpfstat[i]; i++)
  229. slapi_ch_free((void **)&mpfstat[i]);
  230. #endif
  231. slapi_ch_free((void **)&mpfstat);
  232. *returncode = LDAP_SUCCESS;
  233. return SLAPI_DSE_CALLBACK_OK;
  234. }
  235. /* monitor global ldbm stats */
  236. int ldbm_back_monitor_search(Slapi_PBlock *pb, Slapi_Entry *e,
  237. Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
  238. {
  239. struct ldbminfo *li = (struct ldbminfo *)arg;
  240. struct berval val;
  241. struct berval *vals[2];
  242. char buf[BUFSIZ];
  243. DB_MPOOL_STAT *mpstat = NULL;
  244. DB_MPOOL_FSTAT **mpfstat = NULL;
  245. u_int32_t cache_tries;
  246. vals[0] = &val;
  247. vals[1] = NULL;
  248. /* database name */
  249. PR_snprintf(buf, sizeof(buf), "%s", li->li_plugin->plg_name);
  250. MSET("database");
  251. /* we have to ask for file stats in order to get correct global stats */
  252. if (dblayer_memp_stat(li, &mpstat, &mpfstat) != 0) {
  253. *returncode = LDAP_OPERATIONS_ERROR;
  254. return SLAPI_DSE_CALLBACK_ERROR;
  255. }
  256. /* cache hits*/
  257. sprintf(buf, "%u", mpstat->st_cache_hit);
  258. MSET("dbCacheHits");
  259. /* cache tries*/
  260. cache_tries = (mpstat->st_cache_miss + mpstat->st_cache_hit);
  261. sprintf(buf, "%u", cache_tries);
  262. MSET("dbCacheTries");
  263. /* cache hit ratio*/
  264. sprintf(buf, "%lu", (unsigned long)(100.0 * (double)mpstat->st_cache_hit / (double)(cache_tries > 0 ? cache_tries : 1) ));
  265. MSET("dbCacheHitRatio");
  266. sprintf(buf, "%u", mpstat->st_page_in);
  267. MSET("dbCachePageIn");
  268. sprintf(buf, "%u", mpstat->st_page_out);
  269. MSET("dbCachePageOut");
  270. sprintf(buf, "%u", mpstat->st_ro_evict);
  271. MSET("dbCacheROEvict");
  272. sprintf(buf, "%u", mpstat->st_rw_evict);
  273. MSET("dbCacheRWEvict");
  274. slapi_ch_free((void **)&mpstat);
  275. if (mpfstat) {
  276. #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR + DB_VERSION_PATCH <= 3204
  277. /* In DB 3.2.4 and earlier, we need to free each element */
  278. int i;
  279. for (i = 0; mpfstat[i]; i++)
  280. slapi_ch_free((void **)&mpfstat[i]);
  281. #endif
  282. slapi_ch_free((void **)&mpfstat);
  283. }
  284. *returncode = LDAP_SUCCESS;
  285. return SLAPI_DSE_CALLBACK_OK;
  286. }
  287. /* monitor global ldbm database stats */
  288. int
  289. ldbm_back_dbmonitor_search(Slapi_PBlock *pb, Slapi_Entry *e,
  290. Slapi_Entry *entryAfter, int *returncode, char *returntext, void *arg)
  291. {
  292. dblayer_private *dbpriv = NULL;
  293. struct ldbminfo *li = NULL;
  294. PR_ASSERT(NULL != arg);
  295. li = (struct ldbminfo*)arg;
  296. dbpriv = (dblayer_private*)li->li_dblayer_private;
  297. PR_ASSERT(NULL != dbpriv);
  298. perfctrs_as_entry( e, dbpriv->perf_private, dbpriv->dblayer_env->dblayer_DB_ENV);
  299. *returncode = LDAP_SUCCESS;
  300. return SLAPI_DSE_CALLBACK_OK;
  301. }