|
|
3280a9 |
From 5bca57b52069508a55b36fafe3729b7d1243743b Mon Sep 17 00:00:00 2001
|
|
|
3280a9 |
From: tbordaz <tbordaz@redhat.com>
|
|
|
3280a9 |
Date: Wed, 27 Jan 2021 11:58:38 +0100
|
|
|
3280a9 |
Subject: [PATCH 2/3] Issue 4526 - sync_repl: when completing an operation in
|
|
|
3280a9 |
the pending list, it can select the wrong operation (#4553)
|
|
|
3280a9 |
|
|
|
3280a9 |
Bug description:
|
|
|
3280a9 |
When an operation complete, it was retrieved in the pending list with
|
|
|
3280a9 |
the address of the Operation structure. In case of POST OP nested operations
|
|
|
3280a9 |
the same address can be reused. So when completing an operation there could be
|
|
|
3280a9 |
a confusion which operation actually completed.
|
|
|
3280a9 |
A second problem is that if an update its DB_DEADLOCK, the BETXN_PREOP can
|
|
|
3280a9 |
be called several times. During retry, the operation is already in the pending
|
|
|
3280a9 |
list.
|
|
|
3280a9 |
|
|
|
3280a9 |
Fix description:
|
|
|
3280a9 |
The fix defines a new operation extension (sync_persist_extension_type).
|
|
|
3280a9 |
This operation extension contains an index (idx_pl) of the op_pl in the
|
|
|
3280a9 |
the pending list.
|
|
|
3280a9 |
|
|
|
3280a9 |
And additional safety fix is to dump the pending list in case it becomes large (>10).
|
|
|
3280a9 |
The pending list is dumped with SLAPI_LOG_PLUGIN.
|
|
|
3280a9 |
|
|
|
3280a9 |
When there is a retry (operation extension exists) the call to sync_update_persist_betxn_pre_op
|
|
|
3280a9 |
becomes a NOOP: the operation is not added again in the pending list.
|
|
|
3280a9 |
|
|
|
3280a9 |
relates: https://github.com/389ds/389-ds-base/issues/4526
|
|
|
3280a9 |
|
|
|
3280a9 |
Reviewed by: William Brown (Thanks !!)
|
|
|
3280a9 |
---
|
|
|
3280a9 |
ldap/servers/plugins/sync/sync.h | 9 ++
|
|
|
3280a9 |
ldap/servers/plugins/sync/sync_init.c | 64 +++++++-
|
|
|
3280a9 |
ldap/servers/plugins/sync/sync_persist.c | 194 ++++++++++++++++-------
|
|
|
3280a9 |
3 files changed, 208 insertions(+), 59 deletions(-)
|
|
|
3280a9 |
|
|
|
3280a9 |
diff --git a/ldap/servers/plugins/sync/sync.h b/ldap/servers/plugins/sync/sync.h
|
|
|
3280a9 |
index 7241fddbf..2fdf24476 100644
|
|
|
3280a9 |
--- a/ldap/servers/plugins/sync/sync.h
|
|
|
3280a9 |
+++ b/ldap/servers/plugins/sync/sync.h
|
|
|
3280a9 |
@@ -82,6 +82,12 @@ typedef enum _pl_flags {
|
|
|
3280a9 |
OPERATION_PL_IGNORED = 5
|
|
|
3280a9 |
} pl_flags_t;
|
|
|
3280a9 |
|
|
|
3280a9 |
+typedef struct op_ext_ident
|
|
|
3280a9 |
+{
|
|
|
3280a9 |
+ uint32_t idx_pl; /* To uniquely identify an operation in PL, the operation extension
|
|
|
3280a9 |
+ * contains the index of that operation in the pending list
|
|
|
3280a9 |
+ */
|
|
|
3280a9 |
+} op_ext_ident_t;
|
|
|
3280a9 |
/* Pending list operations.
|
|
|
3280a9 |
* it contains a list ('next') of nested operations. The
|
|
|
3280a9 |
* order the same order that the server applied the operation
|
|
|
3280a9 |
@@ -90,6 +96,7 @@ typedef enum _pl_flags {
|
|
|
3280a9 |
typedef struct OPERATION_PL_CTX
|
|
|
3280a9 |
{
|
|
|
3280a9 |
Operation *op; /* Pending operation, should not be freed as it belongs to the pblock */
|
|
|
3280a9 |
+ uint32_t idx_pl; /* index of the operation in the pending list */
|
|
|
3280a9 |
pl_flags_t flags; /* operation is completed (set to TRUE in POST) */
|
|
|
3280a9 |
Slapi_Entry *entry; /* entry to be store in the enqueued node. 1st arg sync_queue_change */
|
|
|
3280a9 |
Slapi_Entry *eprev; /* pre-entry to be stored in the enqueued node. 2nd arg sync_queue_change */
|
|
|
3280a9 |
@@ -99,6 +106,8 @@ typedef struct OPERATION_PL_CTX
|
|
|
3280a9 |
|
|
|
3280a9 |
OPERATION_PL_CTX_T * get_thread_primary_op(void);
|
|
|
3280a9 |
void set_thread_primary_op(OPERATION_PL_CTX_T *op);
|
|
|
3280a9 |
+const op_ext_ident_t * sync_persist_get_operation_extension(Slapi_PBlock *pb);
|
|
|
3280a9 |
+void sync_persist_set_operation_extension(Slapi_PBlock *pb, op_ext_ident_t *op_ident);
|
|
|
3280a9 |
|
|
|
3280a9 |
int sync_register_operation_extension(void);
|
|
|
3280a9 |
int sync_unregister_operation_entension(void);
|
|
|
3280a9 |
diff --git a/ldap/servers/plugins/sync/sync_init.c b/ldap/servers/plugins/sync/sync_init.c
|
|
|
3280a9 |
index 74af14512..9e6a12000 100644
|
|
|
3280a9 |
--- a/ldap/servers/plugins/sync/sync_init.c
|
|
|
3280a9 |
+++ b/ldap/servers/plugins/sync/sync_init.c
|
|
|
3280a9 |
@@ -16,6 +16,7 @@ static int sync_preop_init(Slapi_PBlock *pb);
|
|
|
3280a9 |
static int sync_postop_init(Slapi_PBlock *pb);
|
|
|
3280a9 |
static int sync_be_postop_init(Slapi_PBlock *pb);
|
|
|
3280a9 |
static int sync_betxn_preop_init(Slapi_PBlock *pb);
|
|
|
3280a9 |
+static int sync_persist_register_operation_extension(void);
|
|
|
3280a9 |
|
|
|
3280a9 |
static PRUintn thread_primary_op;
|
|
|
3280a9 |
|
|
|
3280a9 |
@@ -43,7 +44,8 @@ sync_init(Slapi_PBlock *pb)
|
|
|
3280a9 |
slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
|
|
|
3280a9 |
(void *)sync_close) != 0 ||
|
|
|
3280a9 |
slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
|
|
|
3280a9 |
- (void *)&pdesc) != 0) {
|
|
|
3280a9 |
+ (void *)&pdesc) != 0 ||
|
|
|
3280a9 |
+ sync_persist_register_operation_extension()) {
|
|
|
3280a9 |
slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
|
|
|
3280a9 |
"sync_init - Failed to register plugin\n");
|
|
|
3280a9 |
rc = 1;
|
|
|
3280a9 |
@@ -242,4 +244,64 @@ set_thread_primary_op(OPERATION_PL_CTX_T *op)
|
|
|
3280a9 |
PR_SetThreadPrivate(thread_primary_op, (void *) head);
|
|
|
3280a9 |
}
|
|
|
3280a9 |
head->next = op;
|
|
|
3280a9 |
+}
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+/* The following definitions are used for the operation pending list
|
|
|
3280a9 |
+ * (used by sync_repl). To retrieve a specific operation in the pending
|
|
|
3280a9 |
+ * list, the operation extension contains the index of the operation in
|
|
|
3280a9 |
+ * the pending list
|
|
|
3280a9 |
+ */
|
|
|
3280a9 |
+static int sync_persist_extension_type; /* initialized in sync_persist_register_operation_extension */
|
|
|
3280a9 |
+static int sync_persist_extension_handle; /* initialized in sync_persist_register_operation_extension */
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+const op_ext_ident_t *
|
|
|
3280a9 |
+sync_persist_get_operation_extension(Slapi_PBlock *pb)
|
|
|
3280a9 |
+{
|
|
|
3280a9 |
+ Slapi_Operation *op;
|
|
|
3280a9 |
+ op_ext_ident_t *ident;
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
|
|
|
3280a9 |
+ ident = slapi_get_object_extension(sync_persist_extension_type, op,
|
|
|
3280a9 |
+ sync_persist_extension_handle);
|
|
|
3280a9 |
+ slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "sync_persist_get_operation_extension operation (op=0x%lx) -> %d\n",
|
|
|
3280a9 |
+ (ulong) op, ident ? ident->idx_pl : -1);
|
|
|
3280a9 |
+ return (const op_ext_ident_t *) ident;
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+}
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+void
|
|
|
3280a9 |
+sync_persist_set_operation_extension(Slapi_PBlock *pb, op_ext_ident_t *op_ident)
|
|
|
3280a9 |
+{
|
|
|
3280a9 |
+ Slapi_Operation *op;
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
|
|
|
3280a9 |
+ slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "sync_persist_set_operation_extension operation (op=0x%lx) -> %d\n",
|
|
|
3280a9 |
+ (ulong) op, op_ident ? op_ident->idx_pl : -1);
|
|
|
3280a9 |
+ slapi_set_object_extension(sync_persist_extension_type, op,
|
|
|
3280a9 |
+ sync_persist_extension_handle, (void *)op_ident);
|
|
|
3280a9 |
+}
|
|
|
3280a9 |
+/* operation extension constructor */
|
|
|
3280a9 |
+static void *
|
|
|
3280a9 |
+sync_persist_operation_extension_constructor(void *object __attribute__((unused)), void *parent __attribute__((unused)))
|
|
|
3280a9 |
+{
|
|
|
3280a9 |
+ /* we only set the extension value explicitly in sync_update_persist_betxn_pre_op */
|
|
|
3280a9 |
+ return NULL; /* we don't set anything in the ctor */
|
|
|
3280a9 |
+}
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+/* consumer operation extension destructor */
|
|
|
3280a9 |
+static void
|
|
|
3280a9 |
+sync_persist_operation_extension_destructor(void *ext, void *object __attribute__((unused)), void *parent __attribute__((unused)))
|
|
|
3280a9 |
+{
|
|
|
3280a9 |
+ op_ext_ident_t *op_ident = (op_ext_ident_t *)ext;
|
|
|
3280a9 |
+ slapi_ch_free((void **)&op_ident);
|
|
|
3280a9 |
+}
|
|
|
3280a9 |
+static int
|
|
|
3280a9 |
+sync_persist_register_operation_extension(void)
|
|
|
3280a9 |
+{
|
|
|
3280a9 |
+ return slapi_register_object_extension(SYNC_PLUGIN_SUBSYSTEM,
|
|
|
3280a9 |
+ SLAPI_EXT_OPERATION,
|
|
|
3280a9 |
+ sync_persist_operation_extension_constructor,
|
|
|
3280a9 |
+ sync_persist_operation_extension_destructor,
|
|
|
3280a9 |
+ &sync_persist_extension_type,
|
|
|
3280a9 |
+ &sync_persist_extension_handle);
|
|
|
3280a9 |
}
|
|
|
3280a9 |
\ No newline at end of file
|
|
|
3280a9 |
diff --git a/ldap/servers/plugins/sync/sync_persist.c b/ldap/servers/plugins/sync/sync_persist.c
|
|
|
3280a9 |
index d13f142b0..e93a8fa83 100644
|
|
|
3280a9 |
--- a/ldap/servers/plugins/sync/sync_persist.c
|
|
|
3280a9 |
+++ b/ldap/servers/plugins/sync/sync_persist.c
|
|
|
3280a9 |
@@ -47,6 +47,9 @@ static int sync_release_connection(Slapi_PBlock *pb, Slapi_Connection *conn, Sla
|
|
|
3280a9 |
* per thread pending list of nested operation..
|
|
|
3280a9 |
* being a betxn_preop the pending list has the same order
|
|
|
3280a9 |
* that the server received the operation
|
|
|
3280a9 |
+ *
|
|
|
3280a9 |
+ * In case of DB_RETRY, this callback can be called several times
|
|
|
3280a9 |
+ * The detection of the DB_RETRY is done via the operation extension
|
|
|
3280a9 |
*/
|
|
|
3280a9 |
int
|
|
|
3280a9 |
sync_update_persist_betxn_pre_op(Slapi_PBlock *pb)
|
|
|
3280a9 |
@@ -54,64 +57,128 @@ sync_update_persist_betxn_pre_op(Slapi_PBlock *pb)
|
|
|
3280a9 |
OPERATION_PL_CTX_T *prim_op;
|
|
|
3280a9 |
OPERATION_PL_CTX_T *new_op;
|
|
|
3280a9 |
Slapi_DN *sdn;
|
|
|
3280a9 |
+ uint32_t idx_pl = 0;
|
|
|
3280a9 |
+ op_ext_ident_t *op_ident;
|
|
|
3280a9 |
+ Operation *op;
|
|
|
3280a9 |
|
|
|
3280a9 |
if (!SYNC_IS_INITIALIZED()) {
|
|
|
3280a9 |
/* not initialized if sync plugin is not started */
|
|
|
3280a9 |
return 0;
|
|
|
3280a9 |
}
|
|
|
3280a9 |
|
|
|
3280a9 |
+ prim_op = get_thread_primary_op();
|
|
|
3280a9 |
+ op_ident = sync_persist_get_operation_extension(pb);
|
|
|
3280a9 |
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
|
|
|
3280a9 |
+ slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn;;
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ /* Check if we are in a DB retry case */
|
|
|
3280a9 |
+ if (op_ident && prim_op) {
|
|
|
3280a9 |
+ OPERATION_PL_CTX_T *current_op;
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ /* This callback is called (with the same operation) because of a DB_RETRY */
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ /* It already existed (in the operation extension) an index of the operation in the pending list */
|
|
|
3280a9 |
+ for (idx_pl = 0, current_op = prim_op; current_op->next; idx_pl++, current_op = current_op->next) {
|
|
|
3280a9 |
+ if (op_ident->idx_pl == idx_pl) {
|
|
|
3280a9 |
+ break;
|
|
|
3280a9 |
+ }
|
|
|
3280a9 |
+ }
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ /* The retrieved operation in the pending list is at the right
|
|
|
3280a9 |
+ * index and state. Just return making this callback a noop
|
|
|
3280a9 |
+ */
|
|
|
3280a9 |
+ PR_ASSERT(current_op);
|
|
|
3280a9 |
+ PR_ASSERT(current_op->op == op);
|
|
|
3280a9 |
+ PR_ASSERT(current_op->flags == OPERATION_PL_PENDING);
|
|
|
3280a9 |
+ slapi_log_err(SLAPI_LOG_WARNING, SYNC_PLUGIN_SUBSYSTEM, "sync_update_persist_betxn_pre_op - DB retried operation targets "
|
|
|
3280a9 |
+ "\"%s\" (op=0x%lx idx_pl=%d) => op not changed in PL\n",
|
|
|
3280a9 |
+ slapi_sdn_get_dn(sdn), (ulong) op, idx_pl);
|
|
|
3280a9 |
+ return 0;
|
|
|
3280a9 |
+ }
|
|
|
3280a9 |
+
|
|
|
3280a9 |
/* Create a new pending operation node */
|
|
|
3280a9 |
new_op = (OPERATION_PL_CTX_T *)slapi_ch_calloc(1, sizeof(OPERATION_PL_CTX_T));
|
|
|
3280a9 |
new_op->flags = OPERATION_PL_PENDING;
|
|
|
3280a9 |
- slapi_pblock_get(pb, SLAPI_OPERATION, &new_op->op);
|
|
|
3280a9 |
- slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn;;
|
|
|
3280a9 |
+ new_op->op = op;
|
|
|
3280a9 |
|
|
|
3280a9 |
- prim_op = get_thread_primary_op();
|
|
|
3280a9 |
if (prim_op) {
|
|
|
3280a9 |
/* It already exists a primary operation, so the current
|
|
|
3280a9 |
* operation is a nested one that we need to register at the end
|
|
|
3280a9 |
* of the pending nested operations
|
|
|
3280a9 |
+ * Also computes the idx_pl that will be the identifier (index) of the operation
|
|
|
3280a9 |
+ * in the pending list
|
|
|
3280a9 |
*/
|
|
|
3280a9 |
OPERATION_PL_CTX_T *current_op;
|
|
|
3280a9 |
- for (current_op = prim_op; current_op->next; current_op = current_op->next);
|
|
|
3280a9 |
+ for (idx_pl = 0, current_op = prim_op; current_op->next; idx_pl++, current_op = current_op->next);
|
|
|
3280a9 |
current_op->next = new_op;
|
|
|
3280a9 |
+ idx_pl++; /* idx_pl is currently the index of the last op
|
|
|
3280a9 |
+ * as we are adding a new op we need to increase that index
|
|
|
3280a9 |
+ */
|
|
|
3280a9 |
slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "sync_update_persist_betxn_pre_op - nested operation targets "
|
|
|
3280a9 |
- "\"%s\" (0x%lx)\n",
|
|
|
3280a9 |
- slapi_sdn_get_dn(sdn), (ulong) new_op->op);
|
|
|
3280a9 |
+ "\"%s\" (op=0x%lx idx_pl=%d)\n",
|
|
|
3280a9 |
+ slapi_sdn_get_dn(sdn), (ulong) new_op->op, idx_pl);
|
|
|
3280a9 |
} else {
|
|
|
3280a9 |
/* The current operation is the first/primary one in the txn
|
|
|
3280a9 |
* registers it directly in the thread private data (head)
|
|
|
3280a9 |
*/
|
|
|
3280a9 |
set_thread_primary_op(new_op);
|
|
|
3280a9 |
+ idx_pl = 0; /* as primary operation, its index in the pending list is 0 */
|
|
|
3280a9 |
slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "sync_update_persist_betxn_pre_op - primary operation targets "
|
|
|
3280a9 |
"\"%s\" (0x%lx)\n",
|
|
|
3280a9 |
slapi_sdn_get_dn(sdn), (ulong) new_op->op);
|
|
|
3280a9 |
}
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ /* records, in the operation extension AND in the pending list, the identifier (index) of
|
|
|
3280a9 |
+ * this operation into the pending list
|
|
|
3280a9 |
+ */
|
|
|
3280a9 |
+ op_ident = (op_ext_ident_t *) slapi_ch_calloc(1, sizeof (op_ext_ident_t));
|
|
|
3280a9 |
+ op_ident->idx_pl = idx_pl;
|
|
|
3280a9 |
+ new_op->idx_pl = idx_pl;
|
|
|
3280a9 |
+ sync_persist_set_operation_extension(pb, op_ident);
|
|
|
3280a9 |
return 0;
|
|
|
3280a9 |
}
|
|
|
3280a9 |
|
|
|
3280a9 |
-/* This operation can not be proceed by sync_repl listener because
|
|
|
3280a9 |
- * of internal problem. For example, POST entry does not exist
|
|
|
3280a9 |
+/* This operation failed or skipped (e.g. no MODs).
|
|
|
3280a9 |
+ * In such case POST entry does not exist
|
|
|
3280a9 |
*/
|
|
|
3280a9 |
static void
|
|
|
3280a9 |
-ignore_op_pl(Operation *op)
|
|
|
3280a9 |
+ignore_op_pl(Slapi_PBlock *pb)
|
|
|
3280a9 |
{
|
|
|
3280a9 |
OPERATION_PL_CTX_T *prim_op, *curr_op;
|
|
|
3280a9 |
+ op_ext_ident_t *ident;
|
|
|
3280a9 |
+ Operation *op;
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ /* prim_op is set if betxn was called
|
|
|
3280a9 |
+ * In case of invalid update (schema violation) the
|
|
|
3280a9 |
+ * operation skip betxn and prim_op is not set.
|
|
|
3280a9 |
+ * This is the same for ident
|
|
|
3280a9 |
+ */
|
|
|
3280a9 |
prim_op = get_thread_primary_op();
|
|
|
3280a9 |
+ ident = sync_persist_get_operation_extension(pb);
|
|
|
3280a9 |
|
|
|
3280a9 |
- for (curr_op = prim_op; curr_op; curr_op = curr_op->next) {
|
|
|
3280a9 |
- if ((curr_op->op == op) &&
|
|
|
3280a9 |
- (curr_op->flags == OPERATION_PL_PENDING)) { /* If by any "chance" a same operation structure was reused in consecutive updates
|
|
|
3280a9 |
- * we can not only rely on 'op' value
|
|
|
3280a9 |
- */
|
|
|
3280a9 |
- slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM, "ignore_op_pl operation (0x%lx) from the pending list\n",
|
|
|
3280a9 |
- (ulong) op);
|
|
|
3280a9 |
- curr_op->flags = OPERATION_PL_IGNORED;
|
|
|
3280a9 |
- return;
|
|
|
3280a9 |
+ if (ident) {
|
|
|
3280a9 |
+ /* The TXN_BEPROP was called, so the operation is
|
|
|
3280a9 |
+ * registered in the pending list
|
|
|
3280a9 |
+ */
|
|
|
3280a9 |
+ for (curr_op = prim_op; curr_op; curr_op = curr_op->next) {
|
|
|
3280a9 |
+ if (curr_op->idx_pl == ident->idx_pl) {
|
|
|
3280a9 |
+ /* The operation extension (ident) refers this operation (currop in the pending list).
|
|
|
3280a9 |
+ * This is called during sync_repl postop. At this moment
|
|
|
3280a9 |
+ * the operation in the pending list (identified by idx_pl in the operation extension)
|
|
|
3280a9 |
+ * should be pending
|
|
|
3280a9 |
+ */
|
|
|
3280a9 |
+ PR_ASSERT(curr_op->flags == OPERATION_PL_PENDING);
|
|
|
3280a9 |
+ slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "ignore_op_pl operation (op=0x%lx, idx_pl=%d) from the pending list\n",
|
|
|
3280a9 |
+ (ulong) op, ident->idx_pl);
|
|
|
3280a9 |
+ curr_op->flags = OPERATION_PL_IGNORED;
|
|
|
3280a9 |
+ return;
|
|
|
3280a9 |
+ }
|
|
|
3280a9 |
}
|
|
|
3280a9 |
}
|
|
|
3280a9 |
- slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM, "ignore_op_pl can not retrieve an operation (0x%lx) in pending list\n",
|
|
|
3280a9 |
- (ulong) op);
|
|
|
3280a9 |
+ slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "ignore_op_pl failing operation (op=0x%lx, idx_pl=%d) was not in the pending list\n",
|
|
|
3280a9 |
+ (ulong) op, ident ? ident->idx_pl : -1);
|
|
|
3280a9 |
}
|
|
|
3280a9 |
|
|
|
3280a9 |
/* This is a generic function that is called by betxn_post of this plugin.
|
|
|
3280a9 |
@@ -126,7 +193,9 @@ sync_update_persist_op(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eprev, ber
|
|
|
3280a9 |
{
|
|
|
3280a9 |
OPERATION_PL_CTX_T *prim_op = NULL, *curr_op;
|
|
|
3280a9 |
Operation *pb_op;
|
|
|
3280a9 |
+ op_ext_ident_t *ident;
|
|
|
3280a9 |
Slapi_DN *sdn;
|
|
|
3280a9 |
+ uint32_t count; /* use for diagnostic of the lenght of the pending list */
|
|
|
3280a9 |
int32_t rc;
|
|
|
3280a9 |
|
|
|
3280a9 |
if (!SYNC_IS_INITIALIZED()) {
|
|
|
3280a9 |
@@ -138,7 +207,7 @@ sync_update_persist_op(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eprev, ber
|
|
|
3280a9 |
|
|
|
3280a9 |
if (NULL == e) {
|
|
|
3280a9 |
/* Ignore this operation (for example case of failure of the operation) */
|
|
|
3280a9 |
- ignore_op_pl(pb_op);
|
|
|
3280a9 |
+ ignore_op_pl(pb);
|
|
|
3280a9 |
return;
|
|
|
3280a9 |
}
|
|
|
3280a9 |
|
|
|
3280a9 |
@@ -161,16 +230,21 @@ sync_update_persist_op(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eprev, ber
|
|
|
3280a9 |
|
|
|
3280a9 |
|
|
|
3280a9 |
prim_op = get_thread_primary_op();
|
|
|
3280a9 |
+ ident = sync_persist_get_operation_extension(pb);
|
|
|
3280a9 |
PR_ASSERT(prim_op);
|
|
|
3280a9 |
+ PR_ASSERT(ident);
|
|
|
3280a9 |
/* First mark the operation as completed/failed
|
|
|
3280a9 |
* the param to be used once the operation will be pushed
|
|
|
3280a9 |
* on the listeners queue
|
|
|
3280a9 |
*/
|
|
|
3280a9 |
for (curr_op = prim_op; curr_op; curr_op = curr_op->next) {
|
|
|
3280a9 |
- if ((curr_op->op == pb_op) &&
|
|
|
3280a9 |
- (curr_op->flags == OPERATION_PL_PENDING)) { /* If by any "chance" a same operation structure was reused in consecutive updates
|
|
|
3280a9 |
- * we can not only rely on 'op' value
|
|
|
3280a9 |
- */
|
|
|
3280a9 |
+ if (curr_op->idx_pl == ident->idx_pl) {
|
|
|
3280a9 |
+ /* The operation extension (ident) refers this operation (currop in the pending list)
|
|
|
3280a9 |
+ * This is called during sync_repl postop. At this moment
|
|
|
3280a9 |
+ * the operation in the pending list (identified by idx_pl in the operation extension)
|
|
|
3280a9 |
+ * should be pending
|
|
|
3280a9 |
+ */
|
|
|
3280a9 |
+ PR_ASSERT(curr_op->flags == OPERATION_PL_PENDING);
|
|
|
3280a9 |
if (rc == LDAP_SUCCESS) {
|
|
|
3280a9 |
curr_op->flags = OPERATION_PL_SUCCEEDED;
|
|
|
3280a9 |
curr_op->entry = e ? slapi_entry_dup(e) : NULL;
|
|
|
3280a9 |
@@ -183,46 +257,50 @@ sync_update_persist_op(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eprev, ber
|
|
|
3280a9 |
}
|
|
|
3280a9 |
}
|
|
|
3280a9 |
if (!curr_op) {
|
|
|
3280a9 |
- slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM, "%s - operation not found on the pendling list\n", label);
|
|
|
3280a9 |
+ slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM, "%s - operation (op=0x%lx, idx_pl=%d) not found on the pendling list\n",
|
|
|
3280a9 |
+ label, (ulong) pb_op, ident->idx_pl);
|
|
|
3280a9 |
PR_ASSERT(curr_op);
|
|
|
3280a9 |
}
|
|
|
3280a9 |
|
|
|
3280a9 |
-#if DEBUG
|
|
|
3280a9 |
- /* dump the pending queue */
|
|
|
3280a9 |
- for (curr_op = prim_op; curr_op; curr_op = curr_op->next) {
|
|
|
3280a9 |
- char *flags_str;
|
|
|
3280a9 |
- char * entry_str;
|
|
|
3280a9 |
+ /* for diagnostic of the pending list, dump its content if it is too long */
|
|
|
3280a9 |
+ for (count = 0, curr_op = prim_op; curr_op; count++, curr_op = curr_op->next);
|
|
|
3280a9 |
+ if (loglevel_is_set(SLAPI_LOG_PLUGIN) && (count > 10)) {
|
|
|
3280a9 |
|
|
|
3280a9 |
- if (curr_op->entry) {
|
|
|
3280a9 |
- entry_str = slapi_entry_get_dn(curr_op->entry);
|
|
|
3280a9 |
- } else if (curr_op->eprev){
|
|
|
3280a9 |
- entry_str = slapi_entry_get_dn(curr_op->eprev);
|
|
|
3280a9 |
- } else {
|
|
|
3280a9 |
- entry_str = "unknown";
|
|
|
3280a9 |
- }
|
|
|
3280a9 |
- switch (curr_op->flags) {
|
|
|
3280a9 |
- case OPERATION_PL_SUCCEEDED:
|
|
|
3280a9 |
- flags_str = "succeeded";
|
|
|
3280a9 |
- break;
|
|
|
3280a9 |
- case OPERATION_PL_FAILED:
|
|
|
3280a9 |
- flags_str = "failed";
|
|
|
3280a9 |
- break;
|
|
|
3280a9 |
- case OPERATION_PL_IGNORED:
|
|
|
3280a9 |
- flags_str = "ignored";
|
|
|
3280a9 |
- break;
|
|
|
3280a9 |
- case OPERATION_PL_PENDING:
|
|
|
3280a9 |
- flags_str = "pending";
|
|
|
3280a9 |
- break;
|
|
|
3280a9 |
- default:
|
|
|
3280a9 |
- flags_str = "unknown";
|
|
|
3280a9 |
- break;
|
|
|
3280a9 |
-
|
|
|
3280a9 |
+ /* if pending list looks abnormally too long, dump the pending list */
|
|
|
3280a9 |
+ for (curr_op = prim_op; curr_op; curr_op = curr_op->next) {
|
|
|
3280a9 |
+ char *flags_str;
|
|
|
3280a9 |
+ char * entry_str;
|
|
|
3280a9 |
|
|
|
3280a9 |
- }
|
|
|
3280a9 |
- slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "dump pending list(0x%lx) %s %s\n",
|
|
|
3280a9 |
+ if (curr_op->entry) {
|
|
|
3280a9 |
+ entry_str = slapi_entry_get_dn(curr_op->entry);
|
|
|
3280a9 |
+ } else if (curr_op->eprev) {
|
|
|
3280a9 |
+ entry_str = slapi_entry_get_dn(curr_op->eprev);
|
|
|
3280a9 |
+ } else {
|
|
|
3280a9 |
+ entry_str = "unknown";
|
|
|
3280a9 |
+ }
|
|
|
3280a9 |
+ switch (curr_op->flags) {
|
|
|
3280a9 |
+ case OPERATION_PL_SUCCEEDED:
|
|
|
3280a9 |
+ flags_str = "succeeded";
|
|
|
3280a9 |
+ break;
|
|
|
3280a9 |
+ case OPERATION_PL_FAILED:
|
|
|
3280a9 |
+ flags_str = "failed";
|
|
|
3280a9 |
+ break;
|
|
|
3280a9 |
+ case OPERATION_PL_IGNORED:
|
|
|
3280a9 |
+ flags_str = "ignored";
|
|
|
3280a9 |
+ break;
|
|
|
3280a9 |
+ case OPERATION_PL_PENDING:
|
|
|
3280a9 |
+ flags_str = "pending";
|
|
|
3280a9 |
+ break;
|
|
|
3280a9 |
+ default:
|
|
|
3280a9 |
+ flags_str = "unknown";
|
|
|
3280a9 |
+ break;
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+
|
|
|
3280a9 |
+ }
|
|
|
3280a9 |
+ slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "dump pending list(0x%lx) %s %s\n",
|
|
|
3280a9 |
(ulong) curr_op->op, entry_str, flags_str);
|
|
|
3280a9 |
+ }
|
|
|
3280a9 |
}
|
|
|
3280a9 |
-#endif
|
|
|
3280a9 |
|
|
|
3280a9 |
/* Second check if it remains a pending operation in the pending list */
|
|
|
3280a9 |
for (curr_op = prim_op; curr_op; curr_op = curr_op->next) {
|
|
|
3280a9 |
--
|
|
|
3280a9 |
2.26.2
|
|
|
3280a9 |
|