mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noel Rouvignac
29.57.2015 baedb69fcb97c58e201601347f5ec8df0fe00560
OPENDJ-2179 (CR-7413) ECL: full resync step is no longer valid



This was found due to one functional test that was working with 2.6 code base, but no longer works with 2.8.

Here is the sequence of events:

time1 change 1 => changenumber=1, changelogcookie=dc=com:csn1;
time2 ldapsearch (changenumber=1) returns entry with changenumber=1 and changelogcookie=dc=com:csn1;
time3 enable domain dc=fr
time4 change 2 => changenumber=2, changelogcookie=dc=com:csn1;dc=fr:csn2;

2.6:
time5 ldapsearch (changenumber=1) returns entry with changenumber=1 and changelogcookie=dc=com:csn1;dc=fr;
time6 ldapsearch (changelogcookie=dc=com:csn1;) resultcode=UNWILLING_TO_PERFORM message=Full resynch is required...[...]...use dc=com:csn1;dc=fr;
time6 ldapsearch (changelogcookie=dc=com:csn1;dc=fr;) resultcode=SUCCESS returns changes with csn1 and csn2

2.8:
time5 ldapsearch (changenumber=1) returns entry with changenumber=1 and changelogcookie=dc=com:csn1;
time6 ldapsearch (changelogcookie=dc=com:csn1;) resultcode=UNWILLING_TO_PERFORM message=Full resynch is required...[...]...use dc=com:csn1;dc=fr;
time6 ldapsearch (changelogcookie=dc=com:csn1;dc=fr;) resultcode=SUCCESS returns changes with csn1 and csn2

Note the different values for changelogcookie attribute at time4.

I think this difference is due to the fact the change number index DB was storing the previous cookie (thus returning it), while the new change number index DB is not storing it anymore (thus building it on the fly). So the new domain baseDN cannot be included until one change has been seen for it.

I think this error message was originally added as the result of a leaky abstraction: In 2.6, doing a search in the cookie mode was driven by the cookie provided by the user. So when a search was performed using a cookie that did not have all domains, no results would be returned for the missing domains. Hence this restriction was added to force users to iterate over all the domains.

With the new changelog implementation, all domains are iterated by default and this restriction is no longer necessary.

By removing this limitation here is how the results would compare:

time1 change 1 => changenumber=1, changelogcookie=dc=com:csn1;
time2 ldapsearch (changenumber=1) returns entry with changenumber=1 and changelogcookie=dc=com:csn1;
time3 enable domain dc=fr
time4 change 2 => changenumber=2, changelogcookie=dc=com:csn1;dc=fr:csn2;

2.6:
time5 ldapsearch (changenumber=1) returns entry with changenumber=1 and changelogcookie=dc=com:csn1;dc=fr;
time6 ldapsearch (changelogcookie=dc=com:csn1;) resultcode=UNWILLING_TO_PERFORM message=Full resynch is required...[...]...use dc=com:csn1;dc=fr;
time6 ldapsearch (changelogcookie=dc=com:csn1;dc=fr;) resultcode=SUCCESS returns changes with csn1 and csn2

2.8:
time5 ldapsearch (changenumber=1) returns entry with changenumber=1 and changelogcookie=dc=com:csn1;
time6 ldapsearch (changelogcookie=dc=com:csn1;) resultcode=SUCCESS returns changes with csn1 and csn2



