Blame SOURCES/0073-Ticket-49540-Indexing-task-is-reported-finished-too-.patch

b045b9
From 3dac3503087b6bae9e6e3d63a8214e8be65a145b Mon Sep 17 00:00:00 2001
61f723
From: Thierry Bordaz <tbordaz@redhat.com>
61f723
Date: Fri, 19 Jan 2018 17:50:59 +0100
b045b9
Subject: [PATCH 05/10] Ticket 49540 - Indexing task is reported finished too
b045b9
 early regarding the backend status
61f723
61f723
Bug Description:
61f723
	If a task complete successfully, its status is updated before the backend
61f723
	can receive update.
61f723
61f723
Fix Description:
61f723
	postpone the task status update after backend is reenabled
61f723
61f723
https://pagure.io/389-ds-base/issue/49540
61f723
61f723
Reviewed by: Ludwig Krispenz
61f723
61f723
Platforms tested: F26
61f723
61f723
Flag Day: no
61f723
61f723
Doc impact: no
61f723
---
61f723
 dirsrvtests/tests/tickets/ticket49540_test.py | 135 ++++++++++++++++++++++++++
61f723
 ldap/servers/slapd/back-ldbm/ldif2ldbm.c      |  16 +--
61f723
 2 files changed, 145 insertions(+), 6 deletions(-)
61f723
 create mode 100644 dirsrvtests/tests/tickets/ticket49540_test.py
61f723
61f723
diff --git a/dirsrvtests/tests/tickets/ticket49540_test.py b/dirsrvtests/tests/tickets/ticket49540_test.py
61f723
new file mode 100644
61f723
index 000000000..1fbfde2c5
61f723
--- /dev/null
61f723
+++ b/dirsrvtests/tests/tickets/ticket49540_test.py
61f723
@@ -0,0 +1,135 @@
61f723
+import logging
61f723
+import pytest
61f723
+import os
61f723
+import ldap
61f723
+import time
61f723
+import re
61f723
+from lib389._constants import *
61f723
+from lib389.tasks import *
61f723
+from lib389.topologies import topology_st as topo
61f723
+from lib389.idm.user import UserAccount, UserAccounts, TEST_USER_PROPERTIES
61f723
+from lib389 import Entry
61f723
+
61f723
+
61f723
+
61f723
+DEBUGGING = os.getenv("DEBUGGING", default=False)
61f723
+if DEBUGGING:
61f723
+    logging.getLogger(__name__).setLevel(logging.DEBUG)
61f723
+else:
61f723
+    logging.getLogger(__name__).setLevel(logging.INFO)
61f723
+log = logging.getLogger(__name__)
61f723
+
61f723
+HOMEDIRECTORY_INDEX = 'cn=homeDirectory,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config'
61f723
+HOMEDIRECTORY_CN = "homedirectory"
61f723
+MATCHINGRULE = 'nsMatchingRule'
61f723
+USER_CN = 'user_'
61f723
+
61f723
+def create_index_entry(topo):
61f723
+    log.info("\n\nindex homeDirectory")
61f723
+    try:
61f723
+        ent = topo.getEntry(HOMEDIRECTORY_INDEX, ldap.SCOPE_BASE)
61f723
+    except ldap.NO_SUCH_OBJECT:
61f723
+        topo.add_s(Entry((HOMEDIRECTORY_INDEX, {
61f723
+            'objectclass': "top nsIndex".split(),
61f723
+            'cn': HOMEDIRECTORY_CN,
61f723
+            'nsSystemIndex': 'false',
61f723
+            MATCHINGRULE: ['caseIgnoreIA5Match', 'caseExactIA5Match' ],
61f723
+            'nsIndexType': ['eq', 'sub', 'pres']})))
61f723
+
61f723
+
61f723
+def provision_users(topo):
61f723
+    test_users = []
61f723
+    homeValue = b'x' * (32 * 1024)  # just to slow down indexing
61f723
+    for i in range(100):
61f723
+        CN = '%s%d' % (USER_CN, i)
61f723
+        users = UserAccounts(topo, SUFFIX)
61f723
+        user_props = TEST_USER_PROPERTIES.copy()
61f723
+        user_props.update({'uid': CN, 'cn': CN, 'sn': '_%s' % CN, HOMEDIRECTORY_CN: homeValue})
61f723
+        testuser = users.create(properties=user_props)
61f723
+        test_users.append(testuser)
61f723
+    return test_users
61f723
+
61f723
+def start_start_status(server):
61f723
+    args = {TASK_WAIT: False}
61f723
+    indexTask = Tasks(server)
61f723
+    indexTask.reindex(suffix=SUFFIX, attrname='homeDirectory', args=args)
61f723
+    return indexTask
61f723
+
61f723
+def check_task_status(server, indexTask, test_entry):
61f723
+    finish_pattern = re.compile(".*Finished indexing.*")
61f723
+    mod = [(ldap.MOD_REPLACE, 'sn', b'foo')]
61f723
+    for i in range(10):
61f723
+        log.info("check_task_status =========> %d th loop" % i)
61f723
+        try:
61f723
+            ent = server.getEntry(indexTask.dn, ldap.SCOPE_BASE)
61f723
+            if ent.hasAttr('nsTaskStatus'):
61f723
+                value = str(ent.getValue('nsTaskStatus'))
61f723
+                finish = finish_pattern.search(value)
61f723
+                log.info("%s ---> %s" % (indexTask.dn, value))
61f723
+            else:
61f723
+                finish = None
61f723
+                log.info("%s ---> NO STATUS" % (indexTask.dn))
61f723
+
61f723
+            if not finish:
61f723
+                # This is not yet finished try an update
61f723
+                try:
61f723
+                    server.modify_s(test_entry, mod)
61f723
+
61f723
+                    # weird, may be indexing just complete
61f723
+                    ent = server.getEntry(indexTask.dn, ldap.SCOPE_BASE, ['nsTaskStatus'])
61f723
+                    assert (ent.hasAttr('nsTaskStatus') and regex.search(ent.getValue('nsTaskStatus')))
61f723
+                    log.info("Okay, it just finished so the MOD was successful")
61f723
+                except ldap.UNWILLING_TO_PERFORM:
61f723
+                    log.info("=========> Great it was expected in the middle of index")
61f723
+            else:
61f723
+                # The update should be successful
61f723
+                server.modify_s(test_entry, mod)
61f723
+
61f723
+        except ldap.NO_SUCH_OBJECT:
61f723
+            log.info("%s: no found" % (indexTask.dn))
61f723
+
61f723
+        time.sleep(1)
61f723
+
61f723
+def test_ticket49540(topo):
61f723
+    """Specify a test case purpose or name here
61f723
+
61f723
+    :id: 1df16d5a-1b92-46b7-8435-876b87545748
61f723
+    :setup: Standalone Instance
61f723
+    :steps:
61f723
+        1. Create homeDirectory index (especially with substring)
61f723
+        2. Creates 100 users with large homeDirectory value => long to index
61f723
+        3. Start an indexing task WITHOUT waiting for its completion
61f723
+        4. Monitor that until task.status = 'Finish', any update -> UNWILLING to perform
61f723
+    :expectedresults:
61f723
+        1. Index configuration succeeds
61f723
+        2. users entry are successfully created
61f723
+        3. Indexing task is started
61f723
+        4. If the task.status does not contain 'Finished indexing', any update should return UNWILLING_TO_PERFORM
61f723
+           When it contains 'Finished indexing', updates should be successful
61f723
+    """
61f723
+
61f723
+    server = topo.standalone
61f723
+    create_index_entry(server)
61f723
+    test_users = provision_users(server)
61f723
+
61f723
+    indexTask = start_start_status(server)
61f723
+    check_task_status(server, indexTask, test_users[0].dn)
61f723
+
61f723
+    # If you need any test suite initialization,
61f723
+    # please, write additional fixture for that (including finalizer).
61f723
+    # Topology for suites are predefined in lib389/topologies.py.
61f723
+
61f723
+    # If you need host, port or any other data about instance,
61f723
+    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
61f723
+
61f723
+    if DEBUGGING:
61f723
+        # Add debugging steps(if any)...
61f723
+        pass
61f723
+
61f723
+
61f723
+if __name__ == '__main__':
61f723
+    # Run isolated
61f723
+    # -s for DEBUG mode
61f723
+    CURRENT_FILE = os.path.realpath(__file__)
61f723
+    pytest.main(["-s", CURRENT_FILE])
61f723
+
61f723
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
b045b9
index 4347c1721..16b87ee6b 100644
61f723
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
61f723
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
b045b9
@@ -2562,12 +2562,7 @@ ldbm_back_ldbm2index(Slapi_PBlock *pb)
61f723
         vlvIndex_go_online(pvlv[vlvidx], be);
