From 950c0c6bf7515e02f88543e8f477ec717725849f Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@totoro.usersys.redhat.com>
Date: Wed, 25 Jul 2012 10:19:14 -0700
Subject: [PATCH] Trac Ticket #409 - Report during startup if
 nsslapd-cachememsize is too small

https://fedorahosted.org/389/ticket/409

Fix description: adding a code to compare the entry cache size with
the main db file (id2entry.db) size.  If the entry cache size is
less than the db file size, it logs the warning in the error log.
---
 ldap/servers/slapd/back-ldbm/dblayer.c         |   39 +++++++++++++++++++----
 ldap/servers/slapd/back-ldbm/proto-back-ldbm.h |    1 +
 ldap/servers/slapd/back-ldbm/start.c           |   36 ++++++++++++++++++++--
 3 files changed, 66 insertions(+), 10 deletions(-)

diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index eb32709..5452d6b 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -1892,6 +1892,30 @@ check_and_set_import_cache(struct ldbminfo *li)
     return 0;
 }
 
+size_t
+dblayer_get_id2entry_size(ldbm_instance *inst)
+{
+    struct ldbminfo *li = NULL;
+    char *id2entry_file = NULL;
+    PRFileInfo info;
+    int rc;
+    char inst_dir[MAXPATHLEN], *inst_dirp;
+
+    if (NULL == inst) {
+        return 0;
+    }
+    li = inst->inst_li;
+    inst_dirp = dblayer_get_full_inst_dir(li, inst, inst_dir, MAXPATHLEN);
+    id2entry_file = slapi_ch_smprintf("%s/%s", inst_dirp,
+                                      ID2ENTRY LDBM_FILENAME_SUFFIX);
+    rc = PR_GetFileInfo(id2entry_file, &info);
+    slapi_ch_free_string(&id2entry_file);
+    if (rc) {
+        return 0;
+    }
+    return info.size;
+}
+
 /* mode is one of
  * DBLAYER_NORMAL_MODE,
  * DBLAYER_INDEX_MODE,
@@ -2254,7 +2278,7 @@ int dblayer_instance_start(backend *be, int mode)
         dbp->set_cache_priority(dbp, DB_PRIORITY_LOW);
 #endif
 out:
-        slapi_ch_free((void**)&id2entry_file);
+        slapi_ch_free_string(&id2entry_file);
     }
 
     if (0 == return_value) {
@@ -2511,16 +2535,17 @@ err:
        (*ppEnv)->close(*ppEnv, 0);
        *ppEnv = NULL;
     }
-    if (id2entry_file) {
-        slapi_ch_free_string(&id2entry_file);
-    }
     if (priv->dblayer_home_directory) {
         ldbm_delete_dirs(priv->dblayer_home_directory);
     }
 done:
-    if ((0 == rval) && path) { /* only when successfull */
-        *path = slapi_ch_smprintf("%s/%s",
-                                  inst->inst_parent_dir_name, id2entry_file);
+    if (path) {
+        if (0 == rval) { /* return the path only when successfull */
+            *path = slapi_ch_smprintf("%s/%s", inst->inst_parent_dir_name,
+                                      id2entry_file);
+        } else {
+            *path = NULL;
+        }
     }
     slapi_ch_free_string(&id2entry_file);
     if (priv) {
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
index 03e0b11..be4120a 100644
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -174,6 +174,7 @@ int dblayer_db_uses_mpool(DB_ENV *db_env);
 int dblayer_db_uses_logging(DB_ENV *db_env);
 int dblayer_bt_compare(DB *db, const DBT *dbt1, const DBT *dbt2);
 int dblayer_remove_env(struct ldbminfo *li);
+size_t dblayer_get_id2entry_size(ldbm_instance *inst);
 
 int ldbm_back_get_info(Slapi_Backend *be, int cmd, void **info);
 int ldbm_back_set_info(Slapi_Backend *be, int cmd, void *info);
diff --git a/ldap/servers/slapd/back-ldbm/start.c b/ldap/servers/slapd/back-ldbm/start.c
index 61146fe..0f42bed 100644
--- a/ldap/servers/slapd/back-ldbm/start.c
+++ b/ldap/servers/slapd/back-ldbm/start.c
@@ -135,9 +135,7 @@ ldbm_back_start( Slapi_PBlock *pb )
       (li->li_cache_autosize + li->li_import_cache_autosize > 100))) {
       LDAPDebug( LDAP_DEBUG_ANY, "cache autosizing: bad settings, "
         "value or sum of values can not larger than 100.\n", 0, 0, 0 );
-  } else
-  /* if cache autosize was selected, select the cache sizes now */
-  if ((li->li_cache_autosize > 0) || (li->li_import_cache_autosize > 0)) {
+  } else {
       size_t pagesize, pages, procpages, availpages;
 
       dblayer_sys_pages(&pagesize, &pages, &procpages, &availpages);
@@ -147,6 +145,38 @@ ldbm_back_start( Slapi_PBlock *pb )
           int zone_pages, db_pages, entry_pages, import_pages;
           Object *inst_obj;
           ldbm_instance *inst;   
+          size_t cache_size;
+          size_t db_size;
+          size_t total_cache_size = 0;
+          size_t memsize = pages * pagesize;
+          size_t extra = 0; /* e.g., dncache size */
+
+          for (inst_obj = objset_first_obj(li->li_instance_set); inst_obj;
+               inst_obj = objset_next_obj(li->li_instance_set, inst_obj)) {
+              inst = (ldbm_instance *)object_get_data(inst_obj);
+              cache_size = cache_get_max_size(&(inst->inst_cache));
+              db_size = dblayer_get_id2entry_size(inst);
+              if (cache_size < db_size) {
+                  LDAPDebug(LDAP_DEBUG_ANY,
+                            "WARNING: %s: entry cache size %luB is "
+                            "less than db size %luB; "
+                            "We recommend to increase the entry cache size "
+                            "nsslapd-cachememsize.\n",
+                            inst->inst_name, cache_size, db_size);
+              } else {
+                  LDAPDebug(LDAP_DEBUG_BACKLDBM,
+                            "%s: entry cache size: %luB; db size: %luB\n",
+                            inst->inst_name, cache_size, db_size);
+              }
+              total_cache_size += cache_size;
+              /* estimated overhead: dncache size * 2 */
+              extra += cache_get_max_size(&(inst->inst_dncache)) * 2;
+          }
+          LDAPDebug(LDAP_DEBUG_BACKLDBM,
+                    "Total entry cache size: %luB; "
+                    "dbcache size: %luB; "
+                    "available memory size: %luB\n",
+                    total_cache_size, li->li_dbcachesize, memsize - extra);
           /* autosizing dbCache and entryCache */
           if (li->li_cache_autosize > 0) {
               zone_pages = (li->li_cache_autosize * pages) / 100;
-- 
1.7.7.6

