>From 3de5f97d65cb425b721370d5e699a9aa88fe37aa Mon Sep 17 00:00:00 2001
From: "Thierry bordaz (tbordaz)" <tbordaz@redhat.com>
Date: Wed, 6 Feb 2013 20:52:58 +0100
Subject: [PATCH] Ticket 564 - Ticket description

Bug Description:

	This bug is that under write operation transaction, both changelog and DB RUV are written back to disk.
	This is a consequence of bug fix 543633. Although the write back of the DB RUV brings a little overhead
	it is not strictly required. In fact since 633168, changelog RUV is in sync with the data store. So
	changelog RUV and DB RUV have the same values.

Fix Description:

	If the database RUV (on disk) is let behind the real state of data store, in case of crash
	it needs to be resynchronize with the real state. To do this we use the changelog RUV (in sync
	with the data store) to rebuild the database RUV.

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

Reviewed by: ?

Platforms tested: fedora 17

Flag Day: no

Doc impact: no
---
 ldap/servers/plugins/replication/repl5_replica.c | 73 ++++++++++++++----------
 ldap/servers/plugins/replication/repl5_ruv.c     | 31 ++++++++++
 ldap/servers/plugins/replication/repl5_ruv.h     |  1 +
 ldap/servers/slapd/back-ldbm/dblayer.c           |  1 +
 ldap/servers/slapd/back-ldbm/ldbm_add.c          | 44 +-------------
 ldap/servers/slapd/back-ldbm/ldbm_delete.c       | 43 --------------
 ldap/servers/slapd/back-ldbm/ldbm_modify.c       | 48 +---------------
 ldap/servers/slapd/back-ldbm/ldbm_modrdn.c       | 47 ---------------
 ldap/servers/slapd/plugin.c                      | 11 ++++
 ldap/servers/slapd/slapi-plugin.h                |  2 +
 10 files changed, 93 insertions(+), 208 deletions(-)

diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index 6d8b660..ef3bc4c 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -1492,41 +1492,56 @@ int replica_check_for_data_reload (Replica *r, void *arg)
 			 * sessions.
 			 */
 
-            rc = ruv_compare_ruv(upper_bound_ruv, "changelog max RUV", r_ruv, "database RUV", 0, SLAPI_LOG_FATAL);
-            if (RUV_COMP_IS_FATAL(rc))
-            {
-                /* create a temporary replica object to conform to the interface */
-                r_obj = object_new (r, NULL);
-
-                /* We can't use existing changelog - remove existing file */
+            if (slapi_disordely_shutdown(PR_FALSE)) {
                 slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_check_for_data_reload: "
-                    "Warning: data for replica %s does not match the data in the changelog. "
-                    "Recreating the changelog file. "
-                    "This could affect replication with replica's consumers in which case the "
-                    "consumers should be reinitialized.\n",
+                    "Warning: disordely shutdown for replica %s. Check if DB RUV needs to be updated\n",
                     slapi_sdn_get_dn(r->repl_root));
+                
+                if (ruv_covers_ruv(upper_bound_ruv, r_ruv) && !ruv_covers_ruv(r_ruv, upper_bound_ruv)) {
+                    /*
+                     * The Changelog RUV is ahead of the RUV in the DB.
+                     * RUV DB was likely not flushed on disk.
+                     */
+
+                    ruv_force_csn_update_from_ruv(upper_bound_ruv, r_ruv, 
+                            "Force update of database RUV (from CL RUV) -> ", SLAPI_LOG_FATAL);
+                    replica_set_ruv_dirty(r);
+                }
+                
+            } else {
 
-                rc = cl5DeleteDBSync (r_obj);
+                rc = ruv_compare_ruv(upper_bound_ruv, "changelog max RUV", r_ruv, "database RUV", 0, SLAPI_LOG_FATAL);
+                if (RUV_COMP_IS_FATAL(rc)) {
+                    /* create a temporary replica object to conform to the interface */
+                    r_obj = object_new(r, NULL);
 
-                object_release (r_obj);
+                    /* We can't use existing changelog - remove existing file */
+                    slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_check_for_data_reload: "
+                            "Warning: data for replica %s does not match the data in the changelog. "
+                            "Recreating the changelog file. "
+                            "This could affect replication with replica's consumers in which case the "
+                            "consumers should be reinitialized.\n",
+                            slapi_sdn_get_dn(r->repl_root));
 
-                if (rc == CL5_SUCCESS)
-                {
-                    /* log changes to mark starting point for replication */
-                    rc = replica_log_ruv_elements (r);
+                    rc = cl5DeleteDBSync(r_obj);
+
+                    object_release(r_obj);
+
+                    if (rc == CL5_SUCCESS) {
+                        /* log changes to mark starting point for replication */
+                        rc = replica_log_ruv_elements(r);
+                    }
+                } else if (rc) {
+                    slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_check_for_data_reload: "
+                            "Warning: for replica %s there were some differences between the changelog max RUV and the "
+                            "database RUV.  If there are obsolete elements in the database RUV, you "
+                            "should remove them using the CLEANALLRUV task.  If they are not obsolete, "
+                            "you should check their status to see why there are no changes from those "
+                            "servers in the changelog.\n",
+                            slapi_sdn_get_dn(r->repl_root));
+                    rc = 0;
                 }
