andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone

Blame SOURCES/0073-Ticket-47606-replica-init-bulk-import-errors-should-.patch

cc3dff
From 298ada3b2f7b8aa770df9a5a7d8129f46b4417d7 Mon Sep 17 00:00:00 2001
cc3dff
From: Noriko Hosoi <nhosoi@redhat.com>
cc3dff
Date: Mon, 16 Dec 2013 13:03:19 -0800
cc3dff
Subject: [PATCH 73/78] Ticket #47606 - replica init/bulk import errors should
cc3dff
 be more verbose
cc3dff
cc3dff
Description:
cc3dff
1. maxbersize: If the size of an entry is larger than the consumer's
cc3dff
   maxbersize, the following error used to be logged:
cc3dff
     Incoming BER Element was too long, max allowable is ### bytes.
cc3dff
     Change the nsslapd-maxbersize attribute in cn=config to increase.
cc3dff
   This message does not indicate how large the maxbersize needs to be.
cc3dff
   This patch adds the code to retrieve the failed ber size.
cc3dff
   Revised message:
cc3dff
     Incoming BER Element was @@@ bytes, max allowable is ### bytes.
cc3dff
	 Change the nsslapd-maxbersize attribute in cn=config to increase.
cc3dff
   Note: There is no lber API that returns the ber size if it fails to
cc3dff
   handle the ber.  This patch borrows the internal structure of ber
cc3dff
   and get the size.  This could be risky since the size or structure
cc3dff
   of the ber could be updated in the openldap/mozldap lber.
cc3dff
2. cache size: The bulk import depends upon the nsslapd-cachememsize
cc3dff
   value in the backend instance entry (e.g., cn=userRoot,cn=ldbm
cc3dff
   database,cn=plugins,cn=config).  If an entry size is larger than
cc3dff
   the cachememsize, the bulk import used to fail with this message:
cc3dff
     import userRoot: REASON: entry too large (@@@ bytes) for the
