ldap/servers/slapd/back-ldbm/dbhelp.c | 53 +++++++++++++++
ldap/servers/slapd/back-ldbm/dblayer.c | 110 ++++++++++++++++-----------------
ldap/servers/slapd/back-ldbm/dblayer.h | 2
3 files changed, 106 insertions(+), 59 deletions(-)
New commits:
commit b43145218dccc8c9c16ecadad80f94bf58c73d57
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Sep 27 17:58:03 2013 -0700
Ticket #47463 - IDL-style can become mismatched during partial restoration
Description by telackey:
When doing a partial/FRI restoration the database files are copied
key-by-key. This is necessary to reset the LSNs so the restored
files can merge into the existing DB environment (cf. dblayer_copy_
file_resetlsns()) in a recoverable way.
However, dblayer_copy_file_keybykey() does not set the comparison
function before calling DB->put(), which means that the restored
files will not necessarily be using the proper function.
While all the keys are technically present, indexed searches can
still fail to return relevant results because the key order is
significant when intersecting the results with the other indices.
Note: The bug was reported and the patch was provided by telackey.
(Thank you, Thomas!)
Additional fix by nhosoi:
The entryrdn index uses its special dup compare function. The dup
compare function is set when the restoring index file is entryrdn.
https://fedorahosted.org/389/ticket/47463
Reviewed by rmeggins (Thank you, Rich!)
diff --git a/ldap/servers/slapd/back-ldbm/dbhelp.c
b/ldap/servers/slapd/back-ldbm/dbhelp.c
index 1165831..29c0247 100644
--- a/ldap/servers/slapd/back-ldbm/dbhelp.c
+++ b/ldap/servers/slapd/back-ldbm/dbhelp.c
@@ -49,7 +49,13 @@
#include "back-ldbm.h"
#include "dblayer.h"
-static int dblayer_copy_file_keybykey(DB_ENV *env, char *source_file_name, char
*destination_file_name, int overwrite, dblayer_private *priv)
+static int
+dblayer_copy_file_keybykey(DB_ENV *env,
+ char *source_file_name,
+ char *destination_file_name,
+ int overwrite,
+ dblayer_private *priv,
+ ldbm_instance *inst)
{
int retval = 0;
int retval_cleanup = 0;
@@ -62,6 +68,7 @@ static int dblayer_copy_file_keybykey(DB_ENV *env, char
*source_file_name, char
int cursor_flag = 0;
int finished = 0;
int mode = 0;
+ char *p = NULL;
LDAPDebug( LDAP_DEBUG_TRACE, "=> dblayer_copy_file_keybykey\n", 0, 0, 0 );
@@ -119,6 +126,40 @@ static int dblayer_copy_file_keybykey(DB_ENV *env, char
*source_file_name, char
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_keybykey, set_pagesize error %d:
%s\n", retval, db_strerror(retval), 0);
goto error;
}
+
+ /* TEL 20130412: Make sure to set the dup comparison function if needed.
+ * We key our decision off of the presence of new IDL and dup flags on
+ * the source database. This is similar dblayer_open_file, except that
+ * we don't have the attribute info index mask for VLV. That should be OK
+ * since the DB_DUP and DB_DUPSORT flags wouldn't have been toggled on
+ * unless they passed the check on the source.
+ */
+ /* Entryrdn index has its own dup compare function */
+ if ((p = PL_strcasestr(source_file_name, LDBM_ENTRYRDN_STR)) &&
+ (*(p + sizeof(LDBM_ENTRYRDN_STR) - 1) == '.')) {
+ /* entryrdn.db */
+ struct attrinfo *ai = NULL;
+ ainfo_get(inst->inst_be, LDBM_ENTRYRDN_STR, &ai);
+ if (ai->ai_dup_cmp_fn) {
+ /* If set, use the special dup compare callback */
+ retval = destination_file->set_dup_compare(destination_file,
ai->ai_dup_cmp_fn);
+ if (retval) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "dblayer_copy_file_keybykey(entryrdn), set_dup_compare error %d:
%s\n",
+ retval, db_strerror(retval));
+ goto error;
+ }
+ }
+ } else if (idl_get_idl_new() && (dbflags & DB_DUP) && (dbflags &
DB_DUPSORT)) {
+ retval = destination_file->set_dup_compare(destination_file, idl_new_compare_dups);
+ if (retval) {
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
+ "dblayer_copy_file_keybykey, set_dup_compare error %d:
%s\n",
+ retval, db_strerror(retval));
+ goto error;
+ }
+ }
+
retval = (destination_file->open)(destination_file, NULL, destination_file_name,
NULL, dbtype, DB_CREATE | DB_EXCL, mode);
if (retval) {
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_keybykey, Open error %d: %s\n",
retval, db_strerror(retval), 0);
@@ -190,7 +231,13 @@ error:
return retval;
}
-int dblayer_copy_file_resetlsns(char *home_dir ,char *source_file_name, char
*destination_file_name, int overwrite, dblayer_private *priv)
+int
+dblayer_copy_file_resetlsns(char *home_dir,
+ char *source_file_name,
+ char *destination_file_name,
+ int overwrite,
+ dblayer_private *priv,
+ ldbm_instance *inst)
{
int retval = 0;
DB_ENV *env = NULL;
@@ -205,7 +252,7 @@ int dblayer_copy_file_resetlsns(char *home_dir ,char
*source_file_name, char *de
goto out;
}
/* Do the copy */
- retval = dblayer_copy_file_keybykey(env, source_file_name, destination_file_name,
overwrite, priv);
+ retval = dblayer_copy_file_keybykey(env, source_file_name, destination_file_name,
overwrite, priv, inst);
if (retval) {
LDAPDebug(LDAP_DEBUG_ANY, "dblayer_copy_file_resetlsns: Copy not completed
successfully.", 0, 0, 0);
}
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c
b/ldap/servers/slapd/back-ldbm/dblayer.c
index 013d1c0..4102d3c 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -3617,17 +3617,17 @@ dblayer_txn_begin_ext(struct ldbminfo *li, back_txnid parent_txn,
back_txn *txn,
{
/* this txn is now our current transaction for current operations
and new parent for any nested transactions created */
- if (use_lock && log_flush_thread) {
- int txn_id = new_txn.back_txn_txn->id(new_txn.back_txn_txn);
- PR_Lock(sync_txn_log_flush);
- txn_in_progress_count++;
- LDAPDebug(LDAP_DEBUG_BACKLDBM, "txn_begin: batchcount: %d, txn_in_progress:
%d, curr_txn: %x\n", trans_batch_count, txn_in_progress_count, txn_id);
- PR_Unlock(sync_txn_log_flush);
- }
- dblayer_push_pvt_txn(&new_txn);
- if (txn) {
- txn->back_txn_txn = new_txn.back_txn_txn;
- }
+ if (use_lock && log_flush_thread) {
+ int txn_id = new_txn.back_txn_txn->id(new_txn.back_txn_txn);
+ PR_Lock(sync_txn_log_flush);
+ txn_in_progress_count++;
+ LDAPDebug(LDAP_DEBUG_BACKLDBM, "txn_begin: batchcount: %d,
txn_in_progress: %d, curr_txn: %x\n", trans_batch_count, txn_in_progress_count,
txn_id);
+ PR_Unlock(sync_txn_log_flush);
+ }
+ dblayer_push_pvt_txn(&new_txn);
+ if (txn) {
+ txn->back_txn_txn = new_txn.back_txn_txn;
+ }
}
} else
{
@@ -3655,16 +3655,16 @@ dblayer_txn_begin(backend *be, back_txnid parent_txn, back_txn
*txn)
struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
int rc = 0;
if (DBLOCK_INSIDE_TXN(li)) {
- rc = dblayer_txn_begin_ext(li,parent_txn,txn,PR_TRUE);
- if (!rc && SERIALLOCK(li)) {
+ rc = dblayer_txn_begin_ext(li,parent_txn,txn,PR_TRUE);
+ if (!rc && SERIALLOCK(li)) {
dblayer_lock_backend(be);
- }
+ }
} else {
- if (SERIALLOCK(li)) {
+ if (SERIALLOCK(li)) {
dblayer_lock_backend(be);
- }
- rc = dblayer_txn_begin_ext(li,parent_txn,txn,PR_TRUE);
- if (rc && SERIALLOCK(li)) {
+ }
+ rc = dblayer_txn_begin_ext(li,parent_txn,txn,PR_TRUE);
+ if (rc && SERIALLOCK(li)) {
dblayer_unlock_backend(be);
}
}
@@ -3678,8 +3678,8 @@ int dblayer_txn_commit_ext(struct ldbminfo *li, back_txn *txn,
PRBool use_lock)
dblayer_private *priv = NULL;
DB_TXN *db_txn = NULL;
back_txn *cur_txn = NULL;
- int txn_id = 0;
- int txn_batch_slot = 0;
+ int txn_id = 0;
+ int txn_batch_slot = 0;
PR_ASSERT(NULL != li);
@@ -3783,15 +3783,15 @@ dblayer_txn_commit(backend *be, back_txn *txn)
struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
int rc;
if (DBLOCK_INSIDE_TXN(li)) {
- if (SERIALLOCK(li)) {
- dblayer_unlock_backend(be);
+ if (SERIALLOCK(li)) {
+ dblayer_unlock_backend(be);
}
- rc = dblayer_txn_commit_ext(li,txn,PR_TRUE);
+ rc = dblayer_txn_commit_ext(li,txn,PR_TRUE);
} else {
- rc = dblayer_txn_commit_ext(li,txn,PR_TRUE);
- if (SERIALLOCK(li)) {
+ rc = dblayer_txn_commit_ext(li,txn,PR_TRUE);
+ if (SERIALLOCK(li)) {
dblayer_unlock_backend(be);
- }
+ }
}
return rc;
}
@@ -3823,13 +3823,13 @@ int dblayer_txn_abort_ext(struct ldbminfo *li, back_txn *txn,
PRBool use_lock)
priv->dblayer_env &&
priv->dblayer_enable_transactions)
{
- int txn_id = db_txn->id(db_txn);
- if ( use_lock && log_flush_thread) {
- PR_Lock(sync_txn_log_flush);
- txn_in_progress_count--;
- PR_Unlock(sync_txn_log_flush);
- LDAPDebug(LDAP_DEBUG_BACKLDBM, "txn_abort : batchcount: %d, txn_in_progress:
%d, curr_txn: %x\n", trans_batch_count, txn_in_progress_count, txn_id);
- }
+ int txn_id = db_txn->id(db_txn);
+ if ( use_lock && log_flush_thread) {
+ PR_Lock(sync_txn_log_flush);
+ txn_in_progress_count--;
+ PR_Unlock(sync_txn_log_flush);
+ LDAPDebug(LDAP_DEBUG_BACKLDBM, "txn_abort : batchcount: %d,
txn_in_progress: %d, curr_txn: %x\n", trans_batch_count, txn_in_progress_count,
txn_id);
+ }
return_value = TXN_ABORT(db_txn);
/* if we were given a transaction, and it is the same as the
current transaction in progress, pop it off the stack
@@ -3874,14 +3874,14 @@ dblayer_txn_abort(backend *be, back_txn *txn)
int rc;
if (DBLOCK_INSIDE_TXN(li)) {
if (SERIALLOCK(li)) {
- dblayer_unlock_backend(be);
- }
- rc = dblayer_txn_abort_ext(li, txn, PR_TRUE);
+ dblayer_unlock_backend(be);
+ }
+ rc = dblayer_txn_abort_ext(li, txn, PR_TRUE);
} else {
- rc = dblayer_txn_abort_ext(li, txn, PR_TRUE);
+ rc = dblayer_txn_abort_ext(li, txn, PR_TRUE);
if (SERIALLOCK(li)) {
- dblayer_unlock_backend(be);
- }
+ dblayer_unlock_backend(be);
+ }
}
return rc;
}
@@ -4567,9 +4567,9 @@ static int log_flush_threadmain(void *param)
interval_flush = PR_MillisecondsToInterval(trans_batch_txn_min_sleep);
interval_wait = PR_MillisecondsToInterval(trans_batch_txn_max_sleep);
interval_def = PR_MillisecondsToInterval(300); /*used while no txn or txn batching
*/
- /* LK this is only needed if online change of
- * of txn config is supported ???
- */
+ /* LK this is only needed if online change of
+ * of txn config is supported ???
+ */
while ((!priv->dblayer_stop_threads) && (log_flush_thread)){
if (priv->dblayer_enable_transactions){
if (trans_batch_limit > 0) {
@@ -5932,6 +5932,7 @@ dblayer_copy_directory(struct ldbminfo *li,
char inst_dir[MAXPATHLEN];
char sep;
int suffix_len = 0;
+ ldbm_instance *inst = NULL;
if (!src_dir || '\0' == *src_dir)
{
@@ -5955,6 +5956,14 @@ dblayer_copy_directory(struct ldbminfo *li,
else
relative_instance_name++;
+ inst = ldbm_instance_find_by_name(li, relative_instance_name);
+ if (NULL == inst) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not exist;
"
+ "Instance path %s could be invalid.\n",
+ relative_instance_name, src_dir, 0);
+ return return_value;
+ }
+
if (is_fullpath(src_dir))
{
new_src_dir = src_dir;
@@ -5962,15 +5971,6 @@ dblayer_copy_directory(struct ldbminfo *li,
else
{
int len;
- ldbm_instance *inst =
- ldbm_instance_find_by_name(li, relative_instance_name);
- if (NULL == inst)
- {
- LDAPDebug(LDAP_DEBUG_ANY, "Backend instance \"%s\" does not
exist; "
- "Instance path %s could be invalid.\n",
- relative_instance_name, src_dir, 0);
- return return_value;
- }
inst_dirp = dblayer_get_full_inst_dir(inst->inst_li, inst,
inst_dir, MAXPATHLEN);
@@ -6090,13 +6090,12 @@ dblayer_copy_directory(struct ldbminfo *li,
/* If the file is a database file, and resetlsns is set, then we need to do a
key by key copy */
/* PL_strcmp takes NULL arg */
if (resetlsns &&
- (PL_strcmp(LDBM_FILENAME_SUFFIX, strrchr(filename1, '.'))
- == 0)) {
+ (PL_strcmp(LDBM_FILENAME_SUFFIX, strrchr(filename1, '.')) == 0))
{
return_value = dblayer_copy_file_resetlsns(src_dir, filename1,
filename2,
- 0, priv);
+ 0, priv, inst);
} else {
return_value = dblayer_copyfile(filename1, filename2,
- 0, priv->dblayer_file_mode);
+ 0, priv->dblayer_file_mode);
}
slapi_ch_free((void**)&filename1);
slapi_ch_free((void**)&filename2);
@@ -6819,6 +6818,7 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task
*task, char *
PR_Lock(li->li_config_mutex);
/* dblayer_home_directory is freed in dblayer_post_close.
* li_directory needs to live beyond dblayer. */
+ slapi_ch_free_string(&priv->dblayer_home_directory);
priv->dblayer_home_directory = slapi_ch_strdup(li->li_directory);
priv->dblayer_cachesize = li->li_dbcachesize;
priv->dblayer_ncache = li->li_dbncache;
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.h
b/ldap/servers/slapd/back-ldbm/dblayer.h
index c382a98..e1a178e 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.h
+++ b/ldap/servers/slapd/back-ldbm/dblayer.h
@@ -202,7 +202,7 @@ int dblayer_make_private_simple_env(char *db_home_dir, DB_ENV **env);
/* Copy a database file, preserving all its contents (used to reset the LSNs in the file
in order to move
* it from one transacted environment to another.
*/
-int dblayer_copy_file_resetlsns(char *home_dir, char *source_file_name, char
*destination_file_name, int overwrite, dblayer_private *priv);
+int dblayer_copy_file_resetlsns(char *home_dir, char *source_file_name, char
*destination_file_name, int overwrite, dblayer_private *priv, ldbm_instance *inst);
/* Turn on the various logging and debug options for DB */
void dblayer_set_env_debugging(DB_ENV *pEnv, dblayer_private *priv);