-            }
-            else if (rc)
-            {
-                slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_check_for_data_reload: "
-                    "Warning: for replica %s there were some differences between the changelog max RUV and the "
-                    "database RUV.  If there are obsolete elements in the database RUV, you "
-                    "should remove them using the CLEANALLRUV task.  If they are not obsolete, "
-                    "you should check their status to see why there are no changes from those "
-                    "servers in the changelog.\n",
-                    slapi_sdn_get_dn(r->repl_root));
-                rc = 0;
-            }
+            } // slapi_disordely_shutdown
 
             object_release (ruv_obj);
         }
diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c
index 9ce9768..e952cf8 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.c
+++ b/ldap/servers/plugins/replication/repl5_ruv.c
@@ -2147,6 +2147,37 @@ ruv_is_newer (Object *sruvobj, Object *cruvobj)
 	return is_newer;
 }
 
+/*
+ * This routine is called after a disordely shutdown
+ * The Database RUV was found late compare to the changelog RUV
+ */
+void
+ruv_force_csn_update_from_ruv(RUV *src_ruv, RUV *tgt_ruv, char *msg, int logLevel) {
+    RUVElement *replica = NULL;
+    char csnStr [CSN_STRSIZE];
+    int cookie;
+
+    slapi_rwlock_rdlock(src_ruv->lock);
+    
+    for (replica = dl_get_first(src_ruv->elements, &cookie);
+            NULL != replica;
+            replica = dl_get_next(src_ruv->elements, &cookie)) {
+        /* 
+         * In case the DB RUV (tgt_ruv) is behind the CL RUV (src_ruv)
+         * updates the DB RUV.
+         */
+        if (!ruv_covers_csn(tgt_ruv, replica->csn)) {
+            ruv_force_csn_update(tgt_ruv, replica->csn);
+            csn_as_string(replica->csn, PR_FALSE, csnStr);
+            slapi_log_error(logLevel, repl_plugin_name, "%s %s\n",
+                    msg, csnStr);
+        }
+    }
+
+    slapi_rwlock_unlock(src_ruv->lock);
+    
+}
+
 void
 ruv_force_csn_update (RUV *ruv, CSN *csn)
 {
diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h
index 036951f..7c6ad4a 100644
--- a/ldap/servers/plugins/replication/repl5_ruv.h
+++ b/ldap/servers/plugins/replication/repl5_ruv.h
@@ -142,6 +142,7 @@ int ruv_local_contains_supplier(RUV *ruv, ReplicaId rid);
 PRBool ruv_has_csns(const RUV *ruv);
 PRBool ruv_has_both_csns(const RUV *ruv);
 PRBool ruv_is_newer (Object *sruv, Object *cruv);
+void ruv_force_csn_update_from_ruv(RUV *src_ruv, RUV *tgt_ruv, char *msg, int logLevel);
 void ruv_force_csn_update (RUV *ruv, CSN *csn);
 void ruv_insert_dummy_min_csn (RUV *ruv);
 int ruv_compare_ruv(const RUV *ruv1, const char *ruv1name, const RUV *ruv2, const char *ruv2name, int strict, int loglevel);
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 5e53de9..b952ee8 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -1562,6 +1562,7 @@ dblayer_start(struct ldbminfo *li, int dbmode)
                 LDAPDebug(LDAP_DEBUG_ANY, "Detected Disorderly Shutdown last "
                           "time Directory Server was running, recovering "
                           "database.\n", 0, 0, 0);
+                slapi_disordely_shutdown(PR_TRUE);
             }
         }
         switch  (dbmode&DBLAYER_RESTORE_MASK) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index eab2ae1..99cd698 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -99,9 +99,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 	int	retry_count = 0;
 	int	disk_full = 0;
 	modify_context parent_modify_c = {0};
