start.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /*
  13. * start.c
  14. */
  15. #include "back-ldbm.h"
  16. static int initialized = 0;
  17. int
  18. ldbm_back_isinitialized()
  19. {
  20. return initialized;
  21. }
  22. static int
  23. ldbm_back_start_autotune(struct ldbminfo *li) {
  24. Object *inst_obj = NULL;
  25. ldbm_instance *inst = NULL;
  26. /* size_t is a platform unsigned int, IE uint64_t */
  27. size_t total_cache_size = 0;
  28. size_t pagesize = 0;
  29. size_t pages = 0;
  30. size_t procpages __attribute__((unused)) = 0;
  31. size_t availpages = 0;
  32. size_t cache_size_to_configure = 0;
  33. size_t zone_pages = 0;
  34. size_t db_pages = 0;
  35. size_t entry_pages = 0;
  36. size_t import_pages = 0;
  37. size_t zone_size = 0;
  38. size_t import_size = 0;
  39. size_t cache_size = 0;
  40. size_t db_size = 0;
  41. /* For clamping the autotune value to a 64Mb boundary */
  42. size_t clamp_pages = 0;
  43. size_t clamp_div = 0;
  44. size_t clamp_mod = 0;
  45. /* Backend count */
  46. size_t backend_count = 0;
  47. int_fast32_t autosize_percentage = 0;
  48. int_fast32_t autosize_db_percentage_split = 0;
  49. int_fast32_t import_percentage = 0;
  50. int32_t issane = 0;
  51. char *msg = ""; /* This will be set by one of the two cache sizing paths below. */
  52. char size_to_str[32]; /* big enough to hold %ld */
  53. /* == Begin autotune == */
  54. /*
  55. * The process that we take here now defaults to autotune first, then override
  56. * with manual values if so chosen.
  57. *
  58. * This means first off, we need to check for valid autosizing values.
  59. * We then calculate what our system tuning would be. We clamp these to the
  60. * nearest value. IE 487MB would be 510656512 bytes, so we clamp this to
  61. * 536870912 bytes, aka 512MB. This is aligned to 64MB boundaries.
  62. *
  63. * Now that we have these values, we then check the values of dbcachesize
  64. * and cachememsize. If they are 0, we set them to the auto-calculated value.
  65. * If they are non-0, we skip the value.
  66. *
  67. * This way, we are really autotuning on "first run", and if the admin wants
  68. * to up the values, they merely need to reset the value to 0, and let the
  69. * server restart.
  70. *
  71. * wibrown 2017
  72. */
  73. /* sanity check the autosizing values,
  74. no value or sum of values larger than 100.
  75. */
  76. backend_count = objset_size(li->li_instance_set);
  77. /* If autosize == 0, set autosize_per to 10. */
  78. if (li->li_cache_autosize <= 0) {
  79. /* First, set our message. In the case autosize is 0, we calculate some
  80. * sane defaults and populate these values, but it's only on first run.
  81. */
  82. msg = "This can be corrected by altering the values of nsslapd-dbcachesize, nsslapd-cachememsize and nsslapd-dncachememsize\n";
  83. autosize_percentage = 10;
  84. } else {
  85. /* In this case we really are setting the values each start up, so
  86. * change the msg.
  87. */
  88. msg = "This can be corrected by altering the values of nsslapd-cache-autosize, nsslapd-cache-autosize-split and nsslapd-dncachememsize\n";
  89. autosize_percentage = li->li_cache_autosize;
  90. }
  91. /* Has to be less than 0, 0 means to disable I think */
  92. if (li->li_import_cache_autosize < 0) {
  93. import_percentage = 50;
  94. } else {
  95. import_percentage = li->li_import_cache_autosize;
  96. }
  97. /* This doesn't control the availability of the feature, so we can take the
  98. * default from ldbm_config.c
  99. */
  100. autosize_db_percentage_split = li->li_cache_autosize_split;
  101. /* Check the values are sane. */
  102. if ((autosize_percentage > 100) || (import_percentage > 100) || (autosize_db_percentage_split > 100) ||
  103. ((autosize_percentage > 0) && (import_percentage > 0) && (autosize_percentage + import_percentage > 100))) {
  104. slapi_log_err(SLAPI_LOG_CRIT, "ldbm_back_start", "Cache autosizing: bad settings, value or sum of values can not larger than 100.\n");
  105. return SLAPI_FAIL_GENERAL;
  106. }
  107. if (util_info_sys_pages(&pagesize, &pages, &procpages, &availpages) != 0) {
  108. slapi_log_err(SLAPI_LOG_CRIT, "ldbm_back_start", "Unable to determine system page limits\n");
  109. return SLAPI_FAIL_GENERAL;
  110. }
  111. if (pagesize == 0) {
  112. /* If this happens, we are in a very bad state indeed... */
  113. slapi_log_err(SLAPI_LOG_CRIT, "ldbm_back_start", "Unable to determine system page size\n");
  114. return SLAPI_FAIL_GENERAL;
  115. }
  116. /* calculate the needed values */
  117. zone_pages = (autosize_percentage * pages) / 100;
  118. zone_size = zone_pages * pagesize;
  119. /* This is how much we "might" use, lets check it's sane. */
  120. /* In the case it is not, this will *reduce* the allocation */
  121. issane = util_is_cachesize_sane(&zone_size);
  122. if (!issane) {
  123. slapi_log_err(SLAPI_LOG_WARNING, "ldbm_back_start", "Your autosized cache values have been reduced. Likely your nsslapd-cache-autosize percentage is too high.\n");
  124. slapi_log_err(SLAPI_LOG_WARNING, "ldbm_back_start", "%s", msg);
  125. }
  126. /* It's valid, lets divide it up and set according to user prefs */
  127. zone_pages = zone_size / pagesize;
  128. db_pages = (autosize_db_percentage_split * zone_pages) / 100;
  129. /* Cap the DB size at 512MB, as this doesn't help perf much more (lkrispen's advice) */
  130. if ((db_pages * pagesize) > (512 * MEGABYTE)) {
  131. db_pages = (512 * MEGABYTE) / pagesize;
  132. }
  133. /* Number of entry cache pages per backend. */
  134. entry_pages = (zone_pages - db_pages) / backend_count;
  135. /* Now, clamp this value to a 64mb boundary. */
  136. /* How many pages are in 64mb? */
  137. clamp_pages = (64 * MEGABYTE) / pagesize;
  138. /* Now divide the entry pages by this, and also mod. If mod != 0, we need
  139. * to add 1 to the diveded number. This should give us:
  140. * 510 * 1024 * 1024 == 510MB
  141. * 534773760 bytes
  142. * 130560 pages at 4096 pages.
  143. * 16384 pages for 64Mb
  144. * 130560 / 16384 = 7
  145. * 130560 % 16384 = 15872 which is != 0
  146. * therfore 7 + 1, aka 8 * 16384 = 131072 pages = 536870912 bytes = 512MB.
  147. */
  148. clamp_div = entry_pages / clamp_pages;
  149. clamp_mod = entry_pages % clamp_pages;
  150. if (clamp_mod != 0) {
  151. /* If we want to clamp down, remove this line. This would change the above from 510mb -> 448mb. */
  152. clamp_div += 1;
  153. entry_pages = clamp_div * clamp_pages;
  154. }
  155. slapi_log_err(SLAPI_LOG_NOTICE, "ldbm_back_start", "found %luk physical memory\n", pages*(pagesize/1024));
  156. slapi_log_err(SLAPI_LOG_NOTICE, "ldbm_back_start", "found %luk avaliable\n", zone_pages*(pagesize/1024));
  157. /* We've now calculated the autotuning values. Do we need to apply it?
  158. * we use the logic of "if size is 0, or autosize is > 0. This way three
  159. * options can happen.
  160. *
  161. * First, during first run, dbcache is 0, and autosize is 0. So we apply
  162. * the autotuned value ONLY on first run.
  163. * Second, once the admin sets a value, or autotuning set a value, it sticks.
  164. * Third, if the admin really does want autosizing to take effect every
  165. * start up, we disregard the defined value.
  166. */
  167. /* First, check the dbcache */
  168. if (li->li_dbcachesize == 0 || li->li_cache_autosize > 0) {
  169. slapi_log_err(SLAPI_LOG_NOTICE, "ldbm_back_start", "cache autosizing: db cache: %luk\n", db_pages*(pagesize/1024));
  170. cache_size_to_configure = (unsigned long)(db_pages * pagesize);
  171. if (cache_size_to_configure < (500 * MEGABYTE)) {
  172. cache_size_to_configure = (unsigned long)((db_pages * pagesize) / 1.25);
  173. }
  174. /* Have to set this value through text. */
  175. sprintf(size_to_str, "%lu", cache_size_to_configure);
  176. ldbm_config_internal_set(li, CONFIG_DBCACHESIZE, size_to_str);
  177. }
  178. total_cache_size += li->li_dbcachesize;
  179. /* For each backend */
  180. /* apply the appropriate cache size if 0 */
  181. li->li_cache_autosize_ec = (unsigned long)entry_pages * pagesize;
  182. for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
  183. inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) {
  184. inst = (ldbm_instance *)object_get_data(inst_obj);
  185. cache_size = (PRUint64)cache_get_max_size(&(inst->inst_cache));
  186. /* This is the point where we decide to apply or not.
  187. * We have to check for the mincachesize as setting 0 resets
  188. * to this value. This could cause an issue with a *tiny* install, but
  189. * it's highly unlikely.
  190. */
  191. if (cache_size == 0 || cache_size == MINCACHESIZE || li->li_cache_autosize > 0) {
  192. slapi_log_err(SLAPI_LOG_NOTICE, "ldbm_back_start", "cache autosizing: %s entry cache (%lu total): %luk\n", inst->inst_name, backend_count, entry_pages*(pagesize/1024));
  193. cache_set_max_entries(&(inst->inst_cache), -1);
  194. cache_set_max_size(&(inst->inst_cache), li->li_cache_autosize_ec, CACHE_TYPE_ENTRY);
  195. }
  196. /* Refresh this value now. */
  197. cache_size = (PRUint64)cache_get_max_size(&(inst->inst_cache));
  198. db_size = dblayer_get_id2entry_size(inst);
  199. if (cache_size < db_size) {
  200. slapi_log_err(SLAPI_LOG_NOTICE, "ldbm_back_start",
  201. "%s: entry cache size %lu B is "
  202. "less than db size %lu B; "
  203. "We recommend to increase the entry cache size "
  204. "nsslapd-cachememsize.\n",
  205. inst->inst_name, cache_size, db_size);
  206. }
  207. /* We need to get each instances dncache size to add to the total */
  208. /* Else we can't properly check the cache allocations below */
  209. /* Trac 48831 exists to allow this to be auto-sized too ... */
  210. total_cache_size += (PRUint64)cache_get_max_size(&(inst->inst_dncache));
  211. total_cache_size += cache_size;
  212. }
  213. /* autosizing importCache */
  214. if (li->li_import_cache_autosize > 0) {
  215. /* Use import percentage here, as it's been corrected for -1 behaviour */
  216. import_pages = (import_percentage * pages) / 100;
  217. import_size = import_pages * pagesize;
  218. issane = util_is_cachesize_sane(&import_size);
  219. if (!issane) {
  220. slapi_log_err(SLAPI_LOG_WARNING, "ldbm_back_start", "Your autosized import cache values have been reduced. Likely your nsslapd-import-cache-autosize percentage is too high.\n");
  221. }
  222. /* We just accept the reduced allocation here. */
  223. import_pages = import_size / pagesize;
  224. slapi_log_err(SLAPI_LOG_NOTICE, "ldbm_back_start", "cache autosizing: import cache: %luk\n",
  225. import_pages*(pagesize/1024));
  226. sprintf(size_to_str, "%lu", (unsigned long)(import_pages * pagesize));
  227. ldbm_config_internal_set(li, CONFIG_IMPORT_CACHESIZE, size_to_str);
  228. }
  229. /* Finally, lets check that the total result is sane. */
  230. slapi_log_err(SLAPI_LOG_NOTICE, "ldbm_back_start", "total cache size: %lu B; \n", total_cache_size);
  231. issane = util_is_cachesize_sane(&total_cache_size);
  232. if (!issane) {
  233. /* Right, it's time to panic */
  234. slapi_log_err(SLAPI_LOG_CRIT, "ldbm_back_start", "It is highly likely your memory configuration of all backends will EXCEED your systems memory.\n");
  235. slapi_log_err(SLAPI_LOG_CRIT, "ldbm_back_start", "In a future release this WILL prevent server start up. You MUST alter your configuration.\n");
  236. slapi_log_err(SLAPI_LOG_CRIT, "ldbm_back_start", "Total entry cache size: %lu B; dbcache size: %lu B; available memory size: %lu B; \n",
  237. (PRUint64)total_cache_size, (PRUint64)li->li_dbcachesize, availpages * pagesize
  238. );
  239. slapi_log_err(SLAPI_LOG_CRIT, "ldbm_back_start", "%s\n", msg);
  240. /* WB 2016 - This should be UNCOMMENTED in a future release */
  241. /* return SLAPI_FAIL_GENERAL; */
  242. }
  243. /* == End autotune == */
  244. return 0;
  245. }
  246. /*
  247. * Start the LDBM plugin, and all its instances.
  248. */
  249. int
  250. ldbm_back_start( Slapi_PBlock *pb )
  251. {
  252. struct ldbminfo *li;
  253. char *home_dir = NULL;
  254. int action = 0 ;
  255. int retval = 0;
  256. slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_start", "ldbm backend starting\n");
  257. slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
  258. /* parse the config file here */
  259. if (0 != ldbm_config_load_dse_info(li)) {
  260. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Loading database configuration failed\n");
  261. return SLAPI_FAIL_GENERAL;
  262. }
  263. /* register with the binder-based resource limit subsystem so that */
  264. /* lookthroughlimit can be supported on a per-connection basis. */
  265. if ( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT,
  266. LDBM_LOOKTHROUGHLIMIT_AT, &li->li_reslimit_lookthrough_handle )
  267. != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
  268. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Resource limit registration failed for lookthroughlimit\n");
  269. return SLAPI_FAIL_GENERAL;
  270. }
  271. /* register with the binder-based resource limit subsystem so that */
  272. /* allidslimit (aka idlistscanlimit) can be supported on a per-connection basis. */
  273. if ( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT,
  274. LDBM_ALLIDSLIMIT_AT, &li->li_reslimit_allids_handle )
  275. != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
  276. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Resource limit registration failed for allidslimit\n");
  277. return SLAPI_FAIL_GENERAL;
  278. }
  279. /* register with the binder-based resource limit subsystem so that */
  280. /* pagedlookthroughlimit can be supported on a per-connection basis. */
  281. if ( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT,
  282. LDBM_PAGEDLOOKTHROUGHLIMIT_AT, &li->li_reslimit_pagedlookthrough_handle )
  283. != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
  284. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Resource limit registration failed for pagedlookthroughlimit\n");
  285. return SLAPI_FAIL_GENERAL;
  286. }
  287. /* register with the binder-based resource limit subsystem so that */
  288. /* pagedallidslimit (aka idlistscanlimit) can be supported on a per-connection basis. */
  289. if ( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT,
  290. LDBM_PAGEDALLIDSLIMIT_AT, &li->li_reslimit_pagedallids_handle )
  291. != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
  292. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Resource limit registration failed for pagedallidslimit\n");
  293. return SLAPI_FAIL_GENERAL;
  294. }
  295. /* lookthrough limit for the rangesearch */
  296. if ( slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT,
  297. LDBM_RANGELOOKTHROUGHLIMIT_AT, &li->li_reslimit_rangelookthrough_handle )
  298. != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
  299. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Resource limit registration failed for rangelookthroughlimit\n");
  300. return SLAPI_FAIL_GENERAL;
  301. }
  302. /* If the db directory hasn't been set yet, we need to set it to
  303. * the default. */
  304. if (NULL == li->li_directory || '\0' == li->li_directory[0]) {
  305. /* "get default" is a special string that tells the config
  306. * routines to figure out the default db directory by
  307. * reading cn=config. */
  308. ldbm_config_internal_set(li, CONFIG_DIRECTORY, "get default");
  309. }
  310. retval = ldbm_back_start_autotune(li);
  311. if (retval != 0) {
  312. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Failed to set database tuning on backends\n");
  313. return SLAPI_FAIL_GENERAL;
  314. }
  315. retval = check_db_version(li, &action);
  316. if (0 != retval)
  317. {
  318. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "db version is not supported\n");
  319. return SLAPI_FAIL_GENERAL;
  320. }
  321. if (action &
  322. (DBVERSION_UPGRADE_3_4|DBVERSION_UPGRADE_4_4|DBVERSION_UPGRADE_4_5))
  323. {
  324. retval = dblayer_start(li,DBLAYER_CLEAN_RECOVER_MODE);
  325. }
  326. else
  327. {
  328. retval = dblayer_start(li,DBLAYER_NORMAL_MODE);
  329. }
  330. if (0 != retval) {
  331. char *msg;
  332. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Failed to init database, err=%d %s\n",
  333. retval, (msg = dblayer_strerror( retval )) ? msg : "");
  334. if (LDBM_OS_ERR_IS_DISKFULL(retval)) return return_on_disk_full(li);
  335. else return SLAPI_FAIL_GENERAL;
  336. }
  337. /* Walk down the instance list, starting all the instances. */
  338. retval = ldbm_instance_startall(li);
  339. if (0 != retval) {
  340. char *msg;
  341. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Failed to start databases, err=%d %s\n",
  342. retval, (msg = dblayer_strerror( retval )) ? msg : "");
  343. if (LDBM_OS_ERR_IS_DISKFULL(retval)) return return_on_disk_full(li);
  344. else {
  345. if ((li->li_cache_autosize > 0) && (li->li_cache_autosize <= 100)) {
  346. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_start", "Failed to allocate %lu byte dbcache. "
  347. "Please reduce the value of %s and restart the server.\n",
  348. li->li_dbcachesize, CONFIG_CACHE_AUTOSIZE);
  349. }
  350. return SLAPI_FAIL_GENERAL;
  351. }
  352. }
  353. /* write DBVERSION file if one does not exist */
  354. home_dir = dblayer_get_home_dir(li, NULL);
  355. if (!dbversion_exists(li, home_dir))
  356. {
  357. dbversion_write (li, home_dir, NULL, DBVERSION_ALL);
  358. }
  359. /* this function is called every time new db is initialized */
  360. /* currently it is called the 2nd time when changelog db is */
  361. /* dynamically created. Code below should only be called once */
  362. if (!initialized)
  363. {
  364. ldbm_compute_init();
  365. initialized = 1;
  366. }
  367. /* initialize the USN counter */
  368. ldbm_usn_init(li);
  369. slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_start", "ldbm backend done starting\n");
  370. return( 0 );
  371. }