From 1e4e8cda990cba0b15953cb81fc8437a9ef53142 Mon Sep 17 00:00:00 2001
From: pgamba <pgamba@localhost>
Date: Wed, 08 Jul 2009 14:16:25 +0000
Subject: [PATCH] add the changenumber attribute to the changelog entry and fix the schema

---
 opendj-sdk/opends/resource/schema/03-changelog.ldif                                                           |   36 ++++++++++-
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java |    5 +
 opendj-sdk/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java      |   94 +++++++++++++++++++++++--------
 3 files changed, 105 insertions(+), 30 deletions(-)

diff --git a/opendj-sdk/opends/resource/schema/03-changelog.ldif b/opendj-sdk/opends/resource/schema/03-changelog.ldif
index a5bbae5..6f44642 100644
--- a/opendj-sdk/opends/resource/schema/03-changelog.ldif
+++ b/opendj-sdk/opends/resource/schema/03-changelog.ldif
@@ -21,7 +21,7 @@
 # CDDL HEADER END
 #
 #
-#      Copyright 2006-2008 Sun Microsystems, Inc.
+#      Copyright 2006-2009 Sun Microsystems, Inc.
 #
 #
 # This file contains schema definitions from draft-good-ldap-changelog, which
@@ -60,8 +60,34 @@
   DESC 'the new parent of an entry which is the target of a moddn operation'
   EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
   SINGLE-VALUE X-ORIGIN 'draft-good-ldap-changelog' )