-	modify_context ruv_c = {0};
 	int parent_found = 0;
-	int ruv_c_init = 0;
 	int rc = 0;
 	int addingentry_id_assigned= 0;
 	int addingentry_in_cache= 0;
@@ -758,19 +756,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 				parent_found = 1;
 				parententry = NULL;
 			}
-		
-			if (!is_ruv && !is_fixup_operation) {
-				ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
-				if (-1 == ruv_c_init) {
-					LDAPDebug( LDAP_DEBUG_ANY,
-						"ldbm_back_add: ldbm_txn_ruv_modify_context "
-						"failed to construct RUV modify context\n",
-						0, 0, 0);
-					ldap_result_code= LDAP_OPERATIONS_ERROR;
-					retval = 0;
-					goto error_return;
-				}
-			}
+
 		
 			if ( (originalentry = backentry_dup(addingentry )) == NULL ) {
 				ldap_result_code= LDAP_OPERATIONS_ERROR;
@@ -952,23 +938,6 @@ ldbm_back_add( Slapi_PBlock *pb )
 			}
 		}
 
-		if (ruv_c_init) {
-			retval = modify_update_all( be, pb, &ruv_c, &txn );
-			if (DB_LOCK_DEADLOCK == retval) {
-				/* Abort and re-try */
-				continue;
-			}
-			if (0 != retval) {
-				LDAPDebug( LDAP_DEBUG_ANY,
-					"modify_update_all failed, err=%d %s\n", retval,
-					(msg = dblayer_strerror( retval )) ? msg : "", 0 );
-				if (LDBM_OS_ERR_IS_DISKFULL(retval))
-					disk_full = 1;
-				ldap_result_code= LDAP_OPERATIONS_ERROR;
-				goto error_return;
-			}
-		}
-
 		if (retval == 0) {
 			break;
 		}
@@ -1013,14 +982,6 @@ ldbm_back_add( Slapi_PBlock *pb )
 		modify_switch_entries( &parent_modify_c,be);
 	}
 
-	if (ruv_c_init) {
-		if (modify_switch_entries(&ruv_c, be) != 0 ) {
-			ldap_result_code= LDAP_OPERATIONS_ERROR;
-			LDAPDebug( LDAP_DEBUG_ANY,
-				"ldbm_back_add: modify_switch_entries failed\n", 0, 0, 0);
-			goto error_return;
-		}
-	}
 
 	/* call the transaction post add plugins just before the commit */
 	if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_ADD_FN))) {
@@ -1168,9 +1129,6 @@ common_return:
 	slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
 	/* JCMREPL - The bepostop is called even if the operation fails. */
 	plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_ADD_FN);
-	if (ruv_c_init) {
-		modify_term(&ruv_c, be);
-	}
 	modify_term(&parent_modify_c,be);
 	done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_DN_ENTRY);
 	done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_UNIQUEID_ENTRY);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 6efa03e..1b5e0ff 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -70,9 +70,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
 	int retry_count = 0;
 	int disk_full = 0;
 	int parent_found = 0;
-	int ruv_c_init = 0;
 	modify_context parent_modify_c = {0};
-	modify_context ruv_c = {0};
 	int rc = 0;
 	int ldap_result_code= LDAP_SUCCESS;
 	char *ldap_result_message= NULL;
@@ -551,18 +549,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
 				}
 			}
 
