perfctrs.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  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. /* Database performance counters stuff */
  42. #include "back-ldbm.h"
  43. #include "perfctrs.h"
  44. #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4000
  45. #define TXN_STAT(env, statp, flags, malloc) \
  46. (env)->txn_stat((env), (statp), (flags))
  47. #define MEMP_STAT(env, gsp, fsp, flags, malloc) \
  48. (env)->memp_stat((env), (gsp), (fsp), (flags))
  49. #define LOG_STAT(env, spp, flags, malloc) (env)->log_stat((env), (spp), (flags))
  50. #define LOCK_STAT(env, statp, flags, malloc) \
  51. (env)->lock_stat((env), (statp), (flags))
  52. #if DB_VERSION_MINOR >= 4 /* i.e. 4.4 or later */
  53. #define GET_N_LOCK_WAITS(lockstat) lockstat->st_lock_wait
  54. #else
  55. #define GET_N_LOCK_WAITS(lockstat) lockstat->st_nconflicts
  56. #endif
  57. #else /* older than db 4.0 */
  58. #if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 3300
  59. #define TXN_STAT(env, statp, flags, malloc) txn_stat((env), (statp))
  60. #define MEMP_STAT(env, gsp, fsp, flags, malloc) memp_stat((env), (gsp), (fsp))
  61. #define LOG_STAT(env, spp, flags, malloc) log_stat((env), (spp))
  62. #define LOCK_STAT(env, statp, flags, malloc) lock_stat((env), (statp))
  63. #define GET_N_LOCK_WAITS(lockstat) lockstat->st_nconflicts
  64. #else /* older than db 3.3 */
  65. #define TXN_STAT(env, statp, flags, malloc) txn_stat((env), (statp), (malloc))
  66. #define MEMP_STAT(env, gsp, fsp, flags, malloc)
  67. memp_stat((env), (gsp), (fsp), (malloc))
  68. #define LOG_STAT(env, spp, flags, malloc) log_stat((env), (spp), (malloc))
  69. #define LOCK_STAT(env, statp, flags, malloc) lock_stat((env), (statp), (malloc))
  70. #define GET_N_LOCK_WAITS(lockstat) lockstat->st_nconflicts
  71. #endif
  72. #endif
  73. static void perfctrs_update(perfctrs_private *priv, DB_ENV *db_env);
  74. static void perfctr_add_to_entry( Slapi_Entry *e, char *type,
  75. PRUint32 countervalue );
  76. /*
  77. * Win32 specific code (to support the Windows NT/2000 Performance Monitor).
  78. */
  79. #if defined(_WIN32)
  80. static
  81. char * string_concatenate(char *a, char* b)
  82. {
  83. size_t string_length = 0;
  84. char *string = NULL;
  85. string_length = strlen(a) + strlen(b) + 1;
  86. string = slapi_ch_malloc(string_length);
  87. sprintf(string,"%s%s",a,b);
  88. return string;
  89. }
  90. static void init_shared_memory(perfctrs_private *priv)
  91. {
  92. performance_counters *perf = (performance_counters*)priv->memory;
  93. if (NULL != perf) {
  94. memset(perf,0,sizeof(performance_counters));
  95. }
  96. }
  97. static int open_event(char *name, perfctrs_private *priv)
  98. {
  99. HANDLE hEvent = INVALID_HANDLE_VALUE;
  100. hEvent = OpenEvent(EVENT_ALL_ACCESS,FALSE,name);
  101. if (NULL == hEvent) {
  102. hEvent = CreateEvent(NULL,FALSE,FALSE,name);
  103. if (NULL == hEvent) {
  104. LDAPDebug(LDAP_DEBUG_ANY,"BAD EV 1, err=%d\n",GetLastError(),0,0);
  105. return -1;
  106. }
  107. }
  108. priv->hEvent = hEvent;
  109. return 0;
  110. }
  111. static int open_shared_memory(char *name, perfctrs_private *priv)
  112. {
  113. HANDLE hMapping = INVALID_HANDLE_VALUE;
  114. void *pMemory = NULL;
  115. /* We fear a bug in NT where it fails to attach to an existing region on calling CreateFileMapping, so let's call OpenFileMapping first */
  116. hMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,name);
  117. if (NULL == hMapping) {
  118. hMapping = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,sizeof(performance_counters),name);
  119. if (NULL == hMapping) {
  120. LDAPDebug(LDAP_DEBUG_ANY,"BAD MAP 1, err=%d\n",GetLastError(),0,0);
  121. return -1;
  122. }
  123. }
  124. /* If we got to here, we have the mapping object open */
  125. pMemory = MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0);
  126. if (NULL == pMemory) {
  127. LDAPDebug(LDAP_DEBUG_ANY,"BAD MAP 2, err=%d\n",GetLastError(),0,0);
  128. return -1;
  129. }
  130. priv->memory = pMemory;
  131. priv->hMemory = hMapping;
  132. return 0;
  133. }
  134. #endif
  135. /* Init perf ctrs */
  136. void perfctrs_init(struct ldbminfo *li, perfctrs_private **ret_priv)
  137. {
  138. perfctrs_private *priv = NULL;
  139. #if defined(_WIN32)
  140. /* XXX What's my instance name ? */
  141. /*
  142. * We have a single DB environment for all backend databases.
  143. * Therefore the instance name can be the server instance name.
  144. * To match the db perf ctr DLL the instance name should be the
  145. * name of a key defined in the registry under:
  146. * HKEY_LOCAL_MACHINE\SOFTWARE\Netscape\Directory\5
  147. * i.e. slapd-servername
  148. */
  149. char *string = NULL;
  150. char *instance_name = li->li_plugin->plg_name; /* XXX does not identify server instance */
  151. #endif
  152. *ret_priv = NULL;
  153. #if defined(_WIN32)
  154. /*
  155. * On Windows, the performance counters reside in shared memory.
  156. */
  157. if (NULL == instance_name) {
  158. goto error;
  159. }
  160. /* Invent the name for the shared memory region */
  161. string = string_concatenate(instance_name,PERFCTRS_REGION_SUFFIX);
  162. if (NULL == string) {
  163. goto error;
  164. }
  165. #endif
  166. /*
  167. * We need the perfctrs_private area on all platforms.
  168. */
  169. priv = (perfctrs_private *)slapi_ch_calloc(1,sizeof(perfctrs_private));
  170. #if defined(_WIN32)
  171. /* Try to open the shared memory region */
  172. open_shared_memory(string,priv);
  173. free(string);
  174. /* Invent the name for the update mutex */
  175. string = string_concatenate(instance_name,PERFCTRS_MUTEX_SUFFIX);
  176. if (NULL == string) {
  177. goto error;
  178. }
  179. open_event(string,priv);
  180. free(string);
  181. init_shared_memory(priv);
  182. #else
  183. /*
  184. * On other platforms, the performance counters reside in regular memory.
  185. */
  186. priv->memory = slapi_ch_calloc( 1, sizeof( performance_counters ));
  187. #endif
  188. *ret_priv = priv;
  189. return;
  190. #if defined(_WIN32)
  191. error:
  192. slapi_ch_free((void**)&priv);
  193. return;
  194. #endif
  195. }
  196. /* Terminate perf ctrs */
  197. void perfctrs_terminate(perfctrs_private **priv, DB_ENV *db_env)
  198. {
  199. DB_MPOOL_STAT *mpstat = NULL;
  200. DB_TXN_STAT *txnstat = NULL;
  201. DB_LOG_STAT *logstat = NULL;
  202. DB_LOCK_STAT *lockstat = NULL;
  203. MEMP_STAT(db_env, &mpstat, NULL, DB_STAT_CLEAR, (void *)slapi_ch_malloc);
  204. slapi_ch_free((void**)&mpstat);
  205. TXN_STAT(db_env, &txnstat, DB_STAT_CLEAR, (void *)slapi_ch_malloc);
  206. slapi_ch_free((void**)&txnstat);
  207. LOG_STAT(db_env, &logstat, DB_STAT_CLEAR, (void *)slapi_ch_malloc);
  208. slapi_ch_free((void**)&logstat);
  209. LOCK_STAT(db_env, &lockstat, DB_STAT_CLEAR, (void *)slapi_ch_malloc);
  210. slapi_ch_free((void**)&lockstat);
  211. #if defined(_WIN32)
  212. if (NULL != (*priv)->memory) {
  213. UnmapViewOfFile((*priv)->memory);
  214. }
  215. if (NULL != (*priv)->hMemory) {
  216. CloseHandle((*priv)->hMemory);
  217. }
  218. if (NULL != (*priv)->hEvent) {
  219. CloseHandle((*priv)->hEvent);
  220. }
  221. #else
  222. if (NULL != (*priv)->memory) {
  223. slapi_ch_free(&(*priv)->memory);
  224. }
  225. #endif
  226. slapi_ch_free( (void **)priv );
  227. }
  228. /* Wait while checking for perfctr update requests */
  229. void perfctrs_wait(size_t milliseconds,perfctrs_private *priv,DB_ENV *db_env)
  230. {
  231. #if defined(_WIN32)
  232. if (NULL != priv) {
  233. DWORD ret = 0;
  234. if (NULL != priv->hEvent) {
  235. /* Sleep waiting on the perfctrs update event */
  236. ret = WaitForSingleObject(priv->hEvent,milliseconds);
  237. /* If we didn't time out, update the perfctrs */
  238. if (ret == WAIT_OBJECT_0) {
  239. perfctrs_update(priv,db_env);
  240. }
  241. } else {
  242. Sleep(milliseconds);
  243. }
  244. }
  245. #else
  246. /* Just sleep */
  247. PRIntervalTime interval; /*NSPR timeout stuffy*/
  248. interval = PR_MillisecondsToInterval(milliseconds);
  249. DS_Sleep(interval);
  250. #endif
  251. }
  252. /* Update perfctrs */
  253. static
  254. void perfctrs_update(perfctrs_private *priv, DB_ENV *db_env)
  255. {
  256. int ret = 0;
  257. performance_counters *perf;
  258. if (NULL == priv) {
  259. return;
  260. }
  261. if (NULL == db_env) {
  262. return;
  263. }
  264. perf = (performance_counters*)priv->memory;
  265. if (NULL == perf) {
  266. return;
  267. }
  268. /* Call libdb to get the various stats */
  269. if (dblayer_db_uses_logging(db_env))
  270. {
  271. DB_LOG_STAT *logstat = NULL;
  272. ret = LOG_STAT(db_env,&logstat,0,(void *)slapi_ch_malloc);
  273. if (0 == ret) {
  274. perf->log_region_wait_rate = logstat->st_region_wait;
  275. perf->log_write_rate = 1024*1024*logstat->st_w_mbytes + logstat->st_w_bytes;
  276. perf->log_bytes_since_checkpoint = 1024*1024*logstat->st_wc_mbytes + logstat->st_wc_bytes;
  277. }
  278. slapi_ch_free((void **)&logstat);
  279. }
  280. if (dblayer_db_uses_transactions(db_env))
  281. {
  282. DB_TXN_STAT *txnstat = NULL;
  283. ret = TXN_STAT(db_env, &txnstat, 0, (void *)slapi_ch_malloc);
  284. if (0 == ret) {
  285. perf->active_txns = txnstat->st_nactive;
  286. perf->commit_rate = txnstat->st_ncommits;
  287. perf->abort_rate = txnstat->st_naborts;
  288. perf->txn_region_wait_rate = txnstat->st_region_wait;
  289. }
  290. slapi_ch_free((void **)&txnstat);
  291. }
  292. if (dblayer_db_uses_locking(db_env))
  293. {
  294. DB_LOCK_STAT *lockstat = NULL;
  295. ret = LOCK_STAT(db_env,&lockstat,0,(void *)slapi_ch_malloc);
  296. if (0 == ret) {
  297. perf->lock_region_wait_rate = lockstat->st_region_wait;
  298. perf->deadlock_rate = lockstat->st_ndeadlocks;
  299. perf->configured_locks = lockstat->st_maxlocks;
  300. perf->current_locks = lockstat->st_nlocks;
  301. perf->max_locks = lockstat->st_maxnlocks;
  302. perf->lockers = lockstat->st_nlockers;
  303. perf->lock_conflicts = GET_N_LOCK_WAITS(lockstat);
  304. perf->lock_request_rate = lockstat->st_nrequests;
  305. perf->current_lock_objects = lockstat->st_nobjects;
  306. perf->max_lock_objects = lockstat->st_maxnobjects;
  307. }
  308. slapi_ch_free((void **)&lockstat);
  309. }
  310. if (dblayer_db_uses_mpool(db_env))
  311. {
  312. DB_MPOOL_STAT *mpstat = NULL;
  313. ret = MEMP_STAT(db_env,&mpstat,NULL,0,(void *)slapi_ch_malloc);
  314. if (0 == ret) {
  315. #define ONEG 1073741824
  316. perf->cache_size_bytes = mpstat->st_gbytes * ONEG + mpstat->st_bytes;
  317. perf->page_access_rate = mpstat->st_cache_hit + mpstat->st_cache_miss;
  318. perf->cache_hit = mpstat->st_cache_hit;
  319. perf->cache_try = mpstat->st_cache_hit + mpstat->st_cache_miss;
  320. perf->page_create_rate = mpstat->st_page_create;
  321. perf->page_read_rate = mpstat->st_page_in;
  322. perf->page_write_rate = mpstat->st_page_out;
  323. perf->page_ro_evict_rate = mpstat->st_ro_evict;
  324. perf->page_rw_evict_rate = mpstat->st_rw_evict;
  325. perf->hash_buckets = mpstat->st_hash_buckets;
  326. perf->hash_search_rate = mpstat->st_hash_searches;
  327. perf->longest_chain_length = mpstat->st_hash_longest;
  328. perf->hash_elements_examine_rate = mpstat->st_hash_examined;
  329. perf->pages_in_use = mpstat->st_page_dirty + mpstat->st_page_clean;
  330. perf->dirty_pages = mpstat->st_page_dirty;
  331. perf->clean_pages = mpstat->st_page_clean;
  332. perf->page_trickle_rate = mpstat->st_page_trickle;
  333. perf->cache_region_wait_rate = mpstat->st_region_wait;
  334. slapi_ch_free((void **)&mpstat);
  335. }
  336. }
  337. /* Place the stats in the shared memory region */
  338. /* Bump the sequence number */
  339. perf->sequence_number++;
  340. }
  341. /*
  342. * Define a map (array of structures) which is used to retrieve performance
  343. * counters from the performance_counters structure and map them to an
  344. * LDAP attribute type.
  345. */
  346. #define SLAPI_LDBM_PERFCTR_AT_PREFIX "nsslapd-db-"
  347. typedef struct slapi_ldbm_perfctr_at_map {
  348. char *pam_type; /* name of LDAP attribute type */
  349. size_t pam_offset; /* offset into performance_counters struct */
  350. } SlapiLDBMPerfctrATMap;
  351. static SlapiLDBMPerfctrATMap perfctr_at_map[] = {
  352. { SLAPI_LDBM_PERFCTR_AT_PREFIX "abort-rate",
  353. offsetof( performance_counters, abort_rate ) },
  354. { SLAPI_LDBM_PERFCTR_AT_PREFIX "active-txns",
  355. offsetof( performance_counters, active_txns ) },
  356. { SLAPI_LDBM_PERFCTR_AT_PREFIX "cache-hit",
  357. offsetof( performance_counters, cache_hit ) },
  358. { SLAPI_LDBM_PERFCTR_AT_PREFIX "cache-try",
  359. offsetof( performance_counters, cache_try ) },
  360. { SLAPI_LDBM_PERFCTR_AT_PREFIX "cache-region-wait-rate",
  361. offsetof( performance_counters, cache_region_wait_rate ) },
  362. { SLAPI_LDBM_PERFCTR_AT_PREFIX "cache-size-bytes",
  363. offsetof( performance_counters, cache_size_bytes ) },
  364. { SLAPI_LDBM_PERFCTR_AT_PREFIX "clean-pages",
  365. offsetof( performance_counters, clean_pages ) },
  366. { SLAPI_LDBM_PERFCTR_AT_PREFIX "commit-rate",
  367. offsetof( performance_counters, commit_rate ) },
  368. { SLAPI_LDBM_PERFCTR_AT_PREFIX "deadlock-rate",
  369. offsetof( performance_counters, deadlock_rate ) },
  370. { SLAPI_LDBM_PERFCTR_AT_PREFIX "dirty-pages",
  371. offsetof( performance_counters, dirty_pages ) },
  372. { SLAPI_LDBM_PERFCTR_AT_PREFIX "hash-buckets",
  373. offsetof( performance_counters, hash_buckets ) },
  374. { SLAPI_LDBM_PERFCTR_AT_PREFIX "hash-elements-examine-rate",
  375. offsetof( performance_counters, hash_elements_examine_rate ) },
  376. { SLAPI_LDBM_PERFCTR_AT_PREFIX "hash-search-rate",
  377. offsetof( performance_counters, hash_search_rate ) },
  378. { SLAPI_LDBM_PERFCTR_AT_PREFIX "lock-conflicts",
  379. offsetof( performance_counters, lock_conflicts ) },
  380. { SLAPI_LDBM_PERFCTR_AT_PREFIX "lock-region-wait-rate",
  381. offsetof( performance_counters, lock_region_wait_rate ) },
  382. { SLAPI_LDBM_PERFCTR_AT_PREFIX "lock-request-rate",
  383. offsetof( performance_counters, lock_request_rate ) },
  384. { SLAPI_LDBM_PERFCTR_AT_PREFIX "lockers",
  385. offsetof( performance_counters, lockers ) },
  386. { SLAPI_LDBM_PERFCTR_AT_PREFIX "configured-locks",
  387. offsetof( performance_counters, configured_locks ) },
  388. { SLAPI_LDBM_PERFCTR_AT_PREFIX "current-locks",
  389. offsetof( performance_counters, current_locks ) },
  390. { SLAPI_LDBM_PERFCTR_AT_PREFIX "max-locks",
  391. offsetof( performance_counters, max_locks ) },
  392. { SLAPI_LDBM_PERFCTR_AT_PREFIX "current-lock-objects",
  393. offsetof( performance_counters, current_lock_objects ) },
  394. { SLAPI_LDBM_PERFCTR_AT_PREFIX "max-lock-objects",
  395. offsetof( performance_counters, max_lock_objects ) },
  396. { SLAPI_LDBM_PERFCTR_AT_PREFIX "log-bytes-since-checkpoint",
  397. offsetof( performance_counters, log_bytes_since_checkpoint ) },
  398. { SLAPI_LDBM_PERFCTR_AT_PREFIX "log-region-wait-rate",
  399. offsetof( performance_counters, log_region_wait_rate ) },
  400. { SLAPI_LDBM_PERFCTR_AT_PREFIX "log-write-rate",
  401. offsetof( performance_counters, log_write_rate ) },
  402. { SLAPI_LDBM_PERFCTR_AT_PREFIX "longest-chain-length",
  403. offsetof( performance_counters, longest_chain_length ) },
  404. { SLAPI_LDBM_PERFCTR_AT_PREFIX "objects-locked",
  405. offsetof( performance_counters, page_access_rate ) },
  406. { SLAPI_LDBM_PERFCTR_AT_PREFIX "page-create-rate",
  407. offsetof( performance_counters, page_create_rate ) },
  408. { SLAPI_LDBM_PERFCTR_AT_PREFIX "page-read-rate",
  409. offsetof( performance_counters, page_read_rate ) },
  410. { SLAPI_LDBM_PERFCTR_AT_PREFIX "page-ro-evict-rate",
  411. offsetof( performance_counters, page_ro_evict_rate ) },
  412. { SLAPI_LDBM_PERFCTR_AT_PREFIX "page-rw-evict-rate",
  413. offsetof( performance_counters, page_rw_evict_rate ) },
  414. { SLAPI_LDBM_PERFCTR_AT_PREFIX "page-trickle-rate",
  415. offsetof( performance_counters, page_trickle_rate ) },
  416. { SLAPI_LDBM_PERFCTR_AT_PREFIX "page-write-rate",
  417. offsetof( performance_counters, page_write_rate ) },
  418. { SLAPI_LDBM_PERFCTR_AT_PREFIX "pages-in-use",
  419. offsetof( performance_counters, pages_in_use ) },
  420. { SLAPI_LDBM_PERFCTR_AT_PREFIX "txn-region-wait-rate",
  421. offsetof( performance_counters, txn_region_wait_rate ) },
  422. };
  423. #define SLAPI_LDBM_PERFCTR_AT_MAP_COUNT \
  424. (sizeof(perfctr_at_map) / sizeof(SlapiLDBMPerfctrATMap))
  425. /*
  426. * Set attributes and values in entry `e' based on performance counter
  427. * information (from `priv').
  428. */
  429. void
  430. perfctrs_as_entry( Slapi_Entry *e, perfctrs_private *priv, DB_ENV *db_env )
  431. {
  432. performance_counters *perf;
  433. int i;
  434. if (priv == NULL) return;
  435. perf = (performance_counters*)priv->memory;
  436. /*
  437. * First, update the values so they are current.
  438. */
  439. perfctrs_update( priv, db_env );
  440. /*
  441. * Then convert all the counters to attribute values.
  442. */
  443. for ( i = 0; i < SLAPI_LDBM_PERFCTR_AT_MAP_COUNT; ++i ) {
  444. perfctr_add_to_entry( e, perfctr_at_map[i].pam_type,
  445. *((PRUint32 *)((char *)perf + perfctr_at_map[i].pam_offset)));
  446. }
  447. }
  448. static void
  449. perfctr_add_to_entry( Slapi_Entry *e, char *type, PRUint32 countervalue )
  450. {
  451. /*
  452. * XXXmcs: the following line assumes that long's are 32 bits or larger,
  453. * which we assume in other places too I am sure.
  454. */
  455. slapi_entry_attr_set_ulong( e, type, (unsigned long)countervalue );
  456. }