ldap/servers/slapd/back-ldbm/dblayer.c | 167 ++++++++++++++++++---------------
1 file changed, 94 insertions(+), 73 deletions(-)
New commits:
commit 98b42326f1ec871c466a24bc8fd1d8e49c35be0a
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Mar 19 14:56:52 2013 -0400
Ticket 574 - problems with dbcachesize disk space calculation
Bug Description: no_diskpace() in dblayer.c was not calculating the available
diskspace correctly. It was checking the main db directory
only, and it never cheked for db_home_directory.
Fix Description: Check for db_home_directory first, and if it's shared/private
memory then skip the check altogether. Otherwise calulate the
correct directory size, and also add to the available space the
size of the region files(__db* files) - as these should be
ignored.
Also did a little code cleanup of the header files.
https://fedorahosted.org/389/ticket/574
Reviewed by: Noriko(Thanks!)
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c
b/ldap/servers/slapd/back-ldbm/dblayer.c
index 5e53de9..16dac03 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -36,11 +36,6 @@
* All rights reserved.
* END COPYRIGHT BLOCK **/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-
/*
Abstraction layer which sits between db2.0 and
higher layers in the directory server---typically
@@ -93,8 +88,18 @@
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include "back-ldbm.h"
#include "dblayer.h"
+#include <prthread.h>
+#include <prclist.h>
+#ifndef XP_WIN32
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include <sys/resource.h>
+#endif
#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4100
#define DB_OPEN(oflags, db, txnid, file, database, type, flags, mode, rval) \
@@ -194,7 +199,7 @@
PR_Unlock(priv->thread_count_lock)
#define NEWDIR_MODE 0755
-
+#define DB_REGION_PREFIX "__db."
static int perf_threadmain(void *param);
static int checkpoint_threadmain(void *param);
@@ -208,7 +213,6 @@ static int dblayer_force_checkpoint(struct ldbminfo *li);
static int log_flush_threadmain(void *param);
static int dblayer_delete_transaction_logs(const char * log_dir);
static int dblayer_is_logfilename(const char* path);
-
static int dblayer_start_log_flush_thread(dblayer_private *priv);
static int dblayer_start_deadlock_thread(struct ldbminfo *li);
static int dblayer_start_checkpoint_thread(struct ldbminfo *li);
@@ -829,16 +833,13 @@ static void dblayer_init_dbenv(DB_ENV *pEnv, dblayer_private *priv)
*/
#ifdef OS_solaris
#include <sys/procfs.h>
-#include <sys/resource.h>
#endif
#ifdef LINUX
#include <linux/kernel.h>
#include <sys/sysinfo.h> /* undocumented (?) */
-#include <sys/resource.h>
#endif
#if defined ( hpux )
#include <sys/pstat.h>
-#include <sys/resource.h>
#endif
#if !defined(_WIN32)
@@ -1353,75 +1354,100 @@ dblayer_get_full_inst_dir(struct ldbminfo *li, ldbm_instance
*inst,
return buf;
}
-#if defined( OS_solaris )
-#include <sys/types.h>
-#include <sys/statvfs.h>
-#endif
+/*
+ * Get the total size of all the __db files
+ */
+static PRUint64
+dblayer_get_region_size(const char *dir)
+{
+ PRFileInfo info;
+ PRDir *dirhandle = NULL;
+ PRDirEntry *direntry = NULL;
+ PRUint64 region_size = 0;
-#if defined( hpux )
-#undef f_type
-#include <sys/types.h>
-#include <sys/statvfs.h>
-#define f_type f_un.f_un_type
-#endif
+ dirhandle = PR_OpenDir(dir);
+ if (NULL == dirhandle){
+ return region_size;
+ }
+ while (NULL != (direntry = PR_ReadDir(dirhandle, PR_SKIP_DOT | PR_SKIP_DOT_DOT))){
+ if (NULL == direntry->name){
+ continue;
+ }
+ if (0 == strncmp(direntry->name, DB_REGION_PREFIX, 5)){
+ char filename[MAXPATHLEN];
-#if defined( linux )
-#undef f_type
-#include <sys/vfs.h>
-#define f_type f_un.f_un_type
-#endif
+ PR_snprintf(filename, MAXPATHLEN, "%s/%s", dir,
direntry->name);
+ if (PR_GetFileInfo(filename, &info) != PR_FAILURE){
+ region_size += info.size;
+ }
+ }
+ }
+ PR_CloseDir(dirhandle);
+ return region_size;
+}
+
+/*
+ * Check that there is enough room for the dbcache and region files.
+ * We can ignore this check if using db_home_dir and shared/private memory.
+ */
static int
-no_diskspace(struct ldbminfo *li)
+no_diskspace(struct ldbminfo *li, int dbenv_flags)
{
- int rval = 0;
-#if defined( OS_solaris ) || defined( hpux )
- struct statvfs fsbuf;
- if (statvfs(li->li_directory, &fsbuf) < 0)
- {
+ struct statvfs dbhome_buf;
+ struct statvfs db_buf;
+ int using_shared_mem = (dbenv_flags & ( DB_PRIVATE | DB_SYSTEM_MEM));
+ PRUint64 expected_siz = li->li_dbcachesize * 1.5; /* dbcache + region files */
+ PRUint64 fsiz;
+ char *region_dir;
+
+ if (statvfs(li->li_directory, &db_buf) < 0){
LDAPDebug(LDAP_DEBUG_ANY,
- "Cannot get file system info; file system corrupted?\n", 0, 0, 0);
- rval = 1;
- }
- else
- {
- double fsiz = ((double)fsbuf.f_bavail) * fsbuf.f_frsize;
- double expected_siz = ((double)li->li_dbcachesize) * 1.5; /* dbcache +
- region files */
- if (fsiz < expected_siz)
+ "Cannot get file system info for (%s); file system corrupted?\n",
+ li->li_directory, 0, 0);
+ return 1;
+ } else {
+ /*
+ * If db_home_directory is set, and it's not the same as the db_directory,
+ * then check the disk space.
+ */
+ if(li->li_dblayer_private->dblayer_dbhome_directory &&
+ strcmp(li->li_dblayer_private->dblayer_dbhome_directory,"")
&&
+ strcmp(li->li_directory,
li->li_dblayer_private->dblayer_dbhome_directory))
{
- LDAPDebug(LDAP_DEBUG_ANY,
- "No enough space left on device (%lu bytes); "
- "at least %lu bytes space is needed for db region files\n",
- fsiz, expected_siz, 0);
- rval = 1;
+ /* Calculate the available space as long as we are not using shared memory
*/
+ if(!using_shared_mem){
+ if(statvfs(li->li_dblayer_private->dblayer_dbhome_directory,
&dbhome_buf) < 0){
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "Cannot get file system info for (%s); file system
corrupted?\n",
+ li->li_dblayer_private->dblayer_dbhome_directory, 0, 0);
+ return 1;
+ }
+ fsiz = ((PRUint64)dbhome_buf.f_bavail) * ((PRUint64)dbhome_buf.f_bsize);
+ region_dir = li->li_dblayer_private->dblayer_dbhome_directory;
+ } else {
+ /* Shared memory. No need to check disk space, return success */
+ return 0;
+ }
+ } else {
+ /* Ok, just check the db directory */
+ region_dir = li->li_directory;
+ fsiz = ((PRUint64)db_buf.f_bavail) * ((PRUint64)db_buf.f_bsize);
}
- }
-#endif
-#if defined( linux )
- struct statfs fsbuf;
- if (statfs(li->li_directory, &fsbuf) < 0)
- {
- LDAPDebug(LDAP_DEBUG_ANY,
- "Cannot get file system info; file system corrupted?\n", 0, 0, 0);
- rval = 1;
- }
- else
- {
- double fsiz = ((double)fsbuf.f_bavail) * fsbuf.f_bsize;
- double expected_siz = ((double)li->li_dbcachesize) * 1.5; /* dbcache +
- region files */
- if (fsiz < expected_siz)
- {
+ /* Adjust the size for the region files */
+ fsiz += dblayer_get_region_size(region_dir);
+
+ /* Check if we have enough space */
+ if (fsiz < expected_siz){
LDAPDebug(LDAP_DEBUG_ANY,
- "No enough space left on device (%lu bytes); "
+ "No enough space left on device (%s) (%lu bytes); "
"at least %lu bytes space is needed for db region files\n",
- fsiz, expected_siz, 0);
- rval = 1;
+ region_dir, fsiz, expected_siz);
+ return 1;
}
+
+ return 0;
}
-#endif
- return rval;
}
/*
@@ -1629,7 +1655,7 @@ dblayer_start(struct ldbminfo *li, int dbmode)
}
/* check if there's enough disk space to start */
- if (no_diskspace(li))
+ if (no_diskspace(li, open_flags))
{
return ENOSPC;
}
@@ -6946,8 +6972,6 @@ dblayer_strerror(int error)
}
/* [605974] check a db region file's existence to know whether import is executed by
other process or not */
-#define DB_REGION_PREFIX "__db."
-
int
dblayer_in_import(ldbm_instance *inst)
{
@@ -7249,9 +7273,6 @@ ldbm_back_ctrl_info(Slapi_Backend *be, int cmd, void *info)
return rc;
}
-#include <prthread.h>
-#include <prclist.h>
-
static PRUintn thread_private_txn_stack;
typedef struct dblayer_txn_stack {