perfctrs.c 17 KB

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