cc3dff
	 import buffer size (### bytes).  Try increasing nsslapd-
cc3dff
	 cachememsize.
cc3dff
   Also, the message follows the skipping entry message:
cc3dff
     import userRoot: WARNING: skipping entry "<DN>"
cc3dff
   but actually, it did NOT "skip" the entry and continue the bulk
cc3dff
   import, but it failed there and completely wiped out the backend
cc3dff
   database.
cc3dff
   This patch modifies the message as follows:
cc3dff
     import userRoot: REASON: entry too large (@@@ bytes) for the
cc3dff
	 effective import buffer size (### bytes). Try increasing nsslapd-
cc3dff
	 cachememsize for the backend instance "userRoot".
cc3dff
   and as the message mentions, it just skips the failed entry and
cc3dff
   continues the bulk import.
cc3dff
3. In repl5_tot_result_threadmain, when conn_read_result_ex returns
cc3dff
   non zero (non SUCCESS), it sets abort, but does not set any error
cc3dff
   code to rc (return code), which is not considered as "finished" in
cc3dff
   repl5_tot_waitfor_async_results and it contines waiting until the
cc3dff
   code reaches the max loop count (about 5 minutes).  This patch sets
cc3dff
   LDAP_CONNECT_ERROR to the return code along with setting abort, if
cc3dff
   conn_read_result_ex returns CONN_NOT_CONNECTED.  This makes the bulk
cc3dff
   import finishes quickly when it fails.
cc3dff
cc3dff
https://fedorahosted.org/389/ticket/47606
cc3dff
cc3dff
Reviewed by rmeggins@redhat.com (Thank you, Rich!!)
cc3dff
(cherry picked from commit 1119083d3d99993421609783efcb8962d78724fc)
cc3dff
(cherry picked from commit fde9ed5bf74b4ea1fff875bcb421137c78af1227)
cc3dff
(cherry picked from commit c9d0b6ccad84dd56a536da883f5a8e5acb01bc4e)
cc3dff
---
cc3dff
 .../plugins/replication/repl5_tot_protocol.c       |  3 ++
cc3dff
 ldap/servers/slapd/back-ldbm/import-threads.c      |  8 ++---
cc3dff
 ldap/servers/slapd/connection.c                    | 36 ++++++++++++++++++----
cc3dff
 ldap/servers/slapd/openldapber.h                   | 25 +++++++++++++++
cc3dff
 4 files changed, 62 insertions(+), 10 deletions(-)
cc3dff
 create mode 100644 ldap/servers/slapd/openldapber.h
cc3dff
cc3dff
diff --git a/ldap/servers/plugins/replication/repl5_tot_protocol.c b/ldap/servers/plugins/replication/repl5_tot_protocol.c
cc3dff
index a241128..3895ace 100644
cc3dff
--- a/ldap/servers/plugins/replication/repl5_tot_protocol.c
cc3dff
+++ b/ldap/servers/plugins/replication/repl5_tot_protocol.c
cc3dff
@@ -203,6 +203,9 @@ static void repl5_tot_result_threadmain(void *param)
cc3dff
 			/* If so then we need to take steps to abort the update process */
cc3dff
 			PR_Lock(cb->lock);
cc3dff
 			cb->abort = 1;
cc3dff
+			if (conres == CONN_NOT_CONNECTED) {
cc3dff
+				cb->rc = LDAP_CONNECT_ERROR;
cc3dff
+			}
cc3dff
 			PR_Unlock(cb->lock);
cc3dff
 		}
cc3dff
 		/* Should we stop ? */
cc3dff
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c b/ldap/servers/slapd/back-ldbm/import-threads.c
cc3dff
index c0475c6..95433aa 100644
cc3dff
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
cc3dff
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
cc3dff
@@ -3330,11 +3330,11 @@ static int bulk_import_queue(ImportJob *job, Slapi_Entry *entry)
cc3dff
 
cc3dff
     newesize = (slapi_entry_size(ep->ep_entry) + sizeof(struct backentry));
cc3dff
     if (newesize > job->fifo.bsize) {    /* entry too big */
cc3dff
-        import_log_notice(job, "WARNING: skipping entry \"%s\"",
cc3dff
-                    slapi_entry_get_dn(ep->ep_entry));
cc3dff
         import_log_notice(job, "REASON: entry too large (%lu bytes) for "
cc3dff
-                    "the import buffer size (%lu bytes).   Try increasing nsslapd-cachememsize.",
cc3dff
-                    (long unsigned int)newesize, (long unsigned int)job->fifo.bsize);
cc3dff
+                    "the effective import buffer size (%lu bytes). "
cc3dff
+                    "Try increasing nsslapd-cachememsize for the backend instance \"%s\".",
cc3dff
+                    (long unsigned int)newesize, (long unsigned int)job->fifo.bsize,
cc3dff
+                    job->inst->inst_name);
cc3dff
         backentry_clear_entry(ep);      /* entry is released in the frontend on failure*/
cc3dff
         backentry_free( &ep );          /* release the backend wrapper, here */
cc3dff
         PR_Unlock(job->wire_lock);
cc3dff
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
cc3dff
index fed3512..02c86c5 100644
cc3dff
--- a/ldap/servers/slapd/connection.c
cc3dff
+++ b/ldap/servers/slapd/connection.c
cc3dff
@@ -1749,6 +1749,32 @@ void connection_make_new_pb(Slapi_PBlock	**ppb, Connection	*conn)
cc3dff
 }
cc3dff
 
cc3dff
 