+attributeTypes: ( 2.16.840.1.113730.3.1.77 NAME 'changeTime'
+  DESC 'the time when the change was processed'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'Sun DSEE6 Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.42.2.27.9.1.724 NAME 'replicaIdentifier'
+  DESC 'the OpenDS replication domain server identifier for the change'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.42.2.27.9.1.725 NAME 'replicationCSN'
+  DESC 'The OpenDS replication change number for the change'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.590 NAME 'targetEntryUUID'
+  DESC 'The OpenDS unique id of the entry targeted by the change'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.591 NAME 'changeLogCookie'
+  DESC 'The OpenDS opaque cookie for the External Changelog'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 2.16.840.1.113730.3.2.1 NAME 'changeLogEntry' SUP top
-  STRUCTURAL MUST ( changeNumber $ targetDN $ changeType )
-  MAY ( changes $ newRDN $ deleteOldRDN $ newSuperior )
-  X-ORIGIN 'draft-good-ldap-changelog' )
-
+  STRUCTURAL 
+  MUST ( changeNumber $ targetDN $ changeType $ changeTime )
+  MAY ( changes $ newRDN $ deleteOldRDN $ newSuperior $ replicaIdentifier
+  $ replicationCSN $ targetEntryUUID $ cookie )
+  X-ORIGIN 'draft-good-ldap-changelog' )
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
index 0d7a971..0ed7354 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
@@ -647,7 +647,12 @@
         if (update!=null)
         {
           if (phase==INITIAL)
-            buildAndReturnEntry(update);
+            if (!buildAndReturnEntry(update))
+            {
+              // Abandon, Size limit reached
+              eclSession.close();
+              break;
+            }
         }
         else
         {
@@ -678,9 +683,13 @@
   /**
    * Build an ECL entry from a provided ECL msg and return it.
    * @param eclmsg The provided ECL msg.
+   * @return  <CODE>true</CODE> if the caller should continue processing the
+   *          search request and sending additional entries and references, or
+   *          <CODE>false</CODE> if not for some reason (e.g., the size limit
+   *          has been reached or the search has been abandoned).
    * @throws DirectoryException When an errors occurs.
    */
-  private void buildAndReturnEntry(ECLUpdateMsg eclmsg)
+  private boolean buildAndReturnEntry(ECLUpdateMsg eclmsg)
   throws DirectoryException
   {
     Entry entry = null;
@@ -695,12 +704,9 @@
       = new EntryChangelogNotificationControl(
           true,eclmsg.getCookie().toString());
       controls.add(clrc);
-      boolean entryReturned = returnEntry(entry, controls);
-      if (entryReturned==false)
-      {
-        // FIXME:ECL Handle the error case where returnEntry fails
-      }
+      return returnEntry(entry, controls);
     }
+    return true;
   }
 
   /**
@@ -749,7 +755,7 @@
           null, // real time current entry
           null, // real time attrs names
           null, // hist entry attributes
-          0,    // TODO:ECL G Good changelog draft compat. addMsg.getSeqnum()
+          -1,    // TODO:ECL G Good changelog draft compat. addMsg.getSeqnum()
       "add");
 
     } else
@@ -778,7 +784,7 @@
             null, // real time current entry
             null, // real time attrs names
             null, // hist entry attributes
-            0,    // TODO:ECL G Good changelog draft compat. modMsg.getSeqnum()
+            -1,    // TODO:ECL G Good changelog draft compat. modMsg.getSeqnum()
         "modify");
 
       }
@@ -801,7 +807,7 @@
           null, // real time current entry
           null, // real time attrs names
           null, // hist entry attributes
-          0,    // TODO:ECL G Good changelog draft compat. modDNMsg.getSeqnum()
+          -1,    // TODO:ECL G Good changelog draft compat. modDNMsg.getSeqnum()
           "modrdn");
 
       Attribute a = Attributes.create("newrdn", modDNMsg.getNewRDN());
@@ -835,7 +841,7 @@
           null,
           null,
           null, //rattributes,
-          0, // TODO:ECL G Good changelog draft compat. delMsg.getSeqnum()
+          -1, // TODO:ECL G Good changelog draft compat. delMsg.getSeqnum()
          "delete");
     }
     return clEntry;
@@ -890,7 +896,7 @@
    * @param targetAttrNames The provided list of attributes names that should
    *                        be read from the entry (real time values)
    * @param histEntryAttributes TODO:ECL Adress hist entry attributes
-   * @param seqnum          The provided RCL int change number.
+   * @param draftChangenumber The provided draft change number (integer)
    * @param changetype      The provided change type (add, ...)
    * @return                The created ECL entry.
    * @throws DirectoryException
@@ -906,7 +912,7 @@
       Entry entry,
       List<String> targetAttrNames,
       List<RawAttribute> histEntryAttributes,
-      int seqnum,
+      int draftChangenumber,
       String changetype)
   throws DirectoryException
   {
@@ -930,17 +936,11 @@
 
     ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
 
-    // TODO:ECL G Good changelog compat.
-    if (seqnum>0)
-    {
-      Attribute a = Attributes.create("changeNumber", String.valueOf(seqnum));
-      attrList = new ArrayList<Attribute>(1);
-      attrList.add(a);
-      uAttrs.put(a.getAttributeType(), attrList);
-    }
+    // MUST attributes
 
-    //
-    Attribute a = Attributes.create("replicationCSN", changeNumber.toString());
+    // ECL Changelog draft change number
+    Attribute a = Attributes.create("changeNumber",
+        String.valueOf(draftChangenumber));
     attrList = new ArrayList<Attribute>(1);
     attrList.add(a);
     uAttrs.put(a.getAttributeType(), attrList);
@@ -978,12 +978,19 @@
     attrList.add(a);
     uAttrs.put(a.getAttributeType(), attrList);
 
+    // MAY attributes
+
+    a = Attributes.create("replicationCSN", changeNumber.toString());
+    attrList = new ArrayList<Attribute>(1);
+    attrList.add(a);
+    operationalAttrs.put(a.getAttributeType(), attrList);
+
     //
     a = Attributes.create("replicaIdentifier",
         Short.toString(changeNumber.getServerId()));
     attrList = new ArrayList<Attribute>(1);
     attrList.add(a);
-    uAttrs.put(a.getAttributeType(), attrList);
+    operationalAttrs.put(a.getAttributeType(), attrList);
 
     if (clearLDIFchanges != null)
     {
@@ -1014,6 +1021,15 @@
     attrList = new ArrayList<Attribute>(1);
     attrList.add(a);
     operationalAttrs.put(a.getAttributeType(), attrList);
+    if (draftChangenumber>0)
+    {
+      // compat mode
+      a = Attributes.create("targetuniqueid",
+          ECLSearchOperation.openDsToSunDseeNsUniqueId(targetUUID));
+      attrList = new ArrayList<Attribute>(1);
+      attrList.add(a);
+      operationalAttrs.put(a.getAttributeType(), attrList);
+    }
 
     a = Attributes.create("cookie", cookie);
     attrList = new ArrayList<Attribute>(1);
@@ -1309,5 +1325,35 @@
     }
     return super.cancel(cancelRequest);
   }
+
+  /**
+  * The unique identifier used in DSEE is named nsUniqueId and its format is
+  * HHHHHHHH-HHHHHHHH-HHHHHHHH-HHHHHHHH where H is a hex digit.
+  * An nsUniqueId value is for example 3970de28-08b311d9-8095b9bf-c4d9231c
+  * The unique identifier used in OpenDS is named entryUUID.
+  * Its value is for example entryUUID: 50dd9673-71e1-4478-b13c-dba387c4d7e1
+  * @param entryUid the OpenDS entry UID
+  * @return the Dsee format for the entry UID
+  */
+  private static String openDsToSunDseeNsUniqueId(String entryUid)
+  {
+
+    if (entryUid == null)
+      return null;
+
+    //  the conversion from one unique identifier to an other is
+    //  a question of formating : the last “-” is placed
+    StringBuffer buffer = new StringBuffer(entryUid);
+    //  Delete a "-" at 13 to get something like
+    buffer.deleteCharAt(13);
+
+    //  Delete a "-" at 23 to get something like
+    buffer.deleteCharAt(22);
+
+    //  Add the last "-" to get something like
+    buffer.insert(26,'-');
+
+    return buffer.toString();
+  }
 }
 
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
index 07b1cfc..a030288 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
@@ -1081,6 +1081,7 @@
             checkValue(resultEntry,"changetype","delete");
             checkValue(resultEntry,"cookie","o=test:"+cn1.toString()+";");
             checkValue(resultEntry,"targetentryuuid",tn+"uuid1");
+            checkValue(resultEntry,"changenumber","-1");
           } else if (i==2)
           {
             // check the ADD entry has the right content
@@ -1095,7 +1096,7 @@
             checkValue(resultEntry,"changetype","add");
             checkValue(resultEntry,"cookie","o=test:"+cn2.toString()+";");
             checkValue(resultEntry,"targetentryuuid",user1entryUUID);
-
+            checkValue(resultEntry,"changenumber","-1");
           } else if (i==3)
           {
             // check the MOD entry has the right content
@@ -1108,6 +1109,7 @@
             checkValue(resultEntry,"changetype","modify");
             checkValue(resultEntry,"cookie","o=test:"+cn3.toString()+";");
             checkValue(resultEntry,"targetentryuuid",tn+"uuid3");
+            checkValue(resultEntry,"changenumber","-1");
           } else if (i==4)
           {
             // check the MODDN entry has the right content
@@ -1120,6 +1122,7 @@
             checkValue(resultEntry,"newrdn","uid=ECLDirectAllOpsnew4");            
             checkValue(resultEntry,"newsuperior",TEST_ROOT_DN_STRING2);
             checkValue(resultEntry,"deleteoldrdn","true");
+            checkValue(resultEntry,"changenumber","-1");
           }
         }
       }

--
Gitblit v1.10.0