|
|
b8da0b |
From 55a47c1bfe1ce1c27e470384c4f1d50895db25f7 Mon Sep 17 00:00:00 2001
|
|
|
b8da0b |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
b8da0b |
Date: Tue, 13 Jul 2021 14:18:03 -0400
|
|
|
b8da0b |
Subject: [PATCH] Issue 4443 - Internal unindexed searches in syncrepl/retro
|
|
|
b8da0b |
changelog
|
|
|
b8da0b |
|
|
|
b8da0b |
Bug Description:
|
|
|
b8da0b |
|
|
|
b8da0b |
When a non-system index is added to a backend it is
|
|
|
b8da0b |
disabled until the database is initialized or reindexed.
|
|
|
b8da0b |
So in the case of the retro changelog the changenumber index
|
|
|
b8da0b |
is alway disabled by default since it is never initialized.
|
|
|
b8da0b |
This leads to unexpected unindexed searches of the retro
|
|
|
b8da0b |
changelog.
|
|
|
b8da0b |
|
|
|
b8da0b |
Fix Description:
|
|
|
b8da0b |
|
|
|
b8da0b |
If an index has "nsSystemIndex" set to "true" then enable it
|
|
|
b8da0b |
immediately.
|
|
|
b8da0b |
|
|
|
b8da0b |
relates: https://github.com/389ds/389-ds-base/issues/4443
|
|
|
b8da0b |
|
|
|
b8da0b |
Reviewed by: spichugi & tbordaz(Thanks!!)
|
|
|
b8da0b |
---
|
|
|
b8da0b |
.../tests/suites/retrocl/basic_test.py | 53 ++++++++-------
|
|
|
b8da0b |
.../suites/retrocl/retrocl_indexing_test.py | 68 +++++++++++++++++++
|
|
|
b8da0b |
ldap/servers/plugins/retrocl/retrocl_create.c | 2 +-
|
|
|
b8da0b |
.../slapd/back-ldbm/ldbm_index_config.c | 25 +++++--
|
|
|
b8da0b |
src/lib389/lib389/_mapped_object.py | 13 ++++
|
|
|
b8da0b |
5 files changed, 130 insertions(+), 31 deletions(-)
|
|
|
b8da0b |
create mode 100644 dirsrvtests/tests/suites/retrocl/retrocl_indexing_test.py
|
|
|
b8da0b |
|
|
|
b8da0b |
diff --git a/dirsrvtests/tests/suites/retrocl/basic_test.py b/dirsrvtests/tests/suites/retrocl/basic_test.py
|
|
|
b8da0b |
index f3bc50f29..84d513829 100644
|
|
|
b8da0b |
--- a/dirsrvtests/tests/suites/retrocl/basic_test.py
|
|
|
b8da0b |
+++ b/dirsrvtests/tests/suites/retrocl/basic_test.py
|
|
|
b8da0b |
@@ -8,7 +8,6 @@
|
|
|
b8da0b |
|
|
|
b8da0b |
import logging
|
|
|
b8da0b |
import ldap
|
|
|
b8da0b |
-import time
|
|
|
b8da0b |
import pytest
|
|
|
b8da0b |
from lib389.topologies import topology_st
|
|
|
b8da0b |
from lib389.plugins import RetroChangelogPlugin
|
|
|
b8da0b |
@@ -18,7 +17,8 @@ from lib389.tasks import *
|
|
|
b8da0b |
from lib389.cli_base import FakeArgs, connect_instance, disconnect_instance
|
|
|
b8da0b |
from lib389.cli_base.dsrc import dsrc_arg_concat
|
|
|
b8da0b |
from lib389.cli_conf.plugins.retrochangelog import retrochangelog_add_attr
|
|
|
b8da0b |
-from lib389.idm.user import UserAccount, UserAccounts, nsUserAccounts
|
|
|
b8da0b |
+from lib389.idm.user import UserAccount, UserAccounts
|
|
|
b8da0b |
+from lib389._mapped_object import DSLdapObjects
|
|
|
b8da0b |
|
|
|
b8da0b |
pytestmark = pytest.mark.tier1
|
|
|
b8da0b |
|
|
|
b8da0b |
@@ -82,7 +82,7 @@ def test_retrocl_exclude_attr_add(topology_st):
|
|
|
b8da0b |
|
|
|
b8da0b |
log.info('Adding user1')
|
|
|
b8da0b |
try:
|
|
|
b8da0b |
- user1 = users.create(properties={
|
|
|
b8da0b |
+ users.create(properties={
|
|
|
b8da0b |
'sn': '1',
|
|
|
b8da0b |
'cn': 'user 1',
|
|
|
b8da0b |
'uid': 'user1',
|
|
|
b8da0b |
@@ -97,17 +97,18 @@ def test_retrocl_exclude_attr_add(topology_st):
|
|
|
b8da0b |
except ldap.ALREADY_EXISTS:
|
|
|
b8da0b |
pass
|
|
|
b8da0b |
except ldap.LDAPError as e:
|
|
|
b8da0b |
- log.error("Failed to add user1")
|
|
|
b8da0b |
+ log.error("Failed to add user1: " + str(e))
|
|
|
b8da0b |
|
|
|
b8da0b |
log.info('Verify homePhone and carLicense attrs are in the changelog changestring')
|
|
|
b8da0b |
try:
|
|
|
b8da0b |
- cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER1_DN)
|
|
|
b8da0b |
+ retro_changelog_suffix = DSLdapObjects(st, basedn=RETROCL_SUFFIX)
|
|
|
b8da0b |
+ cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
|
|
|
b8da0b |
except ldap.LDAPError as e:
|
|
|
b8da0b |
- log.fatal("Changelog search failed, error: " +str(e))
|
|
|
b8da0b |
+ log.fatal("Changelog search failed, error: " + str(e))
|
|
|
b8da0b |
assert False
|
|
|
b8da0b |
assert len(cllist) > 0
|
|
|
b8da0b |
- if cllist[0].hasAttr('changes'):
|
|
|
b8da0b |
- clstr = (cllist[0].getValue('changes')).decode()
|
|
|
b8da0b |
+ if cllist[0].present('changes'):
|
|
|
b8da0b |
+ clstr = str(cllist[0].get_attr_vals_utf8('changes'))
|
|
|
b8da0b |
assert ATTR_HOMEPHONE in clstr
|
|
|
b8da0b |
assert ATTR_CARLICENSE in clstr
|
|
|
b8da0b |
|
|
|
b8da0b |
@@ -134,7 +135,7 @@ def test_retrocl_exclude_attr_add(topology_st):
|
|
|
b8da0b |
|
|
|
b8da0b |
log.info('Adding user2')
|
|
|
b8da0b |
try:
|
|
|
b8da0b |
- user2 = users.create(properties={
|
|
|
b8da0b |
+ users.create(properties={
|
|
|
b8da0b |
'sn': '2',
|
|
|
b8da0b |
'cn': 'user 2',
|
|
|
b8da0b |
'uid': 'user2',
|
|
|
b8da0b |
@@ -149,18 +150,18 @@ def test_retrocl_exclude_attr_add(topology_st):
|
|
|
b8da0b |
except ldap.ALREADY_EXISTS:
|
|
|
b8da0b |
pass
|
|
|
b8da0b |
except ldap.LDAPError as e:
|
|
|
b8da0b |
- log.error("Failed to add user2")
|
|
|
b8da0b |
+ log.error("Failed to add user2: " + str(e))
|
|
|
b8da0b |
|
|
|
b8da0b |
log.info('Verify homePhone attr is not in the changelog changestring')
|
|
|
b8da0b |
try:
|
|
|
b8da0b |
- cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER2_DN)
|
|
|
b8da0b |
+ cllist = retro_changelog_suffix.filter(f'(targetDn={USER2_DN})')
|
|
|
b8da0b |
assert len(cllist) > 0
|
|
|
b8da0b |
- if cllist[0].hasAttr('changes'):
|
|
|
b8da0b |
- clstr = (cllist[0].getValue('changes')).decode()
|
|
|
b8da0b |
+ if cllist[0].present('changes'):
|
|
|
b8da0b |
+ clstr = str(cllist[0].get_attr_vals_utf8('changes'))
|
|
|
b8da0b |
assert ATTR_HOMEPHONE not in clstr
|
|
|
b8da0b |
assert ATTR_CARLICENSE in clstr
|
|
|
b8da0b |
except ldap.LDAPError as e:
|
|
|
b8da0b |
- log.fatal("Changelog search failed, error: " +str(e))
|
|
|
b8da0b |
+ log.fatal("Changelog search failed, error: " + str(e))
|
|
|
b8da0b |
assert False
|
|
|
b8da0b |
|
|
|
b8da0b |
def test_retrocl_exclude_attr_mod(topology_st):
|
|
|
b8da0b |
@@ -228,19 +229,20 @@ def test_retrocl_exclude_attr_mod(topology_st):
|
|
|
b8da0b |
'homeDirectory': '/home/user1',
|
|
|
b8da0b |
'userpassword': USER_PW})
|
|
|
b8da0b |
except ldap.ALREADY_EXISTS:
|
|
|
b8da0b |
- pass
|
|
|
b8da0b |
+ user1 = UserAccount(st, dn=USER1_DN)
|
|
|
b8da0b |
except ldap.LDAPError as e:
|
|
|
b8da0b |
- log.error("Failed to add user1")
|
|
|
b8da0b |
+ log.error("Failed to add user1: " + str(e))
|
|
|
b8da0b |
|
|
|
b8da0b |
log.info('Verify homePhone and carLicense attrs are in the changelog changestring')
|
|
|
b8da0b |
try:
|
|
|
b8da0b |
- cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER1_DN)
|
|
|
b8da0b |
+ retro_changelog_suffix = DSLdapObjects(st, basedn=RETROCL_SUFFIX)
|
|
|
b8da0b |
+ cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
|
|
|
b8da0b |
except ldap.LDAPError as e:
|
|
|
b8da0b |
- log.fatal("Changelog search failed, error: " +str(e))
|
|
|
b8da0b |
+ log.fatal("Changelog search failed, error: " + str(e))
|
|
|
b8da0b |
assert False
|
|
|
b8da0b |
assert len(cllist) > 0
|
|
|
b8da0b |
- if cllist[0].hasAttr('changes'):
|
|
|
b8da0b |
- clstr = (cllist[0].getValue('changes')).decode()
|
|
|
b8da0b |
+ if cllist[0].present('changes'):
|
|
|
b8da0b |
+ clstr = str(cllist[0].get_attr_vals_utf8('changes'))
|
|
|
b8da0b |
assert ATTR_HOMEPHONE in clstr
|
|
|
b8da0b |
assert ATTR_CARLICENSE in clstr
|
|
|
b8da0b |
|
|
|
b8da0b |
@@ -267,24 +269,25 @@ def test_retrocl_exclude_attr_mod(topology_st):
|
|
|
b8da0b |
|
|
|
b8da0b |
log.info('Modify user1 carLicense attribute')
|
|
|
b8da0b |
try:
|
|
|
b8da0b |
- st.modify_s(USER1_DN, [(ldap.MOD_REPLACE, ATTR_CARLICENSE, b"123WX321")])
|
|
|
b8da0b |
+ user1.replace(ATTR_CARLICENSE, "123WX321")
|
|
|
b8da0b |
except ldap.LDAPError as e:
|
|
|
b8da0b |
log.fatal('test_retrocl_exclude_attr_mod: Failed to update user1 attribute: error ' + e.message['desc'])
|
|
|
b8da0b |
assert False
|
|
|
b8da0b |
|
|
|
b8da0b |
log.info('Verify carLicense attr is not in the changelog changestring')
|
|
|
b8da0b |
try:
|
|
|
b8da0b |
- cllist = st.search_s(RETROCL_SUFFIX, ldap.SCOPE_SUBTREE, '(targetDn=%s)' % USER1_DN)
|
|
|
b8da0b |
+ cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
|
|
|
b8da0b |
assert len(cllist) > 0
|
|
|
b8da0b |
# There will be 2 entries in the changelog for this user, we are only
|
|
|
b8da0b |
#interested in the second one, the modify operation.
|
|
|
b8da0b |
- if cllist[1].hasAttr('changes'):
|
|
|
b8da0b |
- clstr = (cllist[1].getValue('changes')).decode()
|
|
|
b8da0b |
+ if cllist[1].present('changes'):
|
|
|
b8da0b |
+ clstr = str(cllist[1].get_attr_vals_utf8('changes'))
|
|
|
b8da0b |
assert ATTR_CARLICENSE not in clstr
|
|
|
b8da0b |
except ldap.LDAPError as e:
|
|
|
b8da0b |
- log.fatal("Changelog search failed, error: " +str(e))
|
|
|
b8da0b |
+ log.fatal("Changelog search failed, error: " + str(e))
|
|
|
b8da0b |
assert False
|
|
|
b8da0b |
|
|
|
b8da0b |
+
|
|
|
b8da0b |
if __name__ == '__main__':
|
|
|
b8da0b |
# Run isolated
|
|
|
b8da0b |
# -s for DEBUG mode
|
|
|
b8da0b |
diff --git a/dirsrvtests/tests/suites/retrocl/retrocl_indexing_test.py b/dirsrvtests/tests/suites/retrocl/retrocl_indexing_test.py
|
|
|
b8da0b |
new file mode 100644
|
|
|
b8da0b |
index 000000000..b1dfe962c
|
|
|
b8da0b |
--- /dev/null
|
|
|
b8da0b |
+++ b/dirsrvtests/tests/suites/retrocl/retrocl_indexing_test.py
|
|
|
b8da0b |
@@ -0,0 +1,68 @@
|
|
|
b8da0b |
+import logging
|
|
|
b8da0b |
+import pytest
|
|
|
b8da0b |
+import os
|
|
|
b8da0b |
+from lib389._constants import RETROCL_SUFFIX, DEFAULT_SUFFIX
|
|
|
b8da0b |
+from lib389.topologies import topology_st as topo
|
|
|
b8da0b |
+from lib389.plugins import RetroChangelogPlugin
|
|
|
b8da0b |
+from lib389.idm.user import UserAccounts
|
|
|
b8da0b |
+from lib389._mapped_object import DSLdapObjects
|
|
|
b8da0b |
+log = logging.getLogger(__name__)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+def test_indexing_is_online(topo):
|
|
|
b8da0b |
+ """Test that the changenmumber index is online right after enabling the plugin
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ :id: 16f4c001-9e0c-4448-a2b3-08ac1e85d40f
|
|
|
b8da0b |
+ :setup: Standalone Instance
|
|
|
b8da0b |
+ :steps:
|
|
|
b8da0b |
+ 1. Enable retro cl
|
|
|
b8da0b |
+ 2. Perform some updates
|
|
|
b8da0b |
+ 3. Search for "(changenumber>=-1)", and it is not partially unindexed
|
|
|
b8da0b |
+ 4. Search for "(&(changenumber>=-1)(targetuniqueid=*))", and it is not partially unindexed
|
|
|
b8da0b |
+ :expectedresults:
|
|
|
b8da0b |
+ 1. Success
|
|
|
b8da0b |
+ 2. Success
|
|
|
b8da0b |
+ 3. Success
|
|
|
b8da0b |
+ 4. Success
|
|
|
b8da0b |
+ """
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Enable plugin
|
|
|
b8da0b |
+ topo.standalone.config.set('nsslapd-accesslog-logbuffering', 'off')
|
|
|
b8da0b |
+ plugin = RetroChangelogPlugin(topo.standalone)
|
|
|
b8da0b |
+ plugin.enable()
|
|
|
b8da0b |
+ topo.standalone.restart()
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Do a bunch of updates
|
|
|
b8da0b |
+ users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
|
|
|
b8da0b |
+ user_entry = users.create(properties={
|
|
|
b8da0b |
+ 'sn': '1',
|
|
|
b8da0b |
+ 'cn': 'user 1',
|
|
|
b8da0b |
+ 'uid': 'user1',
|
|
|
b8da0b |
+ 'uidNumber': '11',
|
|
|
b8da0b |
+ 'gidNumber': '111',
|
|
|
b8da0b |
+ 'givenname': 'user1',
|
|
|
b8da0b |
+ 'homePhone': '0861234567',
|
|
|
b8da0b |
+ 'carLicense': '131D16674',
|
|
|
b8da0b |
+ 'mail': 'user1@whereever.com',
|
|
|
b8da0b |
+ 'homeDirectory': '/home'
|
|
|
b8da0b |
+ })
|
|
|
b8da0b |
+ for count in range(0, 10):
|
|
|
b8da0b |
+ user_entry.replace('mail', f'test{count}@test.com')
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Search the retro cl, and check for error messages
|
|
|
b8da0b |
+ filter_simple = '(changenumber>=-1)'
|
|
|
b8da0b |
+ filter_compound = '(&(changenumber>=-1)(targetuniqueid=*))'
|
|
|
b8da0b |
+ retro_changelog_suffix = DSLdapObjects(topo.standalone, basedn=RETROCL_SUFFIX)
|
|
|
b8da0b |
+ retro_changelog_suffix.filter(filter_simple)
|
|
|
b8da0b |
+ assert not topo.standalone.searchAccessLog('Partially Unindexed Filter')
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Search the retro cl again with compound filter
|
|
|
b8da0b |
+ retro_changelog_suffix.filter(filter_compound)
|
|
|
b8da0b |
+ assert not topo.standalone.searchAccessLog('Partially Unindexed Filter')
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+if __name__ == '__main__':
|
|
|
b8da0b |
+ # Run isolated
|
|
|
b8da0b |
+ # -s for DEBUG mode
|
|
|
b8da0b |
+ CURRENT_FILE = os.path.realpath(__file__)
|
|
|
b8da0b |
+ pytest.main(["-s", CURRENT_FILE])
|
|
|
b8da0b |
diff --git a/ldap/servers/plugins/retrocl/retrocl_create.c b/ldap/servers/plugins/retrocl/retrocl_create.c
|
|
|
b8da0b |
index 571e6899f..5bfde7831 100644
|
|
|
b8da0b |
--- a/ldap/servers/plugins/retrocl/retrocl_create.c
|
|
|
b8da0b |
+++ b/ldap/servers/plugins/retrocl/retrocl_create.c
|
|
|
b8da0b |
@@ -133,7 +133,7 @@ retrocl_create_be(const char *bedir)
|
|
|
b8da0b |
val.bv_len = strlen(val.bv_val);
|
|
|
b8da0b |
slapi_entry_add_values(e, "cn", vals);
|
|
|
b8da0b |
|
|
|
b8da0b |
- val.bv_val = "false";
|
|
|
b8da0b |
+ val.bv_val = "true"; /* enables the index */
|
|
|
b8da0b |
val.bv_len = strlen(val.bv_val);
|
|
|
b8da0b |
slapi_entry_add_values(e, "nssystemindex", vals);
|
|
|
b8da0b |
|
|
|
b8da0b |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
|
|
|
b8da0b |
index 9722d0ce7..38e7368e1 100644
|
|
|
b8da0b |
--- a/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
|
|
|
b8da0b |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_index_config.c
|
|
|
b8da0b |
@@ -25,7 +25,7 @@ int ldbm_instance_index_config_delete_callback(Slapi_PBlock *pb, Slapi_Entry *en
|
|
|
b8da0b |
#define INDEXTYPE_NONE 1
|
|
|
b8da0b |
|
|
|
b8da0b |
static int
|
|
|
b8da0b |
-ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e, const char *trace_string, char **index_name, char *err_buf)
|
|
|
b8da0b |
+ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e, const char *trace_string, char **index_name, PRBool *is_system_index, char *err_buf)
|
|
|
b8da0b |
{
|
|
|
b8da0b |
Slapi_Attr *attr;
|
|
|
b8da0b |
const struct berval *attrValue;
|
|
|
b8da0b |
@@ -78,6 +78,15 @@ ldbm_index_parse_entry(ldbm_instance *inst, Slapi_Entry *e, const char *trace_st
|
|
|
b8da0b |
}
|
|
|
b8da0b |
}
|
|
|
b8da0b |
|
|
|
b8da0b |
+ *is_system_index = PR_FALSE;
|
|
|
b8da0b |
+ if (0 == slapi_entry_attr_find(e, "nsSystemIndex", &attr)) {
|
|
|
b8da0b |
+ slapi_attr_first_value(attr, &sval);
|
|
|
b8da0b |
+ attrValue = slapi_value_get_berval(sval);
|
|
|
b8da0b |
+ if (strcasecmp(attrValue->bv_val, "true") == 0) {
|
|
|
b8da0b |
+ *is_system_index = PR_TRUE;
|
|
|
b8da0b |
+ }
|
|
|
b8da0b |
+ }
|
|
|
b8da0b |
+
|
|
|
b8da0b |
/* ok the entry is good to process, pass it to attr_index_config */
|
|
|
b8da0b |
if (attr_index_config(inst->inst_be, (char *)trace_string, 0, e, 0, 0, err_buf)) {
|
|
|
b8da0b |
slapi_ch_free_string(index_name);
|
|
|
b8da0b |
@@ -101,9 +110,10 @@ ldbm_index_init_entry_callback(Slapi_PBlock *pb __attribute__((unused)),
|
|
|
b8da0b |
void *arg)
|
|
|
b8da0b |
{
|
|
|
b8da0b |
ldbm_instance *inst = (ldbm_instance *)arg;
|
|
|
b8da0b |
+ PRBool is_system_index = PR_FALSE;
|
|
|
b8da0b |
|
|
|
b8da0b |
returntext[0] = '\0';
|
|
|
b8da0b |
- *returncode = ldbm_index_parse_entry(inst, e, "from ldbm instance init", NULL, NULL);
|
|
|
b8da0b |
+ *returncode = ldbm_index_parse_entry(inst, e, "from ldbm instance init", NULL, &is_system_index /* not used */, NULL);
|
|
|
b8da0b |
if (*returncode == LDAP_SUCCESS) {
|
|
|
b8da0b |
return SLAPI_DSE_CALLBACK_OK;
|
|
|
b8da0b |
} else {
|
|
|
b8da0b |
@@ -126,17 +136,21 @@ ldbm_instance_index_config_add_callback(Slapi_PBlock *pb __attribute__((unused))
|
|
|
b8da0b |
{
|
|
|
b8da0b |
ldbm_instance *inst = (ldbm_instance *)arg;
|
|
|
b8da0b |
char *index_name = NULL;
|
|
|
b8da0b |
+ PRBool is_system_index = PR_FALSE;
|
|
|
b8da0b |
|
|
|
b8da0b |
returntext[0] = '\0';
|
|
|
b8da0b |
- *returncode = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, returntext);
|
|
|
b8da0b |
+ *returncode = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, &is_system_index, returntext);
|
|
|
b8da0b |
if (*returncode == LDAP_SUCCESS) {
|
|
|
b8da0b |
struct attrinfo *ai = NULL;
|
|
|
b8da0b |
/* if the index is a "system" index, we assume it's being added by
|
|
|
b8da0b |
* by the server, and it's okay for the index to go online immediately.
|
|
|
b8da0b |
* if not, we set the index "offline" so it won't actually be used
|
|
|
b8da0b |
* until someone runs db2index on it.
|
|
|
b8da0b |
+ * If caller wants to add an index that they want to be online
|
|
|
b8da0b |
+ * immediately they can also set "nsSystemIndex" to "true" in the
|
|
|
b8da0b |
+ * index config entry (e.g. is_system_index).
|
|
|
b8da0b |
*/
|
|
|
b8da0b |
- if (!ldbm_attribute_always_indexed(index_name)) {
|
|
|
b8da0b |
+ if (!is_system_index && !ldbm_attribute_always_indexed(index_name)) {
|
|
|
b8da0b |
ainfo_get(inst->inst_be, index_name, &ai;;
|
|
|
b8da0b |
PR_ASSERT(ai != NULL);
|
|
|
b8da0b |
ai->ai_indexmask |= INDEX_OFFLINE;
|
|
|
b8da0b |
@@ -386,13 +400,14 @@ ldbm_instance_index_config_enable_index(ldbm_instance *inst, Slapi_Entry *e)
|
|
|
b8da0b |
char *index_name = NULL;
|
|
|
b8da0b |
int rc = LDAP_SUCCESS;
|
|
|
b8da0b |
struct attrinfo *ai = NULL;
|
|
|
b8da0b |
+ PRBool is_system_index = PR_FALSE;
|
|
|
b8da0b |
|
|
|
b8da0b |
index_name = slapi_entry_attr_get_charptr(e, "cn");
|
|
|
b8da0b |
if (index_name) {
|
|
|
b8da0b |
ainfo_get(inst->inst_be, index_name, &ai;;
|
|
|
b8da0b |
}
|
|
|
b8da0b |
if (!ai) {
|
|
|
b8da0b |
- rc = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, NULL);
|
|
|
b8da0b |
+ rc = ldbm_index_parse_entry(inst, e, "from DSE add", &index_name, &is_system_index /* not used */, NULL);
|
|
|
b8da0b |
}
|
|
|
b8da0b |
if (rc == LDAP_SUCCESS) {
|
|
|
b8da0b |
/* Assume the caller knows if it is OK to go online immediately */
|
|
|
b8da0b |
diff --git a/src/lib389/lib389/_mapped_object.py b/src/lib389/lib389/_mapped_object.py
|
|
|
b8da0b |
index b6d778b01..fe610d175 100644
|
|
|
b8da0b |
--- a/src/lib389/lib389/_mapped_object.py
|
|
|
b8da0b |
+++ b/src/lib389/lib389/_mapped_object.py
|
|
|
b8da0b |
@@ -148,6 +148,19 @@ class DSLdapObject(DSLogging, DSLint):
|
|
|
b8da0b |
|
|
|
b8da0b |
return True
|
|
|
b8da0b |
|
|
|
b8da0b |
+ def search(self, scope="subtree", filter='objectclass=*'):
|
|
|
b8da0b |
+ search_scope = ldap.SCOPE_SUBTREE
|
|
|
b8da0b |
+ if scope == 'base':
|
|
|
b8da0b |
+ search_scope = ldap.SCOPE_BASE
|
|
|
b8da0b |
+ elif scope == 'one':
|
|
|
b8da0b |
+ search_scope = ldap.SCOPE_ONE
|
|
|
b8da0b |
+ elif scope == 'subtree':
|
|
|
b8da0b |
+ search_scope = ldap.SCOPE_SUBTREE
|
|
|
b8da0b |
+ return self._instance.search_ext_s(self._dn, search_scope, filter,
|
|
|
b8da0b |
+ serverctrls=self._server_controls,
|
|
|
b8da0b |
+ clientctrls=self._client_controls,
|
|
|
b8da0b |
+ escapehatch='i am sure')
|
|
|
b8da0b |
+
|
|
|
b8da0b |
def display(self, attrlist=['*']):
|
|
|
b8da0b |
"""Get an entry but represent it as a string LDIF
|
|
|
b8da0b |
|
|
|
b8da0b |
--
|
|
|
b8da0b |
2.31.1
|
|
|
b8da0b |
|