-			if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
-				ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
-				if (-1 == ruv_c_init) {
-					LDAPDebug( LDAP_DEBUG_ANY,
-						"ldbm_back_delete: ldbm_txn_ruv_modify_context "
-						"failed to construct RUV modify context\n",
-						0, 0, 0);
-					ldap_result_code= LDAP_OPERATIONS_ERROR;
-					retval = 0;
-					goto error_return;
-				}
-			}
 		} /* if (0 == retry_count) just once */
 		else {
 			/* call the transaction pre delete plugins not just once
@@ -1028,22 +1014,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
 			}
 		}
 
-		if (ruv_c_init) {
-			retval = modify_update_all( be, pb, &ruv_c, &txn );
-			if (DB_LOCK_DEADLOCK == retval) {
-				/* Abort and re-try */
-				continue;
-			}
-			if (0 != retval) {
-				LDAPDebug( LDAP_DEBUG_ANY,
-					"modify_update_all failed, err=%d %s\n", retval,
-					(msg = dblayer_strerror( retval )) ? msg : "", 0 );
-				if (LDBM_OS_ERR_IS_DISKFULL(retval))
-					disk_full = 1;
-				ldap_result_code= LDAP_OPERATIONS_ERROR;
-				goto error_return;
-			}
-		}
 
 		if (retval == 0 ) {
 			break;
@@ -1109,15 +1079,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
 		modify_switch_entries( &parent_modify_c,be);
 	}
 	
-	if (ruv_c_init) {
-		if (modify_switch_entries(&ruv_c, be) != 0 ) {
-			ldap_result_code= LDAP_OPERATIONS_ERROR;
-			LDAPDebug( LDAP_DEBUG_ANY,
-				"ldbm_back_delete: modify_switch_entries failed\n", 0, 0, 0);
-			retval = -1;
-			goto error_return;
-		}
-	}
 
 	rc= 0;
 	goto common_return;
@@ -1224,10 +1185,6 @@ common_return:
 			slapi_counter_decrement(inst->inst_ref_count);
 		}
 	}
-	
-	if (ruv_c_init) {
-		modify_term(&ruv_c, be);
-	}
 
 diskfull_return:
 	if(ldap_result_code!=-1) {
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index 1e728da..df3925b 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -321,8 +321,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
 	Slapi_Mods smods = {0};
 	back_txn txn;
 	back_txnid		parent_txn;
-	modify_context		ruv_c = {0};
-	int			ruv_c_init = 0;
 	int			retval = -1;
 	char			*msg;
 	char			*errbuf = NULL;
@@ -542,20 +540,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
 										  &ldap_result_code, &ldap_result_message)) {
 				goto error_return;
 			}
-		
-			if (!is_ruv && !is_fixup_operation) {
-				ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
-				if (-1 == ruv_c_init) {
-					LDAPDebug( LDAP_DEBUG_ANY,
-						"ldbm_back_modify: ldbm_txn_ruv_modify_context "
-						"failed to construct RUV modify context\n",
-						0, 0, 0);
-					ldap_result_code= LDAP_OPERATIONS_ERROR;
-					retval = 0;
-					goto error_return;
-				}
-			}
-		
+                        
 			/*
 			 * Grab a copy of the mods and the entry in case the be_txn_preop changes
 			 * the them.  If we have a failure, then we need to reset the mods to their
@@ -662,23 +647,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
 
 		}
 
-		if (ruv_c_init) {
-			retval = modify_update_all( be, pb, &ruv_c, &txn );
-			if (DB_LOCK_DEADLOCK == retval) {
-				/* Abort and re-try */
-				continue;
-			}
-			if (0 != retval) {
-				LDAPDebug( LDAP_DEBUG_ANY,
-					"modify_update_all failed, err=%d %s\n", retval,
-					(msg = dblayer_strerror( retval )) ? msg : "", 0 );
-				if (LDBM_OS_ERR_IS_DISKFULL(retval))
-					disk_full = 1;
-				ldap_result_code= LDAP_OPERATIONS_ERROR;
-				goto error_return;
-			}
-		}
-
 		if (0 == retval) {
 			break;
 		}
@@ -688,16 +656,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
 	   	ldap_result_code= LDAP_BUSY;
 		goto error_return;
 	}
-
-	if (ruv_c_init) {
-		if (modify_switch_entries(&ruv_c, be) != 0 ) {
-			ldap_result_code= LDAP_OPERATIONS_ERROR;
-			LDAPDebug( LDAP_DEBUG_ANY,
-				"ldbm_back_modify: modify_switch_entries failed\n", 0, 0, 0);
-			goto error_return;
-		}
-	}
-	
+		
 	if (cache_replace( &inst->inst_cache, e, ec ) != 0 ) {
 		MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
 		goto error_return;
@@ -852,9 +811,6 @@ common_return:
 	if (!disk_full)
 		plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN);
 