cc3dff
+#ifdef USE_OPENLDAP
cc3dff
+#include "openldapber.h"
cc3dff
+#else
cc3dff
+#include "mozldap.h"
cc3dff
+#endif
cc3dff
+
cc3dff
+static ber_tag_t
cc3dff
+_ber_get_len(BerElement *ber, ber_len_t *lenp)
cc3dff
+{
cc3dff
+#ifdef USE_OPENLDAP
cc3dff
+    OLBerElement *lber = (OLBerElement *)ber;
cc3dff
+#else
cc3dff
+    MozElement *lber = (MozElement *)ber;
cc3dff
+#endif
cc3dff
+
cc3dff
+    if (NULL == lenp) {
cc3dff
+        return LBER_DEFAULT;
cc3dff
+    }
cc3dff
+    *lenp = 0;
cc3dff
+    if (NULL == lber) {
cc3dff
+        return LBER_DEFAULT;
cc3dff
+    }
cc3dff
+    *lenp = lber->ber_len;
cc3dff
+    return lber->ber_tag;
cc3dff
+}
cc3dff
+
cc3dff
 /*
cc3dff
  * Utility function called by  connection_read_operation(). This is a
cc3dff
  * small wrapper on top of libldap's ber_get_next_buffer_ext().
cc3dff
@@ -1787,18 +1813,16 @@ get_next_from_buffer( void *buffer, size_t buffer_size, ber_len_t *lenp,
cc3dff
 	if ((LBER_OVERFLOW == *tagp || LBER_DEFAULT == *tagp) && 0 == bytes_scanned &&
cc3dff
 		!SLAPD_SYSTEM_WOULD_BLOCK_ERROR(errno))
cc3dff
 	{
cc3dff
-		if (LBER_OVERFLOW == *tagp)
cc3dff
-		{
cc3dff
-			err = SLAPD_DISCONNECT_BER_TOO_BIG;
cc3dff
-		}
cc3dff
-		else if (errno == ERANGE)
cc3dff
+		if ((LBER_OVERFLOW == *tagp) || (errno == ERANGE))
cc3dff
 		{
cc3dff
 			ber_len_t maxbersize = config_get_maxbersize();
cc3dff
+			ber_len_t tmplen = 0;
cc3dff
+			(void)_ber_get_len(ber, &tmplen);
cc3dff
 			/* openldap does not differentiate between length == 0
cc3dff
 			   and length > max - all we know is that there was a
cc3dff
 			   problem with the length - assume too big */
cc3dff
 			err = SLAPD_DISCONNECT_BER_TOO_BIG;
cc3dff
-			log_ber_too_big_error(conn, 0, maxbersize);
cc3dff
+			log_ber_too_big_error(conn, tmplen, maxbersize);
cc3dff
 		}
cc3dff
 		else
cc3dff
 		{
cc3dff
diff --git a/ldap/servers/slapd/openldapber.h b/ldap/servers/slapd/openldapber.h
cc3dff
new file mode 100644
cc3dff
index 0000000..52644a5
cc3dff
--- /dev/null
cc3dff
+++ b/ldap/servers/slapd/openldapber.h
cc3dff
@@ -0,0 +1,25 @@
cc3dff
+/*
cc3dff
+ * openldap lber library does not provide an API which returns the ber size
cc3dff
+ * (ber->ber_len) when the ber tag is LBER_DEFAULT or LBER_OVERFLOW.
cc3dff
+ * The ber size is useful when issuing an error message to indicate how
cc3dff
+ * large the maxbersize needs to be set.
cc3dff
+ * Borrowed from liblber/lber-int.h
cc3dff
+ */
cc3dff
+struct lber_options {
cc3dff
+    short lbo_valid;
cc3dff
+    unsigned short      lbo_options;
cc3dff
+    int         lbo_debug;
cc3dff
+};
cc3dff
+struct berelement {
cc3dff
+    struct      lber_options ber_opts;
cc3dff
+    ber_tag_t   ber_tag;
cc3dff
+    ber_len_t   ber_len;
cc3dff
+    ber_tag_t   ber_usertag;
cc3dff
+    char        *ber_buf;
cc3dff
+    char        *ber_ptr;
cc3dff
+    char        *ber_end;
cc3dff
+    char        *ber_sos_ptr;
cc3dff
+    char        *ber_rwptr;
cc3dff
+    void        *ber_memctx;
cc3dff
+};
cc3dff
+typedef struct berelement OLBerElement;
cc3dff
-- 
cc3dff
1.8.1.4
cc3dff