|
|
cb1cc6 |
From e65d6225398901c3319e72a460bc58e5d50df67c Mon Sep 17 00:00:00 2001
|
|
|
cb1cc6 |
From: Mark Reynolds <mreynolds@redhat.com>
|
|
|
cb1cc6 |
Date: Wed, 3 Aug 2022 16:27:15 -0400
|
|
|
cb1cc6 |
Subject: [PATCH 2/5] Issue 3903 - Supplier should do periodic updates
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
Description:
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
On suppliers update the keep alive entry periodically to keep the RUV up
|
|
|
cb1cc6 |
to date in case a replica is neglected for along time. This prevents
|
|
|
cb1cc6 |
very long changelog scans when finally processing updates.
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
relates: https://github.com/389ds/389-ds-base/issues/3903
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
Reviewed by: firstyear & tbordaz(Thanks!)
|
|
|
cb1cc6 |
---
|
|
|
cb1cc6 |
.../suites/replication/regression_m2_test.py | 96 +++++--------
|
|
|
cb1cc6 |
.../suites/replication/replica_config_test.py | 6 +-
|
|
|
cb1cc6 |
ldap/schema/01core389.ldif | 3 +-
|
|
|
cb1cc6 |
ldap/servers/plugins/replication/repl5.h | 11 +-
|
|
|
cb1cc6 |
.../plugins/replication/repl5_inc_protocol.c | 44 +-----
|
|
|
cb1cc6 |
.../plugins/replication/repl5_replica.c | 127 +++++++++++++-----
|
|
|
cb1cc6 |
.../replication/repl5_replica_config.c | 12 ++
|
|
|
cb1cc6 |
.../plugins/replication/repl5_tot_protocol.c | 4 +-
|
|
|
cb1cc6 |
ldap/servers/plugins/replication/repl_extop.c | 2 +-
|
|
|
cb1cc6 |
.../plugins/replication/repl_globals.c | 1 +
|
|
|
cb1cc6 |
.../src/lib/replication/replConfig.jsx | 32 ++++-
|
|
|
cb1cc6 |
src/cockpit/389-console/src/replication.jsx | 6 +
|
|
|
cb1cc6 |
src/lib389/lib389/cli_conf/replication.py | 6 +-
|
|
|
cb1cc6 |
13 files changed, 202 insertions(+), 148 deletions(-)
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
diff --git a/dirsrvtests/tests/suites/replication/regression_m2_test.py b/dirsrvtests/tests/suites/replication/regression_m2_test.py
|
|
|
cb1cc6 |
index 466e3c2c0..7dd0f2984 100644
|
|
|
cb1cc6 |
--- a/dirsrvtests/tests/suites/replication/regression_m2_test.py
|
|
|
cb1cc6 |
+++ b/dirsrvtests/tests/suites/replication/regression_m2_test.py
|
|
|
cb1cc6 |
@@ -14,6 +14,7 @@ import ldif
|
|
|
cb1cc6 |
import ldap
|
|
|
cb1cc6 |
import pytest
|
|
|
cb1cc6 |
import subprocess
|
|
|
cb1cc6 |
+import time
|
|
|
cb1cc6 |
from lib389.idm.user import TEST_USER_PROPERTIES, UserAccounts
|
|
|
cb1cc6 |
from lib389.pwpolicy import PwPolicyManager
|
|
|
cb1cc6 |
from lib389.utils import *
|
|
|
cb1cc6 |
@@ -204,12 +205,12 @@ def rename_entry(server, idx, ou_name, new_parent):
|
|
|
cb1cc6 |
def add_ldapsubentry(server, parent):
|
|
|
cb1cc6 |
pwp = PwPolicyManager(server)
|
|
|
cb1cc6 |
policy_props = {'passwordStorageScheme': 'ssha',
|
|
|
cb1cc6 |
- 'passwordCheckSyntax': 'on',
|
|
|
cb1cc6 |
- 'passwordInHistory': '6',
|
|
|
cb1cc6 |
- 'passwordChange': 'on',
|
|
|
cb1cc6 |
- 'passwordMinAge': '0',
|
|
|
cb1cc6 |
- 'passwordExp': 'off',
|
|
|
cb1cc6 |
- 'passwordMustChange': 'off',}
|
|
|
cb1cc6 |
+ 'passwordCheckSyntax': 'on',
|
|
|
cb1cc6 |
+ 'passwordInHistory': '6',
|
|
|
cb1cc6 |
+ 'passwordChange': 'on',
|
|
|
cb1cc6 |
+ 'passwordMinAge': '0',
|
|
|
cb1cc6 |
+ 'passwordExp': 'off',
|
|
|
cb1cc6 |
+ 'passwordMustChange': 'off',}
|
|
|
cb1cc6 |
log.info('Create password policy for subtree {}'.format(parent))
|
|
|
cb1cc6 |
pwp.create_subtree_policy(parent, policy_props)
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
@@ -742,7 +743,7 @@ def get_keepalive_entries(instance, replica):
|
|
|
cb1cc6 |
try:
|
|
|
cb1cc6 |
entries = instance.search_s(replica.get_suffix(), ldap.SCOPE_ONELEVEL,
|
|
|
cb1cc6 |
"(&(objectclass=ldapsubentry)(cn=repl keep alive*))",
|
|
|
cb1cc6 |
- ['cn', 'nsUniqueId', 'modifierTimestamp'])
|
|
|
cb1cc6 |
+ ['cn', 'keepalivetimestamp', 'nsUniqueId', 'modifierTimestamp'])
|
|
|
cb1cc6 |
except ldap.LDAPError as e:
|
|
|
cb1cc6 |
log.fatal('Failed to retrieve keepalive entry (%s) on instance %s: error %s' % (dn, instance, str(e)))
|
|
|
cb1cc6 |
assert False
|
|
|
cb1cc6 |
@@ -761,6 +762,7 @@ def verify_keepalive_entries(topo, expected):
|
|
|
cb1cc6 |
# (for example after: db2ldif / demote a supplier / ldif2db / init other suppliers)
|
|
|
cb1cc6 |
# ==> if the function is somehow pushed in lib389, a check better than simply counting the entries
|
|
|
cb1cc6 |
# should be done.
|
|
|
cb1cc6 |
+ entries = []
|
|
|
cb1cc6 |
for supplierId in topo.ms:
|
|
|
cb1cc6 |
supplier = topo.ms[supplierId]
|
|
|
cb1cc6 |
for replica in Replicas(supplier).list():
|
|
|
cb1cc6 |
@@ -771,6 +773,7 @@ def verify_keepalive_entries(topo, expected):
|
|
|
cb1cc6 |
keepaliveEntries = get_keepalive_entries(supplier, replica);
|
|
|
cb1cc6 |
expectedCount = len(topo.ms) if expected else 0
|
|
|
cb1cc6 |
foundCount = len(keepaliveEntries)
|
|
|
cb1cc6 |
+ entries += keepaliveEntries
|
|
|
cb1cc6 |
if (foundCount == expectedCount):
|
|
|
cb1cc6 |
log.debug(f'Found {foundCount} keepalive entries as expected on {replica_info}.')
|
|
|
cb1cc6 |
else:
|
|
|
cb1cc6 |
@@ -778,70 +781,45 @@ def verify_keepalive_entries(topo, expected):
|
|
|
cb1cc6 |
f'while {expectedCount} were expected on {replica_info}.')
|
|
|
cb1cc6 |
assert False
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
+ return entries
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
-def test_online_init_should_create_keepalive_entries(topo_m2):
|
|
|
cb1cc6 |
- """Check that keep alive entries are created when initializinf a supplier from another one
|
|
|
cb1cc6 |
+def test_keepalive_entries(topo_m2):
|
|
|
cb1cc6 |
+ """Check that keep alive entries are created
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
:id: d5940e71-d18a-4b71-aaf7-b9185361fffe
|
|
|
cb1cc6 |
:setup: Two suppliers replication setup
|
|
|
cb1cc6 |
:steps:
|
|
|
cb1cc6 |
- 1. Generate ldif without replication data
|
|
|
cb1cc6 |
- 2 Init both suppliers from that ldif
|
|
|
cb1cc6 |
- 3 Check that keep alive entries does not exists
|
|
|
cb1cc6 |
- 4 Perform on line init of supplier2 from supplier1
|
|
|
cb1cc6 |
- 5 Check that keep alive entries exists
|
|
|
cb1cc6 |
+ 1. Keep alives entries are present
|
|
|
cb1cc6 |
+ 2. Keep alive entries are updated every 60 seconds
|
|
|
cb1cc6 |
:expectedresults:
|
|
|
cb1cc6 |
- 1. No error while generating ldif
|
|
|
cb1cc6 |
- 2. No error while importing the ldif file
|
|
|
cb1cc6 |
- 3. No keepalive entrie should exists on any suppliers
|
|
|
cb1cc6 |
- 4. No error while initializing supplier2
|
|
|
cb1cc6 |
- 5. All keepalive entries should exist on every suppliers
|
|
|
cb1cc6 |
+ 1. Success
|
|
|
cb1cc6 |
+ 2. Success
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
"""
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
- repl = ReplicationManager(DEFAULT_SUFFIX)
|
|
|
cb1cc6 |
- m1 = topo_m2.ms["supplier1"]
|
|
|
cb1cc6 |
- m2 = topo_m2.ms["supplier2"]
|
|
|
cb1cc6 |
- # Step 1: Generate ldif without replication data
|
|
|
cb1cc6 |
- m1.stop()
|
|
|
cb1cc6 |
- m2.stop()
|
|
|
cb1cc6 |
- ldif_file = '%s/norepl.ldif' % m1.get_ldif_dir()
|
|
|
cb1cc6 |
- m1.db2ldif(bename=DEFAULT_BENAME, suffixes=[DEFAULT_SUFFIX],
|
|
|
cb1cc6 |
- excludeSuffixes=None, repl_data=False,
|
|
|
cb1cc6 |
- outputfile=ldif_file, encrypt=False)
|
|
|
cb1cc6 |
- # Remove replication metadata that are still in the ldif
|
|
|
cb1cc6 |
- _remove_replication_data(ldif_file)
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
- # Step 2: Init both suppliers from that ldif
|
|
|
cb1cc6 |
- m1.ldif2db(DEFAULT_BENAME, None, None, None, ldif_file)
|
|
|
cb1cc6 |
- m2.ldif2db(DEFAULT_BENAME, None, None, None, ldif_file)
|
|
|
cb1cc6 |
- m1.start()
|
|
|
cb1cc6 |
- m2.start()
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
- """ Replica state is now as if CLI setup has been done using:
|
|
|
cb1cc6 |
- dsconf supplier1 replication enable --suffix "${SUFFIX}" --role supplier
|
|
|
cb1cc6 |
- dsconf supplier2 replication enable --suffix "${SUFFIX}" --role supplier
|
|
|
cb1cc6 |
- dsconf supplier1 replication create-manager --name "${REPLICATION_MANAGER_NAME}" --passwd "${REPLICATION_MANAGER_PASSWORD}"
|
|
|
cb1cc6 |
- dsconf supplier2 replication create-manager --name "${REPLICATION_MANAGER_NAME}" --passwd "${REPLICATION_MANAGER_PASSWORD}"
|
|
|
cb1cc6 |
- dsconf supplier1 repl-agmt create --suffix "${SUFFIX}"
|
|
|
cb1cc6 |
- dsconf supplier2 repl-agmt create --suffix "${SUFFIX}"
|
|
|
cb1cc6 |
- """
|
|
|
cb1cc6 |
+ # default interval is 1 hour, too long for test, set it to the minimum of
|
|
|
cb1cc6 |
+ # 60 seconds
|
|
|
cb1cc6 |
+ for supplierId in topo_m2.ms:
|
|
|
cb1cc6 |
+ supplier = topo_m2.ms[supplierId]
|
|
|
cb1cc6 |
+ replica = Replicas(supplier).get(DEFAULT_SUFFIX)
|
|
|
cb1cc6 |
+ replica.replace('nsds5ReplicaKeepAliveUpdateInterval', '60')
|
|
|
cb1cc6 |
+ supplier.restart()
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
- # Step 3: No keepalive entrie should exists on any suppliers
|
|
|
cb1cc6 |
- verify_keepalive_entries(topo_m2, False)
|
|
|
cb1cc6 |
+ # verify entries exist
|
|
|
cb1cc6 |
+ entries = verify_keepalive_entries(topo_m2, True);
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
- # Step 4: Perform on line init of supplier2 from supplier1
|
|
|
cb1cc6 |
- agmt = Agreements(m1).list()[0]
|
|
|
cb1cc6 |
- agmt.begin_reinit()
|
|
|
cb1cc6 |
- (done, error) = agmt.wait_reinit()
|
|
|
cb1cc6 |
- assert done is True
|
|
|
cb1cc6 |
- assert error is False
|
|
|
cb1cc6 |
+ # Get current time from keep alive entry
|
|
|
cb1cc6 |
+ keep_alive_s1 = str(entries[0].data['keepalivetimestamp'])
|
|
|
cb1cc6 |
+ keep_alive_s2 = str(entries[1].data['keepalivetimestamp'])
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
+ # Wait for event interval (60 secs) to pass
|
|
|
cb1cc6 |
+ time.sleep(61)
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
- # Step 5: All keepalive entries should exists on every suppliers
|
|
|
cb1cc6 |
- # Verify the keep alive entry once replication is in sync
|
|
|
cb1cc6 |
- # (that is the step that fails when bug is not fixed)
|
|
|
cb1cc6 |
- repl.wait_for_ruv(m2,m1)
|
|
|
cb1cc6 |
- verify_keepalive_entries(topo_m2, True);
|
|
|
cb1cc6 |
+ # Check keep alives entries have been updated
|
|
|
cb1cc6 |
+ entries = verify_keepalive_entries(topo_m2, True);
|
|
|
cb1cc6 |
+ assert keep_alive_s1 != str(entries[0].data['keepalivetimestamp'])
|
|
|
cb1cc6 |
+ assert keep_alive_s2 != str(entries[1].data['keepalivetimestamp'])
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
@pytest.mark.ds49915
|
|
|
cb1cc6 |
diff --git a/dirsrvtests/tests/suites/replication/replica_config_test.py b/dirsrvtests/tests/suites/replication/replica_config_test.py
|
|
|
cb1cc6 |
index c2140a2ac..06ae5afcf 100644
|
|
|
cb1cc6 |
--- a/dirsrvtests/tests/suites/replication/replica_config_test.py
|
|
|
cb1cc6 |
+++ b/dirsrvtests/tests/suites/replication/replica_config_test.py
|
|
|
cb1cc6 |
@@ -50,7 +50,8 @@ repl_add_attrs = [('nsDS5ReplicaType', '-1', '4', overflow, notnum, '1'),
|
|
|
cb1cc6 |
('nsds5ReplicaProtocolTimeout', '-1', too_big, overflow, notnum, '1'),
|
|
|
cb1cc6 |
('nsds5ReplicaReleaseTimeout', '-1', too_big, overflow, notnum, '1'),
|
|
|
cb1cc6 |
('nsds5ReplicaBackoffMin', '0', too_big, overflow, notnum, '3'),
|
|
|
cb1cc6 |
- ('nsds5ReplicaBackoffMax', '0', too_big, overflow, notnum, '6')]
|
|
|
cb1cc6 |
+ ('nsds5ReplicaBackoffMax', '0', too_big, overflow, notnum, '6'),
|
|
|
cb1cc6 |
+ ('nsds5ReplicaKeepAliveUpdateInterval', '59', too_big, overflow, notnum, '60'),]
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
repl_mod_attrs = [('nsDS5Flags', '-1', '2', overflow, notnum, '1'),
|
|
|
cb1cc6 |
('nsds5ReplicaPurgeDelay', '-2', too_big, overflow, notnum, '1'),
|
|
|
cb1cc6 |
@@ -59,7 +60,8 @@ repl_mod_attrs = [('nsDS5Flags', '-1', '2', overflow, notnum, '1'),
|
|
|
cb1cc6 |
('nsds5ReplicaProtocolTimeout', '-1', too_big, overflow, notnum, '1'),
|
|
|
cb1cc6 |
('nsds5ReplicaReleaseTimeout', '-1', too_big, overflow, notnum, '1'),
|
|
|
cb1cc6 |
('nsds5ReplicaBackoffMin', '0', too_big, overflow, notnum, '3'),
|
|
|
cb1cc6 |
- ('nsds5ReplicaBackoffMax', '0', too_big, overflow, notnum, '6')]
|
|
|
cb1cc6 |
+ ('nsds5ReplicaBackoffMax', '0', too_big, overflow, notnum, '6'),
|
|
|
cb1cc6 |
+ ('nsds5ReplicaKeepAliveUpdateInterval', '59', too_big, overflow, notnum, '60'),]
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
agmt_attrs = [
|
|
|
cb1cc6 |
('nsds5ReplicaPort', '0', '65535', overflow, notnum, '389'),
|
|
|
cb1cc6 |
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
|
|
|
cb1cc6 |
index 0c73e5114..7a9598730 100644
|
|
|
cb1cc6 |
--- a/ldap/schema/01core389.ldif
|
|
|
cb1cc6 |
+++ b/ldap/schema/01core389.ldif
|
|
|
cb1cc6 |
@@ -327,6 +327,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2371 NAME 'nsDS5ReplicaBootstrapBindDN'
|
|
|
cb1cc6 |
attributeTypes: ( 2.16.840.1.113730.3.1.2372 NAME 'nsDS5ReplicaBootstrapCredentials' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
attributeTypes: ( 2.16.840.1.113730.3.1.2373 NAME 'nsDS5ReplicaBootstrapBindMethod' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
attributeTypes: ( 2.16.840.1.113730.3.1.2374 NAME 'nsDS5ReplicaBootstrapTransportInfo' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
+attributeTypes: ( 2.16.840.1.113730.3.1.2390 NAME 'nsds5ReplicaKeepAliveUpdateInterval' DESC '389 defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN '389 Directory Server' )
|
|
|
cb1cc6 |
#
|
|
|
cb1cc6 |
# objectclasses
|
|
|
cb1cc6 |
#
|
|
|
cb1cc6 |
@@ -336,7 +337,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.44 NAME 'nsIndex' DESC 'Netscape defined
|
|
|
cb1cc6 |
objectClasses: ( 2.16.840.1.113730.3.2.109 NAME 'nsBackendInstance' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
objectClasses: ( 2.16.840.1.113730.3.2.110 NAME 'nsMappingTree' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
objectClasses: ( 2.16.840.1.113730.3.2.104 NAME 'nsContainer' DESC 'Netscape defined objectclass' SUP top MUST ( CN ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
-objectClasses: ( 2.16.840.1.113730.3.2.108 NAME 'nsDS5Replica' DESC 'Replication configuration objectclass' SUP top MUST ( nsDS5ReplicaRoot $ nsDS5ReplicaId ) MAY (cn $ nsds5ReplicaPreciseTombstonePurging $ nsds5ReplicaCleanRUV $ nsds5ReplicaAbortCleanRUV $ nsDS5ReplicaType $ nsDS5ReplicaBindDN $ nsDS5ReplicaBindDNGroup $ nsState $ nsDS5ReplicaName $ nsDS5Flags $ nsDS5Task $ nsDS5ReplicaReferral $ nsDS5ReplicaAutoReferral $ nsds5ReplicaPurgeDelay $ nsds5ReplicaTombstonePurgeInterval $ nsds5ReplicaChangeCount $ nsds5ReplicaLegacyConsumer $ nsds5ReplicaProtocolTimeout $ nsds5ReplicaBackoffMin $ nsds5ReplicaBackoffMax $ nsds5ReplicaReleaseTimeout $ nsDS5ReplicaBindDnGroupCheckInterval ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
+objectClasses: ( 2.16.840.1.113730.3.2.108 NAME 'nsDS5Replica' DESC 'Replication configuration objectclass' SUP top MUST ( nsDS5ReplicaRoot $ nsDS5ReplicaId ) MAY (cn $ nsds5ReplicaPreciseTombstonePurging $ nsds5ReplicaCleanRUV $ nsds5ReplicaAbortCleanRUV $ nsDS5ReplicaType $ nsDS5ReplicaBindDN $ nsDS5ReplicaBindDNGroup $ nsState $ nsDS5ReplicaName $ nsDS5Flags $ nsDS5Task $ nsDS5ReplicaReferral $ nsDS5ReplicaAutoReferral $ nsds5ReplicaPurgeDelay $ nsds5ReplicaTombstonePurgeInterval $ nsds5ReplicaChangeCount $ nsds5ReplicaLegacyConsumer $ nsds5ReplicaProtocolTimeout $ nsds5ReplicaBackoffMin $ nsds5ReplicaBackoffMax $ nsds5ReplicaReleaseTimeout $ nsDS5ReplicaBindDnGroupCheckInterval $ nsds5ReplicaKeepAliveUpdateInterval ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
objectClasses: ( 2.16.840.1.113730.3.2.113 NAME 'nsTombstone' DESC 'Netscape defined objectclass' SUP top MAY ( nstombstonecsn $ nsParentUniqueId $ nscpEntryDN ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsds5ReplicaCleanRUVNotified $ nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5ReplicaEnabled $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5ReplicaStripAttrs $ nsds5replicaSessionPauseTime $ nsds5ReplicaProtocolTimeout $ nsds5ReplicaFlowControlWindow $ nsds5ReplicaFlowControlPause $ nsDS5ReplicaWaitForAsyncResults $ nsds5ReplicaIgnoreMissingChange $ nsDS5ReplicaBootstrapBindDN $ nsDS5ReplicaBootstrapCredentials $ nsDS5ReplicaBootstrapBindMethod $ nsDS5ReplicaBootstrapTransportInfo ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
objectClasses: ( 2.16.840.1.113730.3.2.39 NAME 'nsslapdConfig' DESC 'Netscape defined objectclass' SUP top MAY ( cn ) X-ORIGIN 'Netscape Directory Server' )
|
|
|
cb1cc6 |
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
|
|
|
cb1cc6 |
index 06e747811..c2fbff8c0 100644
|
|
|
cb1cc6 |
--- a/ldap/servers/plugins/replication/repl5.h
|
|
|
cb1cc6 |
+++ b/ldap/servers/plugins/replication/repl5.h
|
|
|
cb1cc6 |
@@ -1,6 +1,6 @@
|
|
|
cb1cc6 |
/** BEGIN COPYRIGHT BLOCK
|
|
|
cb1cc6 |
* Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
|
|
|
cb1cc6 |
- * Copyright (C) 2020 Red Hat, Inc.
|
|
|
cb1cc6 |
+ * Copyright (C) 2022 Red Hat, Inc.
|
|
|
cb1cc6 |
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
|
|
|
cb1cc6 |
* All rights reserved.
|
|
|
cb1cc6 |
*
|
|
|
cb1cc6 |
@@ -120,6 +120,8 @@
|
|
|
cb1cc6 |
#define PROTOCOL_STATUS_TOTAL_SENDING_DATA 711
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
#define DEFAULT_PROTOCOL_TIMEOUT 120
|
|
|
cb1cc6 |
+#define DEFAULT_REPLICA_KEEPALIVE_UPDATE_INTERVAL 3600
|
|
|
cb1cc6 |
+#define REPLICA_KEEPALIVE_UPDATE_INTERVAL_MIN 60
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
/* To Allow Consumer Initialization when adding an agreement - */
|
|
|
cb1cc6 |
#define STATE_PERFORMING_TOTAL_UPDATE 501
|
|
|
cb1cc6 |
@@ -162,6 +164,7 @@ extern const char *type_nsds5ReplicaBootstrapBindDN;
|
|
|
cb1cc6 |
extern const char *type_nsds5ReplicaBootstrapCredentials;
|
|
|
cb1cc6 |
extern const char *type_nsds5ReplicaBootstrapBindMethod;
|
|
|
cb1cc6 |
extern const char *type_nsds5ReplicaBootstrapTransportInfo;
|
|
|
cb1cc6 |
+extern const char *type_replicaKeepAliveUpdateInterval;
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
/* Attribute names for windows replication agreements */
|
|
|
cb1cc6 |
extern const char *type_nsds7WindowsReplicaArea;
|
|
|
cb1cc6 |
@@ -677,8 +680,8 @@ Replica *windows_replica_new(const Slapi_DN *root);
|
|
|
cb1cc6 |
during addition of the replica over LDAP */
|
|
|
cb1cc6 |
int replica_new_from_entry(Slapi_Entry *e, char *errortext, PRBool is_add_operation, Replica **r);
|
|
|
cb1cc6 |
void replica_destroy(void **arg);
|
|
|
cb1cc6 |
-int replica_subentry_update(Slapi_DN *repl_root, ReplicaId rid);
|
|
|
cb1cc6 |
-int replica_subentry_check(Slapi_DN *repl_root, ReplicaId rid);
|
|
|
cb1cc6 |
+void replica_subentry_update(time_t when, void *arg);
|
|
|
cb1cc6 |
+int replica_subentry_check(const char *repl_root, ReplicaId rid);
|
|
|
cb1cc6 |
PRBool replica_get_exclusive_access(Replica *r, PRBool *isInc, uint64_t connid, int opid, const char *locking_purl, char **current_purl);
|
|
|
cb1cc6 |
void replica_relinquish_exclusive_access(Replica *r, uint64_t connid, int opid);
|
|
|
cb1cc6 |
PRBool replica_get_tombstone_reap_active(const Replica *r);
|
|
|
cb1cc6 |
@@ -739,6 +742,8 @@ void consumer5_set_mapping_tree_state_for_replica(const Replica *r, RUV *supplie
|
|
|
cb1cc6 |
Replica *replica_get_for_backend(const char *be_name);
|
|
|
cb1cc6 |
void replica_set_purge_delay(Replica *r, uint32_t purge_delay);
|
|
|
cb1cc6 |
void replica_set_tombstone_reap_interval(Replica *r, long interval);
|
|
|
cb1cc6 |
+void replica_set_keepalive_update_interval(Replica *r, int64_t interval);
|
|
|
cb1cc6 |
+int64_t replica_get_keepalive_update_interval(Replica *r);
|
|
|
cb1cc6 |
void replica_update_ruv_consumer(Replica *r, RUV *supplier_ruv);
|
|
|
cb1cc6 |
Slapi_Entry *get_in_memory_ruv(Slapi_DN *suffix_sdn);
|
|
|
cb1cc6 |
int replica_write_ruv(Replica *r);
|
|
|
cb1cc6 |
diff --git a/ldap/servers/plugins/replication/repl5_inc_protocol.c b/ldap/servers/plugins/replication/repl5_inc_protocol.c
|
|
|
cb1cc6 |
index 4bb384882..846951b9e 100644
|
|
|
cb1cc6 |
--- a/ldap/servers/plugins/replication/repl5_inc_protocol.c
|
|
|
cb1cc6 |
+++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c
|
|
|
cb1cc6 |
@@ -1,6 +1,6 @@
|
|
|
cb1cc6 |
/** BEGIN COPYRIGHT BLOCK
|
|
|
cb1cc6 |
* Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
|
|
|
cb1cc6 |
- * Copyright (C) 2020 Red Hat, Inc.
|
|
|
cb1cc6 |
+ * Copyright (C) 2022 Red Hat, Inc.
|
|
|
cb1cc6 |
* All rights reserved.
|
|
|
cb1cc6 |
*
|
|
|
cb1cc6 |
* License: GPL (version 3 or any later version).
|
|
|
cb1cc6 |
@@ -1677,13 +1677,9 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
|
|
|
cb1cc6 |
} else {
|
|
|
cb1cc6 |
ConnResult replay_crc;
|
|
|
cb1cc6 |
Replica *replica = prp->replica;
|
|
|
cb1cc6 |
- PRBool subentry_update_needed = PR_FALSE;
|
|
|
cb1cc6 |
PRUint64 release_timeout = replica_get_release_timeout(replica);
|
|
|
cb1cc6 |
char csn_str[CSN_STRSIZE];
|
|
|
cb1cc6 |
- int skipped_updates = 0;
|
|
|
cb1cc6 |
- int fractional_repl;
|
|
|
cb1cc6 |
int finished = 0;
|
|
|
cb1cc6 |
-#define FRACTIONAL_SKIPPED_THRESHOLD 100
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
/* Start the results reading thread */
|
|
|
cb1cc6 |
rd = repl5_inc_rd_new(prp);
|
|
|
cb1cc6 |
@@ -1700,7 +1696,6 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
memset((void *)&op, 0, sizeof(op));
|
|
|
cb1cc6 |
entry.op = &op;
|
|
|
cb1cc6 |
- fractional_repl = agmt_is_fractional(prp->agmt);
|
|
|
cb1cc6 |
do {
|
|
|
cb1cc6 |
cl5_operation_parameters_done(entry.op);
|
|
|
cb1cc6 |
memset((void *)entry.op, 0, sizeof(op));
|
|
|
cb1cc6 |
@@ -1781,14 +1776,6 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
|
|
|
cb1cc6 |
replica_id = csn_get_replicaid(entry.op->csn);
|
|
|
cb1cc6 |
uniqueid = entry.op->target_address.uniqueid;
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
- if (fractional_repl && message_id) {
|
|
|
cb1cc6 |
- /* This update was sent no need to update the subentry
|
|
|
cb1cc6 |
- * and restart counting the skipped updates
|
|
|
cb1cc6 |
- */
|
|
|
cb1cc6 |
- subentry_update_needed = PR_FALSE;
|
|
|
cb1cc6 |
- skipped_updates = 0;
|
|
|
cb1cc6 |
- }
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
if (prp->repl50consumer && message_id) {
|
|
|
cb1cc6 |
int operation, error = 0;
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
@@ -1816,15 +1803,6 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
|
|
|
cb1cc6 |
agmt_get_long_name(prp->agmt),
|
|
|
cb1cc6 |
entry.op->target_address.uniqueid, csn_str);
|
|
|
cb1cc6 |
agmt_inc_last_update_changecount(prp->agmt, csn_get_replicaid(entry.op->csn), 1 /*skipped*/);
|
|
|
cb1cc6 |
- if (fractional_repl) {
|
|
|
cb1cc6 |
- skipped_updates++;
|
|
|
cb1cc6 |
- if (skipped_updates > FRACTIONAL_SKIPPED_THRESHOLD) {
|
|
|
cb1cc6 |
- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
|
|
|
cb1cc6 |
- "send_updates - %s: skipped updates is too high (%d) if no other update is sent we will update the subentry\n",
|
|
|
cb1cc6 |
- agmt_get_long_name(prp->agmt), skipped_updates);
|
|
|
cb1cc6 |
- subentry_update_needed = PR_TRUE;
|
|
|
cb1cc6 |
- }
|
|
|
cb1cc6 |
- }
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
break;
|
|
|
cb1cc6 |
@@ -1906,26 +1884,6 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
|
|
|
cb1cc6 |
PR_Unlock(rd->lock);
|
|
|
cb1cc6 |
} while (!finished);
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
- if (fractional_repl && subentry_update_needed) {
|
|
|
cb1cc6 |
- ReplicaId rid = -1; /* Used to create the replica keep alive subentry */
|
|
|
cb1cc6 |
- Slapi_DN *replarea_sdn = NULL;
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
- if (replica) {
|
|
|
cb1cc6 |
- rid = replica_get_rid(replica);
|
|
|
cb1cc6 |
- }
|
|
|
cb1cc6 |
- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
|
|
|
cb1cc6 |
- "send_updates - %s: skipped updates was definitely too high (%d) update the subentry now\n",
|
|
|
cb1cc6 |
- agmt_get_long_name(prp->agmt), skipped_updates);
|
|
|
cb1cc6 |
- replarea_sdn = agmt_get_replarea(prp->agmt);
|
|
|
cb1cc6 |
- if (!replarea_sdn) {
|
|
|
cb1cc6 |
- slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name,
|
|
|
cb1cc6 |
- "send_updates - Unknown replication area due to agreement not found.");
|
|
|
cb1cc6 |
- agmt_set_last_update_status(prp->agmt, 0, -1, "Agreement is corrupted: missing suffix");
|
|
|
cb1cc6 |
- return_value = UPDATE_FATAL_ERROR;
|
|
|
cb1cc6 |
- } else {
|
|
|
cb1cc6 |
- replica_subentry_update(replarea_sdn, rid);
|
|
|
cb1cc6 |
- }
|
|
|
cb1cc6 |
- }
|
|
|
cb1cc6 |
/* Terminate the results reading thread */
|
|
|
cb1cc6 |
if (!prp->repl50consumer) {
|
|
|
cb1cc6 |
/* We need to ensure that we wait until all the responses have been received from our operations */
|
|
|
cb1cc6 |
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
|
|
|
cb1cc6 |
index 3bd57647f..ded4cf754 100644
|
|
|
cb1cc6 |
--- a/ldap/servers/plugins/replication/repl5_replica.c
|
|
|
cb1cc6 |
+++ b/ldap/servers/plugins/replication/repl5_replica.c
|
|
|
cb1cc6 |
@@ -1,6 +1,6 @@
|
|
|
cb1cc6 |
/** BEGIN COPYRIGHT BLOCK
|
|
|
cb1cc6 |
* Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
|
|
|
cb1cc6 |
- * Copyright (C) 2005 Red Hat, Inc.
|
|
|
cb1cc6 |
+ * Copyright (C) 2022 Red Hat, Inc.
|
|
|
cb1cc6 |
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
|
|
|
cb1cc6 |
* All rights reserved.
|
|
|
cb1cc6 |
*
|
|
|
cb1cc6 |
@@ -22,7 +22,6 @@
|
|
|
cb1cc6 |
#include "slap.h"
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
#define RUV_SAVE_INTERVAL (30 * 1000) /* 30 seconds */
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
#define REPLICA_RDN "cn=replica"
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
/*
|
|
|
cb1cc6 |
@@ -48,6 +47,7 @@ struct replica
|
|
|
cb1cc6 |
PRMonitor *repl_lock; /* protects entire structure */
|
|
|
cb1cc6 |
Slapi_Eq_Context repl_eqcxt_rs; /* context to cancel event that saves ruv */
|
|
|
cb1cc6 |
Slapi_Eq_Context repl_eqcxt_tr; /* context to cancel event that reaps tombstones */
|
|
|
cb1cc6 |
+ Slapi_Eq_Context repl_eqcxt_ka_update; /* keep-alive entry update event */
|
|
|
cb1cc6 |
Object *repl_csngen; /* CSN generator for this replica */
|
|
|
cb1cc6 |
PRBool repl_csn_assigned; /* Flag set when new csn is assigned. */
|
|
|
cb1cc6 |
int64_t repl_purge_delay; /* When purgeable, CSNs are held on to for this many extra seconds */
|
|
|
cb1cc6 |
@@ -66,6 +66,7 @@ struct replica
|
|
|
cb1cc6 |
uint64_t agmt_count; /* Number of agmts */
|
|
|
cb1cc6 |
Slapi_Counter *release_timeout; /* The amount of time to wait before releasing active replica */
|
|
|
cb1cc6 |
uint64_t abort_session; /* Abort the current replica session */
|
|
|
cb1cc6 |
+ int64_t keepalive_update_interval; /* interval to do dummy update to keep RUV fresh */)
|
|
|
cb1cc6 |
};
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
@@ -133,8 +134,8 @@ replica_new(const Slapi_DN *root)
|
|
|
cb1cc6 |
&r);
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
if (NULL == r) {
|
|
|
cb1cc6 |
- slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "replica_new - "
|
|
|
cb1cc6 |
- "Unable to configure replica %s: %s\n",
|
|
|
cb1cc6 |
+ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name,
|
|
|
cb1cc6 |
+ "replica_new - Unable to configure replica %s: %s\n",
|
|
|
cb1cc6 |
slapi_sdn_get_dn(root), errorbuf);
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
slapi_entry_free(e);
|
|
|
cb1cc6 |
@@ -232,7 +233,15 @@ replica_new_from_entry(Slapi_Entry *e, char *errortext, PRBool is_add_operation,
|
|
|
cb1cc6 |
In that case the updated would fail but nothing bad would happen. The next
|
|
|
cb1cc6 |
scheduled update would save the state */
|
|
|
cb1cc6 |
r->repl_eqcxt_rs = slapi_eq_repeat_rel(replica_update_state, r->repl_name,
|
|
|
cb1cc6 |
- slapi_current_rel_time_t() + START_UPDATE_DELAY, RUV_SAVE_INTERVAL);
|
|
|
cb1cc6 |
+ slapi_current_rel_time_t() + START_UPDATE_DELAY,
|
|
|
cb1cc6 |
+ RUV_SAVE_INTERVAL);
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
+ /* create supplier update event */
|
|
|
cb1cc6 |
+ if (r->repl_eqcxt_ka_update == NULL && replica_get_type(r) == REPLICA_TYPE_UPDATABLE) {
|
|
|
cb1cc6 |
+ r->repl_eqcxt_ka_update = slapi_eq_repeat_rel(replica_subentry_update, r,
|
|
|
cb1cc6 |
+ slapi_current_rel_time_t() + START_UPDATE_DELAY,
|
|
|
cb1cc6 |
+ replica_get_keepalive_update_interval(r));
|
|
|
cb1cc6 |
+ }
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
if (r->tombstone_reap_interval > 0) {
|
|
|
cb1cc6 |
/*
|
|
|
cb1cc6 |
@@ -302,6 +311,11 @@ replica_destroy(void **arg)
|
|
|
cb1cc6 |
* and ruv updates.
|
|
|
cb1cc6 |
*/
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
+ if (r->repl_eqcxt_ka_update) {
|
|
|
cb1cc6 |
+ slapi_eq_cancel_rel(r->repl_eqcxt_ka_update);
|
|
|
cb1cc6 |
+ r->repl_eqcxt_ka_update = NULL;
|
|
|
cb1cc6 |
+ }
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
if (r->repl_eqcxt_rs) {
|
|
|
cb1cc6 |
slapi_eq_cancel_rel(r->repl_eqcxt_rs);
|
|
|
cb1cc6 |
r->repl_eqcxt_rs = NULL;
|
|
|
cb1cc6 |
@@ -393,7 +407,7 @@ replica_destroy(void **arg)
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
static int
|
|
|
cb1cc6 |
-replica_subentry_create(Slapi_DN *repl_root, ReplicaId rid)
|
|
|
cb1cc6 |
+replica_subentry_create(const char *repl_root, ReplicaId rid)
|
|
|
cb1cc6 |
{
|
|
|
cb1cc6 |
char *entry_string = NULL;
|
|
|
cb1cc6 |
Slapi_Entry *e = NULL;
|
|
|
cb1cc6 |
@@ -402,7 +416,7 @@ replica_subentry_create(Slapi_DN *repl_root, ReplicaId rid)
|
|
|
cb1cc6 |
int rc = 0;
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
entry_string = slapi_ch_smprintf("dn: cn=%s %d,%s\nobjectclass: top\nobjectclass: ldapsubentry\nobjectclass: extensibleObject\ncn: %s %d",
|
|
|
cb1cc6 |
- KEEP_ALIVE_ENTRY, rid, slapi_sdn_get_dn(repl_root), KEEP_ALIVE_ENTRY, rid);
|
|
|
cb1cc6 |
+ KEEP_ALIVE_ENTRY, rid, repl_root, KEEP_ALIVE_ENTRY, rid);
|
|
|
cb1cc6 |
if (entry_string == NULL) {
|
|
|
cb1cc6 |
slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name,
|
|
|
cb1cc6 |
"replica_subentry_create - Failed in slapi_ch_smprintf\n");
|
|
|
cb1cc6 |
@@ -441,7 +455,7 @@ done:
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
int
|
|
|
cb1cc6 |
-replica_subentry_check(Slapi_DN *repl_root, ReplicaId rid)
|
|
|
cb1cc6 |
+replica_subentry_check(const char *repl_root, ReplicaId rid)
|
|
|
cb1cc6 |
{
|
|
|
cb1cc6 |
Slapi_PBlock *pb;
|
|
|
cb1cc6 |
char *filter = NULL;
|
|
|
cb1cc6 |
@@ -451,7 +465,7 @@ replica_subentry_check(Slapi_DN *repl_root, ReplicaId rid)
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
pb = slapi_pblock_new();
|
|
|
cb1cc6 |
filter = slapi_ch_smprintf("(&(objectclass=ldapsubentry)(cn=%s %d))", KEEP_ALIVE_ENTRY, rid);
|
|
|
cb1cc6 |
- slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(repl_root), LDAP_SCOPE_ONELEVEL,
|
|
|
cb1cc6 |
+ slapi_search_internal_set_pb(pb, repl_root, LDAP_SCOPE_ONELEVEL,
|
|
|
cb1cc6 |
filter, NULL, 0, NULL, NULL,
|
|
|
cb1cc6 |
repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
|
|
|
cb1cc6 |
slapi_search_internal_pb(pb);
|
|
|
cb1cc6 |
@@ -460,17 +474,19 @@ replica_subentry_check(Slapi_DN *repl_root, ReplicaId rid)
|
|
|
cb1cc6 |
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
|
|
cb1cc6 |
if (entries && (entries[0] == NULL)) {
|
|
|
cb1cc6 |
slapi_log_err(SLAPI_LOG_NOTICE, repl_plugin_name,
|
|
|
cb1cc6 |
- "replica_subentry_check - Need to create replication keep alive entry <cn=%s %d,%s>\n", KEEP_ALIVE_ENTRY, rid, slapi_sdn_get_dn(repl_root));
|
|
|
cb1cc6 |
+ "replica_subentry_check - Need to create replication keep alive entry <cn=%s %d,%s>\n",
|
|
|
cb1cc6 |
+ KEEP_ALIVE_ENTRY, rid, repl_root);
|
|
|
cb1cc6 |
rc = replica_subentry_create(repl_root, rid);
|
|
|
cb1cc6 |
} else {
|
|
|
cb1cc6 |
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
|
|
|
cb1cc6 |
- "replica_subentry_check - replication keep alive entry <cn=%s %d,%s> already exists\n", KEEP_ALIVE_ENTRY, rid, slapi_sdn_get_dn(repl_root));
|
|
|
cb1cc6 |
+ "replica_subentry_check - replication keep alive entry <cn=%s %d,%s> already exists\n",
|
|
|
cb1cc6 |
+ KEEP_ALIVE_ENTRY, rid, repl_root);
|
|
|
cb1cc6 |
rc = 0;
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
} else {
|
|
|
cb1cc6 |
slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name,
|
|
|
cb1cc6 |
"replica_subentry_check - Error accessing replication keep alive entry <cn=%s %d,%s> res=%d\n",
|
|
|
cb1cc6 |
- KEEP_ALIVE_ENTRY, rid, slapi_sdn_get_dn(repl_root), res);
|
|
|
cb1cc6 |
+ KEEP_ALIVE_ENTRY, rid, repl_root, res);
|
|
|
cb1cc6 |
/* The status of the entry is not clear, do not attempt to create it */
|
|
|
cb1cc6 |
rc = 1;
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
@@ -481,60 +497,59 @@ replica_subentry_check(Slapi_DN *repl_root, ReplicaId rid)
|
|
|
cb1cc6 |
return rc;
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
-int
|
|
|
cb1cc6 |
-replica_subentry_update(Slapi_DN *repl_root, ReplicaId rid)
|
|
|
cb1cc6 |
+void
|
|
|
cb1cc6 |
+replica_subentry_update(time_t when __attribute__((unused)), void *arg)
|
|
|
cb1cc6 |
{
|
|
|
cb1cc6 |
- int ldrc;
|
|
|
cb1cc6 |
- int rc = LDAP_SUCCESS; /* Optimistic default */
|
|
|
cb1cc6 |
+ Slapi_PBlock *modpb = NULL;
|
|
|
cb1cc6 |
+ Replica *replica = (Replica *)arg;
|
|
|
cb1cc6 |
+ ReplicaId rid;
|
|
|
cb1cc6 |
LDAPMod *mods[2];
|
|
|
cb1cc6 |
LDAPMod mod;
|
|
|
cb1cc6 |
struct berval *vals[2];
|
|
|
cb1cc6 |
- char buf[SLAPI_TIMESTAMP_BUFSIZE];
|
|
|
cb1cc6 |
struct berval val;
|
|
|
cb1cc6 |
- Slapi_PBlock *modpb = NULL;
|
|
|
cb1cc6 |
- char *dn;
|
|
|
cb1cc6 |
+ const char *repl_root = NULL;
|
|
|
cb1cc6 |
+ char buf[SLAPI_TIMESTAMP_BUFSIZE];
|
|
|
cb1cc6 |
+ char *dn = NULL;
|
|
|
cb1cc6 |
+ int ldrc = 0;
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
+ rid = replica_get_rid(replica);
|
|
|
cb1cc6 |
+ repl_root = slapi_ch_strdup(slapi_sdn_get_dn(replica_get_root(replica)));
|
|
|
cb1cc6 |
replica_subentry_check(repl_root, rid);
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
slapi_timestamp_utc_hr(buf, SLAPI_TIMESTAMP_BUFSIZE);
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
- slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "subentry_update called at %s\n", buf);
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
+ slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "replica_subentry_update called at %s\n", buf);
|
|
|
cb1cc6 |
val.bv_val = buf;
|
|
|
cb1cc6 |
val.bv_len = strlen(val.bv_val);
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
vals[0] = &val;
|
|
|
cb1cc6 |
vals[1] = NULL;
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
mod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
|
|
|
cb1cc6 |
mod.mod_type = KEEP_ALIVE_ATTR;
|
|
|
cb1cc6 |
mod.mod_bvalues = vals;
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
mods[0] = &mod;
|
|
|
cb1cc6 |
mods[1] = NULL;
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
modpb = slapi_pblock_new();
|
|
|
cb1cc6 |
- dn = slapi_ch_smprintf(KEEP_ALIVE_DN_FORMAT, KEEP_ALIVE_ENTRY, rid, slapi_sdn_get_dn(repl_root));
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
+ dn = slapi_ch_smprintf(KEEP_ALIVE_DN_FORMAT, KEEP_ALIVE_ENTRY, rid, repl_root);
|
|
|
cb1cc6 |
slapi_modify_internal_set_pb(modpb, dn, mods, NULL, NULL,
|
|
|
cb1cc6 |
repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
|
|
|
cb1cc6 |
slapi_modify_internal_pb(modpb);
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
slapi_pblock_get(modpb, SLAPI_PLUGIN_INTOP_RESULT, &ldrc;;
|
|
|
cb1cc6 |
-
|
|
|
cb1cc6 |
if (ldrc != LDAP_SUCCESS) {
|
|
|
cb1cc6 |
slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
|
|
|
cb1cc6 |
- "Failure (%d) to update replication keep alive entry \"%s: %s\"\n", ldrc, KEEP_ALIVE_ATTR, buf);
|
|
|
cb1cc6 |
- rc = ldrc;
|
|
|
cb1cc6 |
+ "replica_subentry_update - "
|
|
|
cb1cc6 |
+ "Failure (%d) to update replication keep alive entry \"%s: %s\"\n",
|
|
|
cb1cc6 |
+ ldrc, KEEP_ALIVE_ATTR, buf);
|
|
|
cb1cc6 |
} else {
|
|
|
cb1cc6 |
slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name,
|
|
|
cb1cc6 |
- "Successful update of replication keep alive entry \"%s: %s\"\n", KEEP_ALIVE_ATTR, buf);
|
|
|
cb1cc6 |
+ "replica_subentry_update - "
|
|
|
cb1cc6 |
+ "Successful update of replication keep alive entry \"%s: %s\"\n",
|
|
|
cb1cc6 |
+ KEEP_ALIVE_ATTR, buf);
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
slapi_pblock_destroy(modpb);
|
|
|
cb1cc6 |
+ slapi_ch_free_string((char **)&repl_root);
|
|
|
cb1cc6 |
slapi_ch_free_string(&dn;;
|
|
|
cb1cc6 |
- return rc;
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
/*
|
|
|
cb1cc6 |
* Attempt to obtain exclusive access to replica (advisory only)
|
|
|
cb1cc6 |
@@ -1512,7 +1527,15 @@ replica_set_enabled(Replica *r, PRBool enable)
|
|
|
cb1cc6 |
if (r->repl_eqcxt_rs == NULL) /* event is not already registered */
|
|
|
cb1cc6 |
{
|
|
|
cb1cc6 |
r->repl_eqcxt_rs = slapi_eq_repeat_rel(replica_update_state, r->repl_name,
|
|
|
cb1cc6 |
- slapi_current_rel_time_t() + START_UPDATE_DELAY, RUV_SAVE_INTERVAL);
|
|
|
cb1cc6 |
+ slapi_current_rel_time_t() + START_UPDATE_DELAY,
|
|
|
cb1cc6 |
+ RUV_SAVE_INTERVAL);
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
+ }
|
|
|
cb1cc6 |
+ /* create supplier update event */
|
|
|
cb1cc6 |
+ if (r->repl_eqcxt_ka_update == NULL && replica_get_type(r) == REPLICA_TYPE_UPDATABLE) {
|
|
|
cb1cc6 |
+ r->repl_eqcxt_ka_update = slapi_eq_repeat_rel(replica_subentry_update, r,
|
|
|
cb1cc6 |
+ slapi_current_rel_time_t() + START_UPDATE_DELAY,
|
|
|
cb1cc6 |
+ replica_get_keepalive_update_interval(r));
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
} else /* disable */
|
|
|
cb1cc6 |
{
|
|
|
cb1cc6 |
@@ -1521,6 +1544,11 @@ replica_set_enabled(Replica *r, PRBool enable)
|
|
|
cb1cc6 |
slapi_eq_cancel_rel(r->repl_eqcxt_rs);
|
|
|
cb1cc6 |
r->repl_eqcxt_rs = NULL;
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
+ /* Remove supplier update event */
|
|
|
cb1cc6 |
+ if (replica_get_type(r) == REPLICA_TYPE_PRIMARY) {
|
|
|
cb1cc6 |
+ slapi_eq_cancel_rel(r->repl_eqcxt_ka_update);
|
|
|
cb1cc6 |
+ r->repl_eqcxt_ka_update = NULL;
|
|
|
cb1cc6 |
+ }
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
replica_unlock(r->repl_lock);
|
|
|
cb1cc6 |
@@ -2119,6 +2147,17 @@ _replica_init_from_config(Replica *r, Slapi_Entry *e, char *errortext)
|
|
|
cb1cc6 |
r->tombstone_reap_interval = 3600 * 24; /* One week, in seconds */
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
+ if ((val = (char*)slapi_entry_attr_get_ref(e, type_replicaKeepAliveUpdateInterval))) {
|
|
|
cb1cc6 |
+ if (repl_config_valid_num(type_replicaKeepAliveUpdateInterval, val, REPLICA_KEEPALIVE_UPDATE_INTERVAL_MIN,
|
|
|
cb1cc6 |
+ INT_MAX, &rc, errormsg, &interval) != 0)
|
|
|
cb1cc6 |
+ {
|
|
|
cb1cc6 |
+ return LDAP_UNWILLING_TO_PERFORM;
|
|
|
cb1cc6 |
+ }
|
|
|
cb1cc6 |
+ r->keepalive_update_interval = interval;
|
|
|
cb1cc6 |
+ } else {
|
|
|
cb1cc6 |
+ r->keepalive_update_interval = DEFAULT_REPLICA_KEEPALIVE_UPDATE_INTERVAL;
|
|
|
cb1cc6 |
+ }
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
r->tombstone_reap_stop = r->tombstone_reap_active = PR_FALSE;
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
/* No supplier holding the replica */
|
|
|
cb1cc6 |
@@ -3646,6 +3685,26 @@ replica_set_tombstone_reap_interval(Replica *r, long interval)
|
|
|
cb1cc6 |
replica_unlock(r->repl_lock);
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
+void
|
|
|
cb1cc6 |
+replica_set_keepalive_update_interval(Replica *r, int64_t interval)
|
|
|
cb1cc6 |
+{
|
|
|
cb1cc6 |
+ replica_lock(r->repl_lock);
|
|
|
cb1cc6 |
+ r->keepalive_update_interval = interval;
|
|
|
cb1cc6 |
+ replica_unlock(r->repl_lock);
|
|
|
cb1cc6 |
+}
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
+int64_t
|
|
|
cb1cc6 |
+replica_get_keepalive_update_interval(Replica *r)
|
|
|
cb1cc6 |
+{
|
|
|
cb1cc6 |
+ int64_t interval = DEFAULT_REPLICA_KEEPALIVE_UPDATE_INTERVAL;
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
+ replica_lock(r->repl_lock);
|
|
|
cb1cc6 |
+ interval = r->keepalive_update_interval;
|
|
|
cb1cc6 |
+ replica_unlock(r->repl_lock);
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
+ return interval;
|
|
|
cb1cc6 |
+}
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
static void
|
|
|
cb1cc6 |
replica_strip_cleaned_rids(Replica *r)
|
|
|
cb1cc6 |
{
|
|
|
cb1cc6 |
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
|
|
|
cb1cc6 |
index 2c6d74b13..aea2cf506 100644
|
|
|
cb1cc6 |
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
|
|
|
cb1cc6 |
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
|
|
|
cb1cc6 |
@@ -438,6 +438,9 @@ replica_config_modify(Slapi_PBlock *pb,
|
|
|
cb1cc6 |
} else if (strcasecmp(config_attr, type_replicaBackoffMax) == 0) {
|
|
|
cb1cc6 |
if (apply_mods)
|
|
|
cb1cc6 |
replica_set_backoff_max(r, PROTOCOL_BACKOFF_MAXIMUM);
|
|
|
cb1cc6 |
+ } else if (strcasecmp(config_attr, type_replicaKeepAliveUpdateInterval) == 0) {
|
|
|
cb1cc6 |
+ if (apply_mods)
|
|
|
cb1cc6 |
+ replica_set_keepalive_update_interval(r, DEFAULT_REPLICA_KEEPALIVE_UPDATE_INTERVAL);
|
|
|
cb1cc6 |
} else if (strcasecmp(config_attr, type_replicaPrecisePurge) == 0) {
|
|
|
cb1cc6 |
if (apply_mods)
|
|
|
cb1cc6 |
replica_set_precise_purging(r, 0);
|
|
|
cb1cc6 |
@@ -472,6 +475,15 @@ replica_config_modify(Slapi_PBlock *pb,
|
|
|
cb1cc6 |
} else {
|
|
|
cb1cc6 |
break;
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
+ } else if (strcasecmp(config_attr, type_replicaKeepAliveUpdateInterval) == 0) {
|
|
|
cb1cc6 |
+ int64_t interval = DEFAULT_REPLICA_KEEPALIVE_UPDATE_INTERVAL;
|
|
|
cb1cc6 |
+ if (repl_config_valid_num(config_attr, config_attr_value, REPLICA_KEEPALIVE_UPDATE_INTERVAL_MIN,
|
|
|
cb1cc6 |
+ INT_MAX, returncode, errortext, &interval) == 0)
|
|
|
cb1cc6 |
+ {
|
|
|
cb1cc6 |
+ replica_set_keepalive_update_interval(r, interval);
|
|
|
cb1cc6 |
+ } else {
|
|
|
cb1cc6 |
+ break;
|
|
|
cb1cc6 |
+ }
|
|
|
cb1cc6 |
} else if (strcasecmp(config_attr, attr_replicaType) == 0) {
|
|
|
cb1cc6 |
int64_t rtype;
|
|
|
cb1cc6 |
slapi_ch_free_string(&new_repl_type);
|
|
|
cb1cc6 |
diff --git a/ldap/servers/plugins/replication/repl5_tot_protocol.c b/ldap/servers/plugins/replication/repl5_tot_protocol.c
|
|
|
cb1cc6 |
index f67263c3e..4b2064912 100644
|
|
|
cb1cc6 |
--- a/ldap/servers/plugins/replication/repl5_tot_protocol.c
|
|
|
cb1cc6 |
+++ b/ldap/servers/plugins/replication/repl5_tot_protocol.c
|
|
|
cb1cc6 |
@@ -510,7 +510,7 @@ retry:
|
|
|
cb1cc6 |
if (prp->replica) {
|
|
|
cb1cc6 |
rid = replica_get_rid(prp->replica);
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
- replica_subentry_check(area_sdn, rid);
|
|
|
cb1cc6 |
+ replica_subentry_check(slapi_sdn_get_dn(area_sdn), rid);
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
/* Send the subtree of the suffix in the order of parentid index plus ldapsubentry and nstombstone. */
|
|
|
cb1cc6 |
check_suffix_entryID(be, suffix);
|
|
|
cb1cc6 |
@@ -531,7 +531,7 @@ retry:
|
|
|
cb1cc6 |
if (prp->replica) {
|
|
|
cb1cc6 |
rid = replica_get_rid(prp->replica);
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
- replica_subentry_check(area_sdn, rid);
|
|
|
cb1cc6 |
+ replica_subentry_check(slapi_sdn_get_dn(area_sdn), rid);
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
slapi_search_internal_set_pb(pb, slapi_sdn_get_dn(area_sdn),
|
|
|
cb1cc6 |
LDAP_SCOPE_SUBTREE, "(|(objectclass=ldapsubentry)(objectclass=nstombstone)(nsuniqueid=*))", NULL, 0, ctrls, NULL,
|
|
|
cb1cc6 |
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
|
|
|
cb1cc6 |
index ef2025dd9..8b178610b 100644
|
|
|
cb1cc6 |
--- a/ldap/servers/plugins/replication/repl_extop.c
|
|
|
cb1cc6 |
+++ b/ldap/servers/plugins/replication/repl_extop.c
|
|
|
cb1cc6 |
@@ -1176,7 +1176,7 @@ multimaster_extop_EndNSDS50ReplicationRequest(Slapi_PBlock *pb)
|
|
|
cb1cc6 |
/* now that the changelog is open and started, we can alos cretae the
|
|
|
cb1cc6 |
* keep alive entry without risk that db and cl will not match
|
|
|
cb1cc6 |
*/
|
|
|
cb1cc6 |
- replica_subentry_check((Slapi_DN *)replica_get_root(r), replica_get_rid(r));
|
|
|
cb1cc6 |
+ replica_subentry_check(slapi_sdn_get_dn(replica_get_root(r)), replica_get_rid(r));
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
/* ONREPL code that dealt with new RUV, etc was moved into the code
|
|
|
cb1cc6 |
diff --git a/ldap/servers/plugins/replication/repl_globals.c b/ldap/servers/plugins/replication/repl_globals.c
|
|
|
cb1cc6 |
index 000777fdd..797ca957f 100644
|
|
|
cb1cc6 |
--- a/ldap/servers/plugins/replication/repl_globals.c
|
|
|
cb1cc6 |
+++ b/ldap/servers/plugins/replication/repl_globals.c
|
|
|
cb1cc6 |
@@ -89,6 +89,7 @@ const char *type_replicaReleaseTimeout = "nsds5ReplicaReleaseTimeout";
|
|
|
cb1cc6 |
const char *type_replicaBackoffMin = "nsds5ReplicaBackoffMin";
|
|
|
cb1cc6 |
const char *type_replicaBackoffMax = "nsds5ReplicaBackoffMax";
|
|
|
cb1cc6 |
const char *type_replicaPrecisePurge = "nsds5ReplicaPreciseTombstonePurging";
|
|
|
cb1cc6 |
+const char *type_replicaKeepAliveUpdateInterval = "nsds5ReplicaKeepAliveUpdateInterval";
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
/* Attribute names for replication agreement attributes */
|
|
|
cb1cc6 |
const char *type_nsds5ReplicaHost = "nsds5ReplicaHost";
|
|
|
cb1cc6 |
diff --git a/src/cockpit/389-console/src/lib/replication/replConfig.jsx b/src/cockpit/389-console/src/lib/replication/replConfig.jsx
|
|
|
cb1cc6 |
index 1f0dc3ec5..3dffb8f1a 100644
|
|
|
cb1cc6 |
--- a/src/cockpit/389-console/src/lib/replication/replConfig.jsx
|
|
|
cb1cc6 |
+++ b/src/cockpit/389-console/src/lib/replication/replConfig.jsx
|
|
|
cb1cc6 |
@@ -48,6 +48,7 @@ export class ReplConfig extends React.Component {
|
|
|
cb1cc6 |
nsds5replicaprotocoltimeout: Number(this.props.data.nsds5replicaprotocoltimeout) == 0 ? 120 : Number(this.props.data.nsds5replicaprotocoltimeout),
|
|
|
cb1cc6 |
nsds5replicabackoffmin: Number(this.props.data.nsds5replicabackoffmin) == 0 ? 3 : Number(this.props.data.nsds5replicabackoffmin),
|
|
|
cb1cc6 |
nsds5replicabackoffmax: Number(this.props.data.nsds5replicabackoffmax) == 0 ? 300 : Number(this.props.data.nsds5replicabackoffmax),
|
|
|
cb1cc6 |
+ nsds5replicakeepaliveupdateinterval: Number(this.props.data.nsds5replicakeepaliveupdateinterval) == 0 ? 3600 : Number(this.props.data.nsds5replicakeepaliveupdateinterval),
|
|
|
cb1cc6 |
// Original settings
|
|
|
cb1cc6 |
_nsds5replicabinddn: this.props.data.nsds5replicabinddn,
|
|
|
cb1cc6 |
_nsds5replicabinddngroup: this.props.data.nsds5replicabinddngroup,
|
|
|
cb1cc6 |
@@ -59,6 +60,7 @@ export class ReplConfig extends React.Component {
|
|
|
cb1cc6 |
_nsds5replicaprotocoltimeout: Number(this.props.data.nsds5replicaprotocoltimeout) == 0 ? 120 : Number(this.props.data.nsds5replicaprotocoltimeout),
|
|
|
cb1cc6 |
_nsds5replicabackoffmin: Number(this.props.data.nsds5replicabackoffmin) == 0 ? 3 : Number(this.props.data.nsds5replicabackoffmin),
|
|
|
cb1cc6 |
_nsds5replicabackoffmax: Number(this.props.data.nsds5replicabackoffmax) == 0 ? 300 : Number(this.props.data.nsds5replicabackoffmax),
|
|
|
cb1cc6 |
+ _nsds5replicakeepaliveupdateinterval: Number(this.props.data.nsds5replicakeepaliveupdateinterval) == 0 ? 3600 : Number(this.props.data.nsds5replicakeepaliveupdateinterval),
|
|
|
cb1cc6 |
};
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
this.onToggle = (isExpanded) => {
|
|
|
cb1cc6 |
@@ -275,7 +277,7 @@ export class ReplConfig extends React.Component {
|
|
|
cb1cc6 |
'nsds5replicapurgedelay', 'nsds5replicatombstonepurgeinterval',
|
|
|
cb1cc6 |
'nsds5replicareleasetimeout', 'nsds5replicaprotocoltimeout',
|
|
|
cb1cc6 |
'nsds5replicabackoffmin', 'nsds5replicabackoffmax',
|
|
|
cb1cc6 |
- 'nsds5replicaprecisetombstonepurging'
|
|
|
cb1cc6 |
+ 'nsds5replicaprecisetombstonepurging', 'nsds5replicakeepaliveupdateinterval',
|
|
|
cb1cc6 |
];
|
|
|
cb1cc6 |
// Check if a setting was changed, if so enable the save button
|
|
|
cb1cc6 |
for (const config_attr of config_attrs) {
|
|
|
cb1cc6 |
@@ -301,7 +303,7 @@ export class ReplConfig extends React.Component {
|
|
|
cb1cc6 |
'nsds5replicapurgedelay', 'nsds5replicatombstonepurgeinterval',
|
|
|
cb1cc6 |
'nsds5replicareleasetimeout', 'nsds5replicaprotocoltimeout',
|
|
|
cb1cc6 |
'nsds5replicabackoffmin', 'nsds5replicabackoffmax',
|
|
|
cb1cc6 |
- 'nsds5replicaprecisetombstonepurging'
|
|
|
cb1cc6 |
+ 'nsds5replicaprecisetombstonepurging', 'nsds5replicakeepaliveupdateinterval',
|
|
|
cb1cc6 |
];
|
|
|
cb1cc6 |
// Check if a setting was changed, if so enable the save button
|
|
|
cb1cc6 |
for (const config_attr of config_attrs) {
|
|
|
cb1cc6 |
@@ -451,6 +453,9 @@ export class ReplConfig extends React.Component {
|
|
|
cb1cc6 |
if (this.state.nsds5replicabinddngroupcheckinterval != this.state._nsds5replicabinddngroupcheckinterval) {
|
|
|
cb1cc6 |
cmd.push("--repl-bind-group-interval=" + this.state.nsds5replicabinddngroupcheckinterval);
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
+ if (this.state.nsds5replicakeepaliveupdateinterval != this.state._nsds5replicakeepaliveupdateinterval) {
|
|
|
cb1cc6 |
+ cmd.push("--repl-keepalive-update-interval=" + this.state.nsds5replicakeepaliveupdateinterval);
|
|
|
cb1cc6 |
+ }
|
|
|
cb1cc6 |
if (this.state.nsds5replicareleasetimeout != this.state._nsds5replicareleasetimeout) {
|
|
|
cb1cc6 |
cmd.push("--repl-release-timeout=" + this.state.nsds5replicareleasetimeout);
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
@@ -786,6 +791,29 @@ export class ReplConfig extends React.Component {
|
|
|
cb1cc6 |
/>
|
|
|
cb1cc6 |
</GridItem>
|
|
|
cb1cc6 |
</Grid>
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
+ title="The interval in seconds that the server will apply an internal update to get the RUV from getting stale. (nsds5replicakeepaliveupdateinterval)."
|
|
|
cb1cc6 |
+ className="ds-margin-top"
|
|
|
cb1cc6 |
+ >
|
|
|
cb1cc6 |
+ <GridItem className="ds-label" span={3}>
|
|
|
cb1cc6 |
+ Refresh RUV Interval
|
|
|
cb1cc6 |
+ </GridItem>
|
|
|
cb1cc6 |
+ <GridItem span={9}>
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
+ value={this.state.nsds5replicakeepaliveupdateinterval}
|
|
|
cb1cc6 |
+ min={60}
|
|
|
cb1cc6 |
+ max={this.maxValue}
|
|
|
cb1cc6 |
+ onMinus={() => { this.onMinusConfig("nsds5replicakeepaliveupdateinterval") }}
|
|
|
cb1cc6 |
+ onChange={(e) => { this.onConfigChange(e, "nsds5replicakeepaliveupdateinterval", 60) }}
|
|
|
cb1cc6 |
+ onPlus={() => { this.onPlusConfig("nsds5replicakeepaliveupdateinterval") }}
|
|
|
cb1cc6 |
+ inputName="input"
|
|
|
cb1cc6 |
+ inputAriaLabel="number input"
|
|
|
cb1cc6 |
+ minusBtnAriaLabel="minus"
|
|
|
cb1cc6 |
+ plusBtnAriaLabel="plus"
|
|
|
cb1cc6 |
+ widthChars={8}
|
|
|
cb1cc6 |
+ />
|
|
|
cb1cc6 |
+ </GridItem>
|
|
|
cb1cc6 |
+ </Grid>
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
title="Enables faster tombstone purging (nsds5replicaprecisetombstonepurging)."
|
|
|
cb1cc6 |
className="ds-margin-top"
|
|
|
cb1cc6 |
diff --git a/src/cockpit/389-console/src/replication.jsx b/src/cockpit/389-console/src/replication.jsx
|
|
|
cb1cc6 |
index 28364156a..db9d030db 100644
|
|
|
cb1cc6 |
--- a/src/cockpit/389-console/src/replication.jsx
|
|
|
cb1cc6 |
+++ b/src/cockpit/389-console/src/replication.jsx
|
|
|
cb1cc6 |
@@ -553,6 +553,7 @@ export class Replication extends React.Component {
|
|
|
cb1cc6 |
nsds5replicaprotocoltimeout: 'nsds5replicaprotocoltimeout' in config.attrs ? config.attrs.nsds5replicaprotocoltimeout[0] : "",
|
|
|
cb1cc6 |
nsds5replicabackoffmin: 'nsds5replicabackoffmin' in config.attrs ? config.attrs.nsds5replicabackoffmin[0] : "",
|
|
|
cb1cc6 |
nsds5replicabackoffmax: 'nsds5replicabackoffmax' in config.attrs ? config.attrs.nsds5replicabackoffmax[0] : "",
|
|
|
cb1cc6 |
+ nsds5replicakeepaliveupdateinterval: 'nsds5replicakeepaliveupdateinterval' in config.attrs ? config.attrs.nsds5replicakeepaliveupdateinterval[0] : "3600",
|
|
|
cb1cc6 |
},
|
|
|
cb1cc6 |
suffixSpinning: false,
|
|
|
cb1cc6 |
disabled: false,
|
|
|
cb1cc6 |
@@ -695,6 +696,11 @@ export class Replication extends React.Component {
|
|
|
cb1cc6 |
nsds5replicaprotocoltimeout: 'nsds5replicaprotocoltimeout' in config.attrs ? config.attrs.nsds5replicaprotocoltimeout[0] : "",
|
|
|
cb1cc6 |
nsds5replicabackoffmin: 'nsds5replicabackoffmin' in config.attrs ? config.attrs.nsds5replicabackoffmin[0] : "",
|
|
|
cb1cc6 |
nsds5replicabackoffmax: 'nsds5replicabackoffmax' in config.attrs ? config.attrs.nsds5replicabackoffmax[0] : "",
|
|
|
cb1cc6 |
+ nsds5replicakeepaliveupdateinterval: 'nsds5replicakeepaliveupdateinterval' in config.attrs ? config.attrs.nsds5replicakeepaliveupdateinterval[0] : "3600",
|
|
|
cb1cc6 |
+ clMaxEntries: "",
|
|
|
cb1cc6 |
+ clMaxAge: "",
|
|
|
cb1cc6 |
+ clTrimInt: "",
|
|
|
cb1cc6 |
+ clEncrypt: false,
|
|
|
cb1cc6 |
}
|
|
|
cb1cc6 |
}, this.loadLDIFs);
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
diff --git a/src/lib389/lib389/cli_conf/replication.py b/src/lib389/lib389/cli_conf/replication.py
|
|
|
cb1cc6 |
index 0048cd09b..450246b3d 100644
|
|
|
cb1cc6 |
--- a/src/lib389/lib389/cli_conf/replication.py
|
|
|
cb1cc6 |
+++ b/src/lib389/lib389/cli_conf/replication.py
|
|
|
cb1cc6 |
@@ -33,6 +33,7 @@ arg_to_attr = {
|
|
|
cb1cc6 |
'repl_backoff_min': 'nsds5replicabackoffmin',
|
|
|
cb1cc6 |
'repl_backoff_max': 'nsds5replicabackoffmax',
|
|
|
cb1cc6 |
'repl_release_timeout': 'nsds5replicareleasetimeout',
|
|
|
cb1cc6 |
+ 'repl_keepalive_update_interval': 'nsds5replicakeepaliveupdateinterval',
|
|
|
cb1cc6 |
# Changelog
|
|
|
cb1cc6 |
'cl_dir': 'nsslapd-changelogdir',
|
|
|
cb1cc6 |
'max_entries': 'nsslapd-changelogmaxentries',
|
|
|
cb1cc6 |
@@ -1278,6 +1279,9 @@ def create_parser(subparsers):
|
|
|
cb1cc6 |
"while waiting to acquire the consumer. Default is 3 seconds")
|
|
|
cb1cc6 |
repl_set_parser.add_argument('--repl-release-timeout', help="A timeout in seconds a replication supplier should send "
|
|
|
cb1cc6 |
"updates before it yields its replication session")
|
|
|
cb1cc6 |
+ repl_set_parser.add_argument('--repl-keepalive-update-interval', help="Interval in seconds for how often the server will apply "
|
|
|
cb1cc6 |
+ "an internal update to keep the RUV from getting stale. "
|
|
|
cb1cc6 |
+ "The default is 1 hour (3600 seconds)")
|
|
|
cb1cc6 |
|
|
|
cb1cc6 |
repl_monitor_parser = repl_subcommands.add_parser('monitor', help='Display the full replication topology report')
|
|
|
cb1cc6 |
repl_monitor_parser.set_defaults(func=get_repl_monitor_info)
|
|
|
cb1cc6 |
@@ -1289,7 +1293,7 @@ def create_parser(subparsers):
|
|
|
cb1cc6 |
repl_monitor_parser.add_argument('-a', '--aliases', nargs="*",
|
|
|
cb1cc6 |
help="Enables displaying an alias instead of host:port, if an alias is "
|
|
|
cb1cc6 |
"assigned to a host:port combination. The format: alias=host:port")
|
|
|
cb1cc6 |
-#
|
|
|
cb1cc6 |
+
|
|
|
cb1cc6 |
############################################
|
|
|
cb1cc6 |
# Replication Agmts
|
|
|
cb1cc6 |
############################################
|
|
|
cb1cc6 |
--
|
|
|
cb1cc6 |
2.37.1
|
|
|
cb1cc6 |
|