zrhoffman / rpms / 389-ds-base

Forked from rpms/389-ds-base 3 years ago
Clone

Blame SOURCES/0034-Issue-4526-sync_repl-when-completing-an-operation-in.patch

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