-	if (ruv_c_init) {
-		modify_term(&ruv_c, be);
-	}
 
 	if(ldap_result_code!=-1)
 	{
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index 80bf2f4..9a632f7 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -87,9 +87,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
     struct backentry *original_newparent = NULL;
     modify_context parent_modify_context = {0};
     modify_context newparent_modify_context = {0};
-    modify_context ruv_c = {0};
-    int ruv_c_init = 0;
-    int is_ruv = 0;
     IDList *children= NULL;
     struct backentry **child_entries = NULL;
     struct backdn **child_dns = NULL;
@@ -134,7 +131,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
     slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
     slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
     slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation );
-    is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
     is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
 
     if (NULL == sdn) {
@@ -839,18 +835,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
                 /* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */
             }
         
-            if (!is_ruv && !is_fixup_operation) {
-                ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
-                if (-1 == ruv_c_init) {
-                    LDAPDebug( LDAP_DEBUG_ANY,
-                        "ldbm_back_modrdn: ldbm_txn_ruv_modify_context "
-                        "failed to construct RUV modify context\n",
-                        0, 0, 0);
-                    ldap_result_code = LDAP_OPERATIONS_ERROR;
-                    retval = 0;
-                    goto error_return;
-                }
-            }
         
             /*
              * make copies of the originals, no need to copy the mods because
@@ -1058,24 +1042,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
             goto error_return;
         }
 
-        if (ruv_c_init) {
-            retval = modify_update_all( be, pb, &ruv_c, &txn );
-            if (DB_LOCK_DEADLOCK == retval) {
-                /* Abort and re-try */
-                continue;
-            }
-            if (0 != retval) {
-                LDAPDebug( LDAP_DEBUG_ANY,
-                    "modify_update_all failed, err=%d %s\n", retval,
-                    (msg = dblayer_strerror( retval )) ? msg : "", 0 );
-                if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
-                    disk_full = 1;
-                }
-                ldap_result_code= LDAP_OPERATIONS_ERROR;
-                goto error_return;
-            }
-        }
-
         break; /* retval==0, Done, Terminate the loop */
     }
     if (retry_count == RETRY_TIMES)
@@ -1166,15 +1132,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
         }
     }
 
-    if (ruv_c_init) {
-        if (modify_switch_entries(&ruv_c, be) != 0 ) {
-            ldap_result_code= LDAP_OPERATIONS_ERROR;
-            LDAPDebug( LDAP_DEBUG_ANY,
-                "ldbm_back_modrdn: modify_switch_entries failed\n", 0, 0, 0);
-            goto error_return;
-        }
-    }
-
     retval= 0;
     goto common_return;
 
@@ -1319,10 +1276,6 @@ common_return:
 
     moddn_unlock_and_return_entry(be,&e);
 
-    if (ruv_c_init) {
-        modify_term(&ruv_c, be);
-    }
-
     if (ldap_result_code!=-1)
     {
 		if (not_an_error) {
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index f90bd0d..d66e7a2 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -3214,3 +3214,14 @@ slapi_set_plugin_open_rootdn_bind(Slapi_PBlock *pb){
 
 	ptd_set_special_data(&(config->plgc_bind_subtrees), PLGC_DATA_BIND_ROOT);
 }
+
+PRBool
+slapi_disordely_shutdown(PRBool set)
+{
+    static PRBool is_disordely_shutdown = PR_FALSE;
+    
+    if (set) {
+        is_disordely_shutdown = PR_TRUE;
+    }
+    return (is_disordely_shutdown);
+}
\ No newline at end of file
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 73ae477..d8ff5f4 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -7258,6 +7258,8 @@ uint64_t slapi_str_to_u64(const char *s);
 
 void slapi_set_plugin_open_rootdn_bind(Slapi_PBlock *pb);
 
+PRBool slapi_disordely_shutdown(PRBool set);
+
 /* 
  * Public entry extension getter/setter functions
  *
-- 
1.7.11.7