ReplicationServer.java:
Removed error ERR_RESYNC_REQUIRED_MISSING_DOMAIN_IN_PROVIDED_COOKIE, no longer necessary with the new changelog implementation.
8 files modified
56 ■■■■■ changed files
opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServer.java 40 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication.properties 4 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_de.properties 1 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_es.properties 1 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_fr.properties 1 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_ja.properties 1 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_zh_CN.properties 1 ●●●● patch | view | raw | blame | history
opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/ChangelogBackendTestCase.java 7 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServer.java
@@ -54,7 +54,11 @@
import org.opends.server.replication.common.MultiDomainServerState;
import org.opends.server.replication.common.ServerState;
import org.opends.server.replication.plugin.MultimasterReplication;
import org.opends.server.replication.protocol.*;
import org.opends.server.replication.protocol.ReplServerStartMsg;
import org.opends.server.replication.protocol.ReplSessionSecurity;
import org.opends.server.replication.protocol.ReplicationMsg;
import org.opends.server.replication.protocol.ServerStartMsg;
import org.opends.server.replication.protocol.Session;
import org.opends.server.replication.server.changelog.api.ChangeNumberIndexDB;
import org.opends.server.replication.server.changelog.api.ChangeNumberIndexRecord;
import org.opends.server.replication.server.changelog.api.ChangelogDB;
@@ -63,7 +67,12 @@
import org.opends.server.replication.server.changelog.file.FileChangelogDB;
import org.opends.server.replication.server.changelog.je.JEChangelogDB;
import org.opends.server.replication.service.DSRSShutdownSync;
import org.opends.server.types.*;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.HostPort;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.VirtualAttributeRule;
/**
 * ReplicationServer Listener. This singleton is the main object of the
@@ -616,7 +625,6 @@
    final Set<DN> activeDomains = getDNsOfActiveDomainsInServer(ignoredBaseDNs);
    final Set<DN> cookieDomains = getDNsOfCookie(cookie);
    checkNoActiveDomainIsMissingInCookie(cookie, activeDomains, cookieDomains);
    checkNoUnknownDomainIsProvidedInCookie(cookie, activeDomains, cookieDomains);
    checkCookieIsNotOutdated(cookie, activeDomains);
  }
@@ -662,24 +670,6 @@
    }
  }
  private void checkNoActiveDomainIsMissingInCookie(final MultiDomainServerState cookie, final Set<DN> activeDomains,
      final Set<DN> cookieDomains) throws DirectoryException
  {
    if (!cookieDomains.containsAll(activeDomains))
    {
      final Set<DN> missingActiveDomains = new HashSet<DN>(activeDomains);
      missingActiveDomains.removeAll(cookieDomains);
      final StringBuilder missingDomains = new StringBuilder();
      for (DN domainDN : missingActiveDomains)
      {
        missingDomains.append(domainDN).append(":;");
      }
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
          ERR_RESYNC_REQUIRED_MISSING_DOMAIN_IN_PROVIDED_COOKIE.get(
              missingDomains, "<" + cookie + missingDomains + ">"));
    }
  }
  private void checkCookieIsNotOutdated(final MultiDomainServerState cookie, final Set<DN> activeDomains)
      throws DirectoryException
  {
@@ -696,8 +686,14 @@
  /** Check that provided cookie is not outdated compared to the oldest state of a domain. */
  private boolean isCookieOutdatedForDomain(MultiDomainServerState cookie, DN domainDN)
  {
    final ServerState domainOldestState = getReplicationServerDomain(domainDN).getOldestState();
    final ServerState providedState = cookie.getServerState(domainDN);
    if (providedState == null)
    {
      // missing domains do not invalidate a cookie.
      // results will include all the changes of the missing domains
      return false;
    }
    final ServerState domainOldestState = getReplicationServerDomain(domainDN).getOldestState();
    for (final CSN oldestCsn : domainOldestState)
    {
      final CSN providedCsn = providedState.getCSN(oldestCsn.getServerId());
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication.properties
@@ -250,10 +250,6 @@
 on base-dn %s : %s
ERR_REPLICATION_PROTOCOL_MESSAGE_TYPE_157=Replication \
 protocol error. Bad message type. %s received, %s required
ERR_RESYNC_REQUIRED_MISSING_DOMAIN_IN_PROVIDED_COOKIE_158=Full resync \
 required because the provided cookie is missing the replicated domain(s) %s. \
 The following cookie value can be used to retrieve the missing changes, \
 including the COMPLETE record of changes for the missing domain(s) : %s
ERR_BYTE_COUNT_159=The Server Handler byte count is not correct \
 Byte Count=%s (Fixed)
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS_160=Wrong fractional \
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_de.properties
@@ -146,7 +146,6 @@
NOTE_ERR_CANNOT_CHANGE_CONFIG_DURING_TOTAL_UPDATE_153=Konfiguration kann w\u00e4hrend einer vollst\u00e4ndigen Aktualisierung nicht ge\u00e4ndert werden
ERR_COULD_NOT_START_REPLICATION_154=Die Replikation wurde nicht in Basis-DN %s gestartet : %s
ERR_REPLICATION_PROTOCOL_MESSAGE_TYPE_157=Replikationsprotokollfehler. Ung\u00fcltiger Meldungstyp. %s empfangen, %s erforderlich
ERR_RESYNC_REQUIRED_MISSING_DOMAIN_IN_PROVIDED_COOKIE_158=Vollst\u00e4ndige Neusynchronisierung erforderlich, da f\u00fcr das angegebene Cookie die replizierte(n) Dom\u00e4ne(n) %s fehlen. Der folgende Cookie-Wert kann verwendet werden, um die fehlenden \u00c4nderungen abzurufen, einschlie\u00dflich Datensatz COMPLETE f\u00fcr die \u00c4nderungen der fehlenden Dom\u00e4ne(n) : %s
ERR_BYTE_COUNT_159=Die Byte-Anzahl des Serverhandlers ist nicht korrekt Byte-Anzahl=%s (fest)
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS_160=Falsche Teilreplikationskonfiguration: Im Schema konnte keine Objektklassendefinition f\u00fcr %s gefunden werden
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_ATTRIBUTE_TYPE_161=Falsche Teilreplikationskonfiguration: Im Schema konnte keine Attributtypdefinition f\u00fcr %s gefunden werden
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_es.properties
@@ -146,7 +146,6 @@
NOTE_ERR_CANNOT_CHANGE_CONFIG_DURING_TOTAL_UPDATE_153=No es posible cambiar la configuraci\u00f3n mientras se lleva a cabo una actualizaci\u00f3n completa
ERR_COULD_NOT_START_REPLICATION_154=No se inici\u00f3 la repetici\u00f3n en el ND de base %s: %s
ERR_REPLICATION_PROTOCOL_MESSAGE_TYPE_157=Error de protocolo de repetici\u00f3n. Tipo de mensaje err\u00f3neo. Se ha recibido %s, se requiere %s
ERR_RESYNC_REQUIRED_MISSING_DOMAIN_IN_PROVIDED_COOKIE_158=Se requiere una resincronizaci\u00f3n completa porque la cookie proporcionada no cuenta con el dominio repetido %s. Puede utilizarse el siguiente valor de cookie para recuperar los cambios que faltan, incluido el registro COMPLETO de cambios para el dominio que falta: %s
ERR_BYTE_COUNT_159=El recuento de bytes del controlador del servidor no es correcto. Recuento de bytes=%s (solucionado)
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS_160=Configuraci\u00f3n de repetici\u00f3n fraccional err\u00f3nea: no se ha podido encontrar la definici\u00f3n de clase de objeto para %s en el esquema
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_ATTRIBUTE_TYPE_161=Configuraci\u00f3n de repetici\u00f3n fraccional err\u00f3nea: no se ha podido encontrar la definici\u00f3n de tipo de atributo para %s en el esquema
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_fr.properties
@@ -146,7 +146,6 @@
NOTE_ERR_CANNOT_CHANGE_CONFIG_DURING_TOTAL_UPDATE_153=Impossible de modifier la configuration alors qu'une mise \u00e0 jour compl\u00e8te est en cours
ERR_COULD_NOT_START_REPLICATION_154=La r\u00e9plication n'a pas \u00e9t\u00e9 d\u00e9marr\u00e9e sur le DN de base %s\u00a0: %s
ERR_REPLICATION_PROTOCOL_MESSAGE_TYPE_157=Erreur du protocole de r\u00e9plication. Type de message incorrect. %s re\u00e7u, %s requis
ERR_RESYNC_REQUIRED_MISSING_DOMAIN_IN_PROVIDED_COOKIE_158=Une resynchronisation compl\u00e8te est requise car le cookie fournie ne contient pas le(s) domaine(s) r\u00e9pliqu\u00e9(s) %s. Vous pouvez utiliser la valeur de cookie suivante pour r\u00e9cup\u00e9rer les modifications manquantes, notamment l'enregistrement des modifications COMPLETE du/des domaine(s) manquant(s)\u00a0: %s
ERR_BYTE_COUNT_159=Le nombre d'octets du gestionnaire de serveurs n'est pas correct Nb d'octets=%s (fixe)
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS_160=Configuration de r\u00e9plication partielle incorrecte : impossible de trouver la d\u00e9finition de la classe d'objet pour %s dans le sch\u00e9ma
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_ATTRIBUTE_TYPE_161=Configuration de r\u00e9plication partielle incorrecte : impossible de trouver la d\u00e9finition du type d'attribut pour %s dans le sch\u00e9ma
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_ja.properties
@@ -145,7 +145,6 @@
NOTE_ERR_CANNOT_CHANGE_CONFIG_DURING_TOTAL_UPDATE_153=\u5b8c\u5168\u66f4\u65b0\u306e\u9032\u884c\u4e2d\u306f\u3001\u69cb\u6210\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093
ERR_COULD_NOT_START_REPLICATION_154=base-dn %s \u3067\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u958b\u59cb\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f: %s
ERR_REPLICATION_PROTOCOL_MESSAGE_TYPE_157=\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30d7\u30ed\u30c8\u30b3\u30eb\u30a8\u30e9\u30fc\u3002\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7\u304c\u9593\u9055\u3063\u3066\u3044\u307e\u3059\u3002%s \u53d7\u4fe1\u6e08\u307f\u3001%s \u5fc5\u8981
ERR_RESYNC_REQUIRED_MISSING_DOMAIN_IN_PROVIDED_COOKIE_158=\u63d0\u4f9b\u3055\u308c\u305f Cookie \u306b\u306f\u30ec\u30d7\u30ea\u30b1\u30fc\u30c8\u3055\u308c\u305f\u30c9\u30e1\u30a4\u30f3 %s \u304c\u6b20\u843d\u3057\u3066\u3044\u308b\u305f\u3081\u3001\u5b8c\u5168\u306a\u518d\u540c\u671f\u304c\u5fc5\u8981\u3067\u3059\u3002\u6b21\u306e Cookie \u5024\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u6b20\u843d\u3057\u3066\u3044\u308b\u30c9\u30e1\u30a4\u30f3\u306b\u5bfe\u3059\u308b\u5909\u66f4\u306e COMPLETE \u30ec\u30b3\u30fc\u30c9\u3092\u542b\u3081\u3066\u3001\u6b20\u843d\u3057\u3066\u3044\u308b\u5909\u66f4\u3092\u53d6\u5f97\u3067\u304d\u307e\u3059: %s
ERR_BYTE_COUNT_159=\u30b5\u30fc\u30d0\u30fc\u30cf\u30f3\u30c9\u30e9\u306e\u30d0\u30a4\u30c8\u6570\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002\u30d0\u30a4\u30c8\u6570=%s (\u56fa\u5b9a\u5024)
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS_160=\u90e8\u5206\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u69cb\u6210\u304c\u4e0d\u6b63\u3067\u3059: \u30b9\u30ad\u30fc\u30de\u4e2d\u306b %s \u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30af\u30e9\u30b9\u5b9a\u7fa9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_ATTRIBUTE_TYPE_161=\u90e8\u5206\u30ec\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u69cb\u6210\u304c\u4e0d\u6b63\u3067\u3059 : \u30b9\u30ad\u30fc\u30de\u4e2d\u306b %s \u306e\u5c5e\u6027\u578b\u5b9a\u7fa9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f
opendj-sdk/opendj-server-legacy/src/messages/org/opends/messages/replication_zh_CN.properties
@@ -144,7 +144,6 @@
NOTE_ERR_CANNOT_CHANGE_CONFIG_DURING_TOTAL_UPDATE_153=\u5f53\u6b63\u5728\u8fdb\u884c\u5b8c\u5168\u66f4\u65b0\u65f6\uff0c\u4e0d\u80fd\u66f4\u6539\u914d\u7f6e
ERR_COULD_NOT_START_REPLICATION_154=\u672a\u5728\u57fa DN %s \u4e0a\u542f\u52a8\u590d\u5236: %s
ERR_REPLICATION_PROTOCOL_MESSAGE_TYPE_157=\u590d\u5236\u534f\u8bae\u9519\u8bef\u3002\u9519\u8bef\u6d88\u606f\u7c7b\u578b\u3002\u63a5\u6536\u5230 %s\uff0c\u8981\u6c42 %s
ERR_RESYNC_REQUIRED_MISSING_DOMAIN_IN_PROVIDED_COOKIE_158=\u8981\u6c42\u5b8c\u5168\u518d\u540c\u6b65\uff0c\u56e0\u4e3a\u63d0\u4f9b\u7684 Cookie \u7f3a\u5c11\u590d\u5236\u57df %s\u3002\u4ee5\u4e0b Cookie \u503c\u53ef\u7528\u4e8e\u68c0\u7d22\u7f3a\u5931\u7684\u66f4\u6539\uff0c\u5305\u62ec\u7f3a\u5931\u57df %s \u7684\u66f4\u6539\u7684\u5b8c\u6574\u8bb0\u5f55
ERR_BYTE_COUNT_159=\u670d\u52a1\u5668\u5904\u7406\u7a0b\u5e8f\u5b57\u8282\u8ba1\u6570\u4e0d\u6b63\u786e\uff0c\u5b57\u8282\u8ba1\u6570=%s\uff08\u5df2\u4fee\u6b63\uff09
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS_160=\u90e8\u5206\u590d\u5236\u914d\u7f6e\u9519\u8bef\uff1a\u5728\u6a21\u5f0f\u4e2d\u65e0\u6cd5\u627e\u5230 %s \u7684\u5bf9\u8c61\u7c7b\u5b9a\u4e49
NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_ATTRIBUTE_TYPE_161=\u90e8\u5206\u590d\u5236\u914d\u7f6e\u9519\u8bef\uff1a\u5728\u6a21\u5f0f\u4e2d\u65e0\u6cd5\u627e\u5230 %s \u7684\u5c5e\u6027\u7c7b\u578b\u5b9a\u4e49
opendj-sdk/opendj-server-legacy/src/test/java/org/opends/server/backends/ChangelogBackendTestCase.java
@@ -446,10 +446,9 @@
      // test missing domain in provided cookie
      final String cookie3 = lastCookie.substring(lastCookie.indexOf(';')+1);
      debugInfo(test, "Search with bad domain in cookie=" + cookie);
      searchOp = searchChangelogUsingCookie("(targetDN=*" + test + "*,o=test)", cookie3, UNWILLING_TO_PERFORM, 0, test);
      expectedError = ERR_RESYNC_REQUIRED_MISSING_DOMAIN_IN_PROVIDED_COOKIE
          .get("o=test:;","<"+ cookie3 + "o=test:;>").toString();
      assertThat(searchOp.getErrorMessage().toString()).isEqualToIgnoringCase(expectedError);
      searchOp = searchChangelogUsingCookie("(targetDN=*" + test + "*,o=test)", cookie3, SUCCESS, 5, test);
      assertEntriesContainsCSNsAndReadLastCookie(test, searchOp.getSearchEntries(), ldifWriter,
          csn1, csn4, csn5, csn7, csn9);
    }
    finally
    {