|
|
6b9042 |
From c5e89132f2ee017aa026f7b8009a2976b627fa3a Mon Sep 17 00:00:00 2001
|
|
|
6b9042 |
From: Thierry Bordaz <tbordaz@redhat.com>
|
|
|
6b9042 |
Date: Tue, 26 Apr 2016 13:00:44 +0300
|
|
|
6b9042 |
Subject: [PATCH 2/4] backend: support backend shutdown for priming thread
|
|
|
6b9042 |
cancellation
|
|
|
6b9042 |
|
|
|
6b9042 |
Launching a separate thread to populate map cache has a side effect that
|
|
|
6b9042 |
the thread could be scheduled to execute over a shutdown time. If LDAP server
|
|
|
6b9042 |
received the request to shutdown, we need to stop processing the
|
|
|
6b9042 |
original source and shut the priming thread.
|
|
|
6b9042 |
|
|
|
6b9042 |
Resolves: rhbz#1327197
|
|
|
6b9042 |
---
|
|
|
6b9042 |
src/back-shr.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++----------
|
|
|
6b9042 |
src/back-shr.h | 1 +
|
|
|
6b9042 |
src/backend.h | 1 +
|
|
|
6b9042 |
src/plugin.h | 3 ++
|
|
|
6b9042 |
4 files changed, 92 insertions(+), 17 deletions(-)
|
|
|
6b9042 |
|
|
|
6b9042 |
diff --git a/src/back-shr.c b/src/back-shr.c
|
|
|
6b9042 |
index 0157582..7842e05 100644
|
|
|
6b9042 |
--- a/src/back-shr.c
|
|
|
6b9042 |
+++ b/src/back-shr.c
|
|
|
6b9042 |
@@ -665,25 +665,34 @@ backend_shr_get_vattr_sdnlist(struct plugin_state *state,
|
|
|
6b9042 |
}
|
|
|
6b9042 |
|
|
|
6b9042 |
struct backend_shr_data_init_cbdata {
|
|
|
6b9042 |
- Slapi_PBlock *parent_pb;
|
|
|
6b9042 |
struct plugin_state *state;
|
|
|
6b9042 |
const char *filter;
|
|
|
6b9042 |
};
|
|
|
6b9042 |
|
|
|
6b9042 |
#define PLUGIN_SCAN_DELAY 5
|
|
|
6b9042 |
|
|
|
6b9042 |
-static void
|
|
|
6b9042 |
-backend_shr_data_initialize_thread_cb(void *arg)
|
|
|
6b9042 |
+static void *
|
|
|
6b9042 |
+backend_shr_data_initialize_thread_cb(struct wrapped_thread *t)
|
|
|
6b9042 |
{
|
|
|
6b9042 |
- struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg;
|
|
|
6b9042 |
+ struct backend_shr_data_init_cbdata *cbdata = wrap_thread_arg(t);
|
|
|
6b9042 |
Slapi_PBlock *pb = NULL;
|
|
|
6b9042 |
struct backend_set_config_entry_add_cbdata set_cbdata;
|
|
|
6b9042 |
int result = 0, i = 0;
|
|
|
6b9042 |
Slapi_Entry **entries = NULL;
|
|
|
6b9042 |
struct plugin_state *state = NULL;
|
|
|
6b9042 |
|
|
|
6b9042 |
+ /* We have to be cautious here as the thread can be executed after
|
|
|
6b9042 |
+ * the plugin received a shutdown request, thus a number of checks here. */
|
|
|
6b9042 |
+ if (slapi_is_shutting_down()) {
|
|
|
6b9042 |
+ return NULL;
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
+
|
|
|
6b9042 |
if (cbdata == NULL) {
|
|
|
6b9042 |
- return;
|
|
|
6b9042 |
+ return NULL;
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
+
|
|
|
6b9042 |
+ if ((cbdata->state == NULL) || (cbdata->state->plugin_base == NULL)) {
|
|
|
6b9042 |
+ return NULL;
|
|
|
6b9042 |
}
|
|
|
6b9042 |
|
|
|
6b9042 |
state = cbdata->state;
|
|
|
6b9042 |
@@ -694,13 +703,23 @@ backend_shr_data_initialize_thread_cb(void *arg)
|
|
|
6b9042 |
* so we just wait some time. */
|
|
|
6b9042 |
DS_Sleep(PR_SecondsToInterval(PLUGIN_SCAN_DELAY));
|
|
|
6b9042 |
|
|
|
6b9042 |
- backend_update_params(cbdata->parent_pb, state);
|
|
|
6b9042 |
+ if (slapi_is_shutting_down()) {
|
|
|
6b9042 |
+ return NULL;
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
+
|
|
|
6b9042 |
+ if (state->plugin_base == NULL) {
|
|
|
6b9042 |
+ return NULL;
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
+
|
|
|
6b9042 |
+ pb = wrap_pblock_new(NULL);
|
|
|
6b9042 |
+ backend_update_params(pb, state);
|
|
|
6b9042 |
+ slapi_pblock_destroy(pb);
|
|
|
6b9042 |
|
|
|
6b9042 |
slapi_log_error(SLAPI_LOG_PLUGIN,
|
|
|
6b9042 |
state->plugin_desc->spd_id,
|
|
|
6b9042 |
"searching under \"%s\" for configuration\n",
|
|
|
6b9042 |
state->plugin_base);
|
|
|
6b9042 |
- pb = wrap_pblock_new(cbdata->parent_pb);
|
|
|
6b9042 |
+ pb = wrap_pblock_new(NULL);
|
|
|
6b9042 |
slapi_search_internal_set_pb(pb,
|
|
|
6b9042 |
state->plugin_base,
|
|
|
6b9042 |
LDAP_SCOPE_ONELEVEL,
|
|
|
6b9042 |
@@ -717,10 +736,10 @@ backend_shr_data_initialize_thread_cb(void *arg)
|
|
|
6b9042 |
/* Do a search and collect found entries to avoid locking the backends */
|
|
|
6b9042 |
if (slapi_search_internal_pb(pb) == 0) {
|
|
|
6b9042 |
if (map_wrlock() != 0) {
|
|
|
6b9042 |
- slapi_log_error(SLAPI_LOG_PLUGIN,
|
|
|
6b9042 |
+ slapi_log_error(SLAPI_LOG_FATAL,
|
|
|
6b9042 |
state->plugin_desc->spd_id,
|
|
|
6b9042 |
"failed to search under \"%s\" for "
|
|
|
6b9042 |
- "configuration: failed to acquire a lock\n",
|
|
|
6b9042 |
+ "configuration: failed to acquire a write lock to a map\n",
|
|
|
6b9042 |
state->plugin_base);
|
|
|
6b9042 |
goto done_with_lock;
|
|
|
6b9042 |
}
|
|
|
6b9042 |
@@ -728,6 +747,11 @@ backend_shr_data_initialize_thread_cb(void *arg)
|
|
|
6b9042 |
if (result == 0) {
|
|
|
6b9042 |
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
|
|
6b9042 |
for (i = 0; entries[i] != NULL; i++) {
|
|
|
6b9042 |
+ /* We may be scheduled to run over shutdown time, exit early */
|
|
|
6b9042 |
+ if (slapi_is_shutting_down()) {
|
|
|
6b9042 |
+ map_unlock();
|
|
|
6b9042 |
+ goto done_with_lock;
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
backend_set_config_entry_add_cb(entries[i], &set_cbdata);
|
|
|
6b9042 |
}
|
|
|
6b9042 |
}
|
|
|
6b9042 |
@@ -746,6 +770,7 @@ done_with_lock:
|
|
|
6b9042 |
}
|
|
|
6b9042 |
|
|
|
6b9042 |
PR_AtomicSet(&state->ready_to_serve, 1);
|
|
|
6b9042 |
+ return NULL;
|
|
|
6b9042 |
}
|
|
|
6b9042 |
|
|
|
6b9042 |
static void
|
|
|
6b9042 |
@@ -754,11 +779,28 @@ backend_shr_data_initialize_thread(time_t when, void *arg)
|
|
|
6b9042 |
struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg;
|
|
|
6b9042 |
PRThread *thread = NULL;
|
|
|
6b9042 |
|
|
|
6b9042 |
- /* start data import as a separate thread */
|
|
|
6b9042 |
- thread = PR_CreateThread(PR_USER_THREAD, backend_shr_data_initialize_thread_cb,
|
|
|
6b9042 |
- (void *)arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
|
|
6b9042 |
- PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
|
|
|
6b9042 |
- if (thread == NULL) {
|
|
|
6b9042 |
+ if (slapi_is_shutting_down()) {
|
|
|
6b9042 |
+ return;
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
+
|
|
|
6b9042 |
+ if (cbdata->state->priming_mutex == NULL) {
|
|
|
6b9042 |
+ /* This mutex is allocated at plugin startup
|
|
|
6b9042 |
+ * Without this mutex we can not enforce that shutdown wait for priming completion
|
|
|
6b9042 |
+ * This is better to skip the priming
|
|
|
6b9042 |
+ */
|
|
|
6b9042 |
+ slapi_log_error(SLAPI_LOG_FATAL, cbdata->state->plugin_desc->spd_id, "priming_mutex not initialized. Priming fails\n");
|
|
|
6b9042 |
+ return;
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
+ wrap_mutex_lock(cbdata->state->priming_mutex);
|
|
|
6b9042 |
+
|
|
|
6b9042 |
+ if (!cbdata->state->start_priming_thread) {
|
|
|
6b9042 |
+ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata->state->plugin_desc->spd_id,
|
|
|
6b9042 |
+ "Likely a shutdown occurred before we started \n");
|
|
|
6b9042 |
+ goto done;
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
+
|
|
|
6b9042 |
+ cbdata->state->priming_tid = wrap_start_thread(&backend_shr_data_initialize_thread_cb, arg);
|
|
|
6b9042 |
+ if (cbdata->state->priming_tid == NULL) {
|
|
|
6b9042 |
slapi_log_error(SLAPI_LOG_FATAL,
|
|
|
6b9042 |
cbdata->state->plugin_desc->spd_id,
|
|
|
6b9042 |
"unable to create compatibility tree scan thread!\n");
|
|
|
6b9042 |
@@ -769,6 +811,8 @@ backend_shr_data_initialize_thread(time_t when, void *arg)
|
|
|
6b9042 |
cbdata->state->plugin_desc->spd_id, PLUGIN_SCAN_DELAY);
|
|
|
6b9042 |
}
|
|
|
6b9042 |
|
|
|
6b9042 |
+done:
|
|
|
6b9042 |
+ wrap_mutex_unlock(cbdata->state->priming_mutex);
|
|
|
6b9042 |
}
|
|
|
6b9042 |
|
|
|
6b9042 |
/* Scan for the list of configured groups and sets. */
|
|
|
6b9042 |
@@ -779,6 +823,14 @@ backend_shr_startup(struct plugin_state *state,
|
|
|
6b9042 |
{
|
|
|
6b9042 |
struct backend_shr_data_init_cbdata *cbdata = NULL;
|
|
|
6b9042 |
|
|
|
6b9042 |
+ if (slapi_is_shutting_down()) {
|
|
|
6b9042 |
+ slapi_log_error(SLAPI_LOG_FATAL,
|
|
|
6b9042 |
+ state->plugin_desc->spd_id,
|
|
|
6b9042 |
+ "task for populating compatibility tree will "
|
|
|
6b9042 |
+ "not be created due to upcoming server shutdown\n");
|
|
|
6b9042 |
+ return;
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
+
|
|
|
6b9042 |
cbdata = (struct backend_shr_data_init_cbdata *)
|
|
|
6b9042 |
slapi_ch_malloc(sizeof(struct backend_shr_data_init_cbdata));
|
|
|
6b9042 |
|
|
|
6b9042 |
@@ -792,10 +844,10 @@ backend_shr_startup(struct plugin_state *state,
|
|
|
6b9042 |
|
|
|
6b9042 |
PR_AtomicSet(&state->ready_to_serve, 0);
|
|
|
6b9042 |
cbdata->state = state;
|
|
|
6b9042 |
- cbdata->parent_pb = parent_pb;
|
|
|
6b9042 |
cbdata->filter = filter;
|
|
|
6b9042 |
|
|
|
6b9042 |
- /* Schedule running a callback that will create a thread */
|
|
|
6b9042 |
+ /* Schedule running a callback that will create a thread
|
|
|
6b9042 |
+ * but make sure it is called a first thing when event loop is created */
|
|
|
6b9042 |
slapi_eq_once(backend_shr_data_initialize_thread,
|
|
|
6b9042 |
cbdata, PR_SecondsToInterval(PLUGIN_SCAN_DELAY));
|
|
|
6b9042 |
|
|
|
6b9042 |
@@ -808,6 +860,24 @@ backend_shr_startup(struct plugin_state *state,
|
|
|
6b9042 |
|
|
|
6b9042 |
}
|
|
|
6b9042 |
|
|
|
6b9042 |
+void
|
|
|
6b9042 |
+backend_shr_shutdown(struct plugin_state *state)
|
|
|
6b9042 |
+{
|
|
|
6b9042 |
+ /* Make sure the priming thread is stopped or will not start
|
|
|
6b9042 |
+ * Note: priming_mutex will not be freed because the priming thread
|
|
|
6b9042 |
+ * may access it independently of the server/plugin shutdown
|
|
|
6b9042 |
+ */
|
|
|
6b9042 |
+ wrap_mutex_lock(state->priming_mutex);
|
|
|
6b9042 |
+ state->start_priming_thread = 0; /* prevent spawing of priming thread */
|
|
|
6b9042 |
+ if (state->priming_tid == NULL) {
|
|
|
6b9042 |
+ /* priming thread has not yet started or failed to start */
|
|
|
6b9042 |
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
|
|
|
6b9042 |
+ "At shutdown, priming thread not yet started or failed to start\n");
|
|
|
6b9042 |
+ } else {
|
|
|
6b9042 |
+ wrap_stop_thread(state->priming_tid);
|
|
|
6b9042 |
+ }
|
|
|
6b9042 |
+ wrap_mutex_unlock(state->priming_mutex);
|
|
|
6b9042 |
+}
|
|
|
6b9042 |
/* Process a set configuration directory entry. Pull out the group and set
|
|
|
6b9042 |
* names which are specified in the entry and delete each in turn. */
|
|
|
6b9042 |
int
|
|
|
6b9042 |
@@ -2336,7 +2406,7 @@ backend_shr_modify_cb(Slapi_PBlock *pb)
|
|
|
6b9042 |
backend_set_config_entry_add_cb(cbdata.e_post, &set_cbdata);
|
|
|
6b9042 |
}
|
|
|
6b9042 |
/* Lastly, if the entry is our own entry, re-read parameters. */
|
|
|
6b9042 |
- sdn = slapi_sdn_new_dn_byref(cbdata.state->plugin_base);
|
|
|
6b9042 |
+ sdn = slapi_sdn_new_dn_byval(cbdata.state->plugin_base);
|
|
|
6b9042 |
if (sdn != NULL) {
|
|
|
6b9042 |
if ((strcmp(slapi_entry_get_ndn(cbdata.e_pre),
|
|
|
6b9042 |
slapi_sdn_get_ndn(sdn)) == 0) ||
|
|
|
6b9042 |
diff --git a/src/back-shr.h b/src/back-shr.h
|
|
|
6b9042 |
index 44c25fe..2caea5d 100644
|
|
|
6b9042 |
--- a/src/back-shr.h
|
|
|
6b9042 |
+++ b/src/back-shr.h
|
|
|
6b9042 |
@@ -39,6 +39,7 @@ void backend_shr_free_sdnlist(const Slapi_DN **sdnlist);
|
|
|
6b9042 |
|
|
|
6b9042 |
void backend_shr_startup(struct plugin_state *state,
|
|
|
6b9042 |
Slapi_PBlock *pb, const char *set_filter);
|
|
|
6b9042 |
+void backend_shr_shutdown(struct plugin_state *state);
|
|
|
6b9042 |
int backend_shr_betxn_postop_init(Slapi_PBlock *pb,
|
|
|
6b9042 |
struct plugin_state *state);
|
|
|
6b9042 |
int backend_shr_postop_init(Slapi_PBlock *pb, struct plugin_state *state);
|
|
|
6b9042 |
diff --git a/src/backend.h b/src/backend.h
|
|
|
6b9042 |
index 7974aae..4608d2d 100644
|
|
|
6b9042 |
--- a/src/backend.h
|
|
|
6b9042 |
+++ b/src/backend.h
|
|
|
6b9042 |
@@ -58,6 +58,7 @@ struct backend_shr_set_data {
|
|
|
6b9042 |
|
|
|
6b9042 |
/* Startup/initialization functions called through the map. */
|
|
|
6b9042 |
void backend_startup(struct slapi_pblock *pb, struct plugin_state *state);
|
|
|
6b9042 |
+void backend_shutdown(struct plugin_state *state);
|
|
|
6b9042 |
int backend_init_preop(struct slapi_pblock *pb, struct plugin_state *state);
|
|
|
6b9042 |
int backend_init_betxn_preop(struct slapi_pblock *pb,
|
|
|
6b9042 |
struct plugin_state *state);
|
|
|
6b9042 |
diff --git a/src/plugin.h b/src/plugin.h
|
|
|
6b9042 |
index 7a89ac7..56d672f 100644
|
|
|
6b9042 |
--- a/src/plugin.h
|
|
|
6b9042 |
+++ b/src/plugin.h
|
|
|
6b9042 |
@@ -34,6 +34,9 @@ struct plugin_state {
|
|
|
6b9042 |
Slapi_PluginDesc *plugin_desc;
|
|
|
6b9042 |
unsigned int use_be_txns: 1;
|
|
|
6b9042 |
PRInt32 ready_to_serve;
|
|
|
6b9042 |
+ struct wrapped_mutex *priming_mutex;
|
|
|
6b9042 |
+ unsigned int start_priming_thread: 1; /* flag to allow spawning of the priming thread */
|
|
|
6b9042 |
+ struct wrapped_thread *priming_tid; /* priming thread pid. use to join */
|
|
|
6b9042 |
|
|
|
6b9042 |
/* NIS-specific data. */
|
|
|
6b9042 |
struct wrapped_thread *tid;
|
|
|
6b9042 |
--
|
|
|
6b9042 |
2.7.4
|
|
|
6b9042 |
|