61f723
     }
61f723
 
61f723
-    if (task) {
61f723
-        slapi_task_log_status(task, "%s: Finished indexing.",
61f723
-                              inst->inst_name);
61f723
-        slapi_task_log_notice(task, "%s: Finished indexing.",
61f723
-                              inst->inst_name);
61f723
-    }
61f723
+    /* if it was a task, its status will be updated later after backend is ready for update */
61f723
     slapi_log_err(SLAPI_LOG_INFO, "ldbm_back_ldbm2index", "%s: Finished indexing.\n",
b045b9
                   inst->inst_name);
61f723
     return_value = 0; /* success */
b045b9
@@ -2591,6 +2586,15 @@ err_min:
b045b9
     dblayer_release_id2entry(be, db); /* nope */
61f723
     instance_set_not_busy(inst);
61f723
 
61f723
+    if (return_value == 0) {
61f723
+        if (task) {
61f723
+            slapi_task_log_status(task, "%s: Finished indexing.",
61f723
+                    inst->inst_name);
61f723
+            slapi_task_log_notice(task, "%s: Finished indexing.",
61f723
+                    inst->inst_name);
61f723
+        }
61f723
+    }
61f723
+
61f723
     if (run_from_cmdline) {
b045b9
         dblayer_instance_close(be);
b045b9
         if (0 != dblayer_close(li, DBLAYER_INDEX_MODE)) {
61f723
-- 
61f723
2.13.6
61f723