]> git.sur5r.net Git - openldap/commitdiff
LDAP Sync Operation (draft-zeilenga-ldup-sync) as a groundwork for an LDAP replicatio...
authorJong Hyuk Choi <jongchoi@openldap.org>
Wed, 5 Feb 2003 07:37:02 +0000 (07:37 +0000)
committerJong Hyuk Choi <jongchoi@openldap.org>
Wed, 5 Feb 2003 07:37:02 +0000 (07:37 +0000)
19 files changed:
clients/tools/ldapsearch.c
include/ldap.h
libraries/libldap/error.c
servers/slapd/abandon.c
servers/slapd/back-bdb/add.c
servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/delete.c
servers/slapd/back-bdb/init.c
servers/slapd/back-bdb/lcup.c
servers/slapd/back-bdb/modify.c
servers/slapd/back-bdb/modrdn.c
servers/slapd/back-bdb/proto-bdb.h
servers/slapd/back-bdb/search.c
servers/slapd/cancel.c
servers/slapd/connection.c
servers/slapd/controls.c
servers/slapd/operation.c
servers/slapd/search.c
servers/slapd/slap.h

index ec86820b88d90a0cf2322af1bc8bfbc8c7d95a77..46745acef2a09541411b38d8cb2401fedc4df43a 100644 (file)
@@ -76,6 +76,10 @@ usage( void )
  * "                     sp/<cint>/<cookie>/<slimit>\n"
  * */
 #endif
+#ifdef LDAP_SYNC
+"             [!]sync= ro[/<cookie>] (ldap sync - refreshOnly)\n"
+"                      rp[/<cookie>][/<slimit>] (ldap sync - refreshAndPersist)\n"
+#endif
 "  -F prefix  URL prefix for files (default: %s)\n"
 "  -l limit   time limit (in seconds) for search\n"
 "  -L         print responses in LDIFv1 format\n"
@@ -147,11 +151,20 @@ static int  includeufn, vals2tmp = 0, ldif = 0;
 static int subentries = 0, valuesReturnFilter = 0;
 static char    *vrFilter = NULL;
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
 static int lcup = 0;
+static int ldapsync = 0;
+#endif
+
+#ifdef LDAP_CLIENT_UPDATE
 static int lcup_cint = 0;
 static struct berval lcup_cookie = { 0, NULL };
-static int lcup_slimit = 0;
+static int lcup_slimit = -1;
+#endif
+
+#ifdef LDAP_SYNC
+static struct berval sync_cookie = { 0, NULL };
+static int sync_slimit = -1;
 #endif
 
 static int pagedResults = 0;
@@ -290,29 +303,35 @@ handle_private_option( int i )
 #endif
 
 #ifdef LDAP_CLIENT_UPDATE
-               } else if ( strcasecmp( control, "lcup" ) == 0 ) {
-                       char *cookiep;
-                       char *slimitp;
-                       if ( lcup ) {
-                               fprintf( stderr, "client update control previously specified\n");
-                               exit( EXIT_FAILURE );
-                       }
-                       if ( cvalue == NULL ) {
-                               fprintf( stderr,
-                                       "missing specification of client update control\n");
-                               exit( EXIT_FAILURE );
-                       }
-                       if ( strncasecmp( cvalue, "p", 1 ) == 0 ) {
-                               lcup = LDAP_CUP_PERSIST_ONLY;
-                               cvalue += 2;
-                               cookiep = strchr( cvalue, '/' );
-                               *cookiep++ = '\0';
-                               lcup_cint = atoi( cvalue );
-                               cvalue = cookiep;
-                               slimitp = strchr( cvalue, '/' );
-                               *slimitp++ = '\0';
-                               ber_str2bv( cookiep, 0, 0, &lcup_cookie );
-                               lcup_slimit = atoi( slimitp );
+                } else if ( strcasecmp( control, "lcup" ) == 0 ) {
+                        char *cookiep;
+                        char *slimitp;
+                        if ( lcup ) {
+                                fprintf( stderr, "client update control previously specified\n");
+                                exit( EXIT_FAILURE );
+                        }
+                        if ( ldapsync != -1 ) {
+                                fprintf( stderr, "ldap sync control previously specified\n");
+                                exit( EXIT_FAILURE );
+                        }
+                        if ( cvalue == NULL ) {
+                                fprintf( stderr,
+                                        "missing specification of client update control\n");
+                                exit( EXIT_FAILURE );
+                        }
+                        if ( strncasecmp( cvalue, "p", 1 ) == 0 ) {
+                                lcup = LDAP_CUP_PERSIST_ONLY;
+                                cvalue = strchr( cvalue, '/' );
+                                cvalue++;
+                                cookiep = strchr( cvalue, '/' );
+                                *cookiep++ = '\0';
+                                lcup_cint = atoi( cvalue );
+                                cvalue = cookiep;
+                                slimitp = strchr( cvalue, '/' );
+                                *slimitp++ = '\0';
+                                while ( isspace( *cookiep ) ) cookiep++;
+                                ber_str2bv( cookiep, 0, 0, &lcup_cookie );
+                                lcup_slimit = atoi( slimitp );
 /*
                        } else if ( strncasecmp( cvalue, "s", 1 ) == 0 ) {
                                lcup = LDAP_CUP_SYNC_ONLY;
@@ -342,6 +361,56 @@ handle_private_option( int i )
                        if ( crit ) lcup *= -1;
 #endif
 
+#ifdef LDAP_SYNC
+       } else if ( strcasecmp( control, "sync" ) == 0 ) {
+                       char *cookiep;
+                       char *slimitp;
+                       if ( ldapsync ) {
+                               fprintf( stderr, "ldap sync control previously specified\n" );
+                               exit( EXIT_FAILURE );
+                       }
+                       if ( lcup ) {
+                               fprintf( stderr, "client update control previously specified\n" );
+                               exit( EXIT_FAILURE );
+                       }
+                       if ( cvalue == NULL ) {
+                               fprintf( stderr,
+                                       "missing specification of ldap sync control\n");
+                               exit( EXIT_FAILURE );
+                       }
+                       if ( strncasecmp( cvalue, "ro", 2 ) == 0 ) {
+                               ldapsync = LDAP_SYNC_REFRESH_ONLY;
+                               cookiep = strchr( cvalue, '/' );
+                               if ( cookiep != NULL ) {
+                                       cookiep++;
+                                       if ( *cookiep != '\0' ) {
+                                               ber_str2bv( cookiep, 0, 0, &sync_cookie );
+                                       }
+                               }
+                       } else if ( strncasecmp( cvalue, "rp", 2 ) == 0 ) {
+                               ldapsync = LDAP_SYNC_REFRESH_AND_PERSIST;
+                               cookiep = strchr( cvalue, '/' );
+                               if ( cookiep != NULL ) {
+                                       *cookiep++ = '\0';      
+                                       cvalue = cookiep;
+                               }
+                               slimitp = strchr( cvalue, '/' );
+                               if ( slimitp != NULL ) {
+                                       *slimitp++ = '\0';
+                               }
+                               if ( cookiep != NULL && *cookiep != '\0' )
+                                       ber_str2bv( cookiep, 0, 0, &sync_cookie );
+                               if ( slimitp != NULL && *slimitp != '\0' )
+                                       sync_slimit = atoi( slimitp );
+                       } else {
+                               fprintf( stderr,
+                                       "ldap sync control value \"%s\" invalid\n",
+                                       cvalue );
+                               exit( EXIT_FAILURE );
+                       }
+                       if ( crit ) ldapsync *= -1;
+#endif
+
                } else {
                        fprintf( stderr, "Invalid control name: %s\n", control );
                        usage();
@@ -434,6 +503,11 @@ main( int argc, char **argv )
         struct berval   *cubvalp = NULL;
 #endif
 
+#ifdef LDAP_SYNC
+       BerElement      *syncber = NULL;
+       struct berval   *syncbvalp = NULL;
+#endif
+
        npagedresponses = npagedentries = npagedreferences =
                npagedextended = npagedpartial = 0;
 
@@ -530,7 +604,10 @@ getNextPage:
                        || valuesReturnFilter || pageSize
 #ifdef LDAP_CLIENT_UPDATE
                        || lcup
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#ifdef LDAP_SYNC
+                       || ldapsync
+#endif
                        ) {
                int err;
                int i=0;
@@ -560,25 +637,61 @@ getNextPage:
 #endif
 
 #ifdef LDAP_CLIENT_UPDATE
-               if ( lcup ) {
-                       if (( cuber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+                if ( lcup ) {
+                        if (( cuber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+                                return EXIT_FAILURE;
+                        }
+
+                        if ( lcup_cookie.bv_len == 0 ) {
+                                err = ber_printf( cuber, "{ei}", abs(lcup), lcup_cint );
+                        } else {
+                                err = ber_printf( cuber, "{ei{sO}}", abs(lcup), lcup_cint,
+                                                LDAP_LCUP_COOKIE_OID, &lcup_cookie );
+                        }
+
+                        if ( err == LBER_ERROR ) {
+                                ber_free( cuber, 1 );
+                                fprintf( stderr, "client update control encoding error!\n" );
+                                return EXIT_FAILURE;
+                        }
+
+                        if ( ber_flatten( cuber, &cubvalp ) == LBER_ERROR ) {
+                                return EXIT_FAILURE;
+                        }
+
+                        c[i].ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE;
+                        c[i].ldctl_value = (*cubvalp);
+                        c[i].ldctl_iscritical = lcup < 0;
+                        i++;
+                }
+#endif
+
+#ifdef LDAP_SYNC
+               if ( ldapsync ) {
+                       if (( syncber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
                                return EXIT_FAILURE;
                        }
-                       err = ber_printf( cuber, "{ei{sO}}", abs(lcup), lcup_cint,
-                                       LDAP_CLIENT_UPDATE_COOKIE, &lcup_cookie);
+
+                       if ( sync_cookie.bv_len == 0 ) {
+                               err = ber_printf( syncber, "{e}", abs(ldapsync) );
+                       } else {
+                               err = ber_printf( syncber, "{eO}", abs(ldapsync),
+                                                       &sync_cookie );
+                       }
+
                        if ( err == LBER_ERROR ) {
-                               ber_free( cuber, 1 );
-                               fprintf( stderr, "client update control encoding error!\n" );
+                               ber_free( syncber, 1 );
+                               fprintf( stderr, "ldap sync control encoding error!\n" );
                                return EXIT_FAILURE;
                        }
 
-                       if ( ber_flatten( cuber, &cubvalp ) == LBER_ERROR ) {
+                       if ( ber_flatten( syncber, &syncbvalp ) == LBER_ERROR ) {
                                return EXIT_FAILURE;
                        }
 
-                       c[i].ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE;
-                       c[i].ldctl_value=(*cubvalp);
-                       c[i].ldctl_iscritical = lcup < 0;
+                       c[i].ldctl_oid = LDAP_CONTROL_SYNC;
+                       c[i].ldctl_value = (*syncbvalp);
+                       c[i].ldctl_iscritical = ldapsync < 0;
                        i++;
                }
 #endif
@@ -776,7 +889,13 @@ static int dosearch(
        int                     nextended;
        int                     npartial;
        LDAPMessage             *res, *msg;
-       ber_int_t       msgid;
+       ber_int_t               msgid;
+#ifdef LDAP_SYNC
+       char                    *retoid = NULL;
+       struct berval           *retdata = NULL;
+       int                     nresponses_psearch = -1;
+       int                     cancel_msgid = -1;
+#endif
 
        if( filtpatt != NULL ) {
                filter = malloc( strlen( filtpatt ) + strlen( value ) );
@@ -806,6 +925,8 @@ static int dosearch(
        rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
                sctrls, cctrls, timeout, sizelimit, &msgid );
 
+       printf("msgid = %d\n", msgid);
+
        if ( filtpatt != NULL ) {
                free( filter );
        }
@@ -833,7 +954,11 @@ static int dosearch(
                        msg != NULL;
                        msg = ldap_next_message( ld, msg ) )
                {
-                       if( nresponses++ ) putchar('\n');
+                       if ( nresponses++ ) putchar('\n');
+#if LDAP_SYNC
+                       if ( nresponses_psearch >= 0 ) 
+                               nresponses_psearch++;
+#endif
 
                        switch( ldap_msgtype( msg ) ) {
                        case LDAP_RES_SEARCH_ENTRY:
@@ -854,6 +979,16 @@ static int dosearch(
                                        /* unsolicited extended operation */
                                        goto done;
                                }
+
+#ifdef LDAP_SYNC
+                               if ( cancel_msgid != -1 &&
+                                               cancel_msgid == ldap_msgid( msg ) ) {
+                                       printf("Cancelled \n");
+                                       printf("cancel_msgid = %d\n", cancel_msgid);
+                                       goto done;
+                               }
+#endif
+
                                break;
 
                        case LDAP_RES_EXTENDED_PARTIAL:
@@ -866,14 +1001,62 @@ static int dosearch(
                                if ( pageSize != 0 ) { 
                                        rc = parse_page_control( ld, msg, &cookie );
                                }
+
+#ifdef LDAP_CLIENT_UPDATE
+                               if ( lcup == LDAP_CUP_PERSIST_ONLY ||
+                                    lcup == LDAP_CUP_SYNC_AND_PERSIST ) {
+                                       break;
+                               }
+#endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+                               else
+#endif
+#ifdef LDAP_SYNC
+                               if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) {
+                                       break;
+                               }
+#endif
+
                                goto done;
+
+#ifdef LDAP_SYNC
+                       case LDAP_RES_INTERMEDIATE_RESP:
+                               ldap_parse_intermediate_resp_result( ld, msg, &retoid, &retdata, 0 );
+                               nresponses_psearch = 0;
+
+                               if ( strcmp( retoid, LDAP_SYNC_INFO ) ) {
+                                       printf("Unexpected Intermediate Response\n");
+                                       ldap_memfree( retoid );
+                                       ber_bvfree( retdata );
+                                       goto done;
+                               } else {
+                                       printf("SyncInfo Received\n");
+                                       ldap_memfree( retoid );
+                                       ber_bvfree( retdata );
+                                       break;
+                               }
+#endif
                        }
+
 #ifdef LDAP_CLIENT_UPDATE
-                       if ( nresponses >= lcup_slimit ) {
+                       if ( lcup && lcup_slimit != -1 && nresponses >= lcup_slimit ) {
                                ldap_abandon (ld, ldap_msgid(msg));
                                goto done;
                        }
 #endif
+#ifdef LDAP_SYNC
+                       if ( ldapsync && sync_slimit != -1 &&
+                                       nresponses_psearch >= sync_slimit ) {
+                               BerElement *msgidber = NULL;
+                               struct berval *msgidvalp = NULL;
+                               msgidber = ber_alloc_t(LBER_USE_DER);
+                               ber_printf(msgidber, "{i}", msgid);
+                               ber_flatten(msgidber, &msgidvalp);
+                               ldap_extended_operation(ld, LDAP_EXOP_X_CANCEL,
+                                               msgidvalp, NULL, NULL, &cancel_msgid);
+                               nresponses_psearch = -1;
+                       }
+#endif
 
                }
 
index 361a8244399478e64853ad48d4286f9c553c3ed3..9b18a751101df6825c5676447ec3dc8017526f75 100644 (file)
@@ -205,11 +205,29 @@ typedef struct ldapcontrol {
 
 /*
 #define LDAP_CLIENT_UPDATE 1
+#define LDAP_SYNC 2
 */
+
 #ifdef LDAP_CLIENT_UPDATE
 #define LDAP_CONTROL_CLIENT_UPDATE             "1.3.6.1.4.1.4203.666.5.3"
 #define LDAP_CONTROL_ENTRY_UPDATE              "1.3.6.1.4.1.4203.666.5.4"
-#define LDAP_CONTROL_CLIENT_UPDATE_DONE        "1.3.6.1.4.1.4203.666.5.5"
+#define LDAP_CONTROL_CLIENT_UPDATE_DONE                "1.3.6.1.4.1.4203.666.5.5"
+#define LDAP_LCUP_COOKIE_OID                   "1.3.6.1.4.1.4203.666.10.1"
+#endif
+
+#ifdef LDAP_SYNC
+#define LDAP_CONTROL_SYNC                      "1.3.6.1.4.1.4203.666.5.TBD1"
+#define LDAP_CONTROL_SYNC_STATE                        "1.3.6.1.4.1.4203.666.5.TBD2"
+#define LDAP_CONTROL_SYNC_DONE                 "1.3.6.1.4.1.4203.666.5.TBD3"
+#define LDAP_SYNC_INFO                         "1.3.6.1.4.1.4203.666.5.TBD4"
+
+#define LDAP_SYNC_REFRESH_DONE         0
+#define LDAP_SYNC_NEW_COOKIE           1
+
+#define LDAP_SYNC_PRESENT              0
+#define LDAP_SYNC_ADD                  1
+#define LDAP_SYNC_MODIFY               2
+#define LDAP_SYNC_DELETE               3
 #endif
 
 #define LDAP_CONTROL_SORTREQUEST    "1.2.840.113556.1.4.473"
@@ -278,8 +296,12 @@ typedef struct ldapcontrol {
 #define LDAP_TAG_LDAPCRED      ((ber_tag_t) 0x04U)     /* octet string */
 
 #ifdef LDAP_CLIENT_UPDATE
-#define LDAP_TAG_COOKIE                ((ber_tag_t) 0x30U)     /* sequence */
-#endif /* LDAP_CLIENT_UPDATE */
+#define LDAP_LCUP_TAG_COOKIE   ((ber_tag_t) 0x30U)     /* sequence */
+#endif
+
+#ifdef LDAP_SYNC
+#define LDAP_SYNC_TAG_COOKIE   ((ber_tag_t) 0x04U)     /* octet string */
+#endif
 
 #define LDAP_TAG_CONTROLS      ((ber_tag_t) 0xa0U)     /* context specific + constructed + 0 */
 #define LDAP_TAG_REFERRAL      ((ber_tag_t) 0xa3U)     /* context specific + constructed + 3 */
@@ -477,15 +499,7 @@ typedef struct ldapcontrol {
 #define LDAP_CUP_UNSUPPORTED_SCHEME            0x65
 #define LDAP_CUP_CLIENT_DISCONNECT             0x66
 #define LDAP_CUP_RELOAD_REQUIRED               0x67
-
-/* LCUP update type */
-#define LDAP_CUP_SYNC_ONLY                     0x00
-#define LDAP_CUP_SYNC_AND_PERSIST      0x01
-#define LDAP_CUP_PERSIST_ONLY          0x02
-
-/* LCUP default cookie interval */
-#define LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL  0x01
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
 
 /* resultCode for Cancel Response */
 #define LDAP_CANCELLED                  0x68
@@ -498,6 +512,24 @@ typedef struct ldapcontrol {
 #define LDAP_CANCEL_ACK                 0x02
 #define LDAP_CANCEL_DONE                0x03
 
+#ifdef LDAP_CLIENT_UPDATE
+/* LCUP update type */
+#define LDAP_CUP_NONE                  0x00
+#define LDAP_CUP_SYNC_ONLY             0x01
+#define LDAP_CUP_PERSIST_ONLY          0x02
+#define LDAP_CUP_SYNC_AND_PERSIST      0x03
+
+/* LCUP default cookie interval */
+#define LDAP_CUP_DEFAULT_SEND_COOKIE_INTERVAL  0x01
+#endif /* LDAP_CLIENT_UPDATE */
+
+/* LDAP SYNC request type */
+#ifdef LDAP_SYNC
+#define LDAP_SYNC_NONE                 0x00
+#define LDAP_SYNC_REFRESH_ONLY         0x01
+#define LDAP_SYNC_REFRESH_AND_PERSIST  0x03
+#endif
+
 /*
  * This structure represents both ldap messages and ldap responses.
  * These are really the same, except in the case of search responses,
index 204cd71957211b8a36418b4d1dc65398fc18b4a8..7b6dfb68b9494d9eb587b2a0e4c715cacfdc12db 100644 (file)
@@ -92,6 +92,18 @@ static struct ldaperror ldap_builtin_errlist[] = {
        {LDAP_MORE_RESULTS_TO_RETURN,   "More results to return" },
        {LDAP_CLIENT_LOOP,                              "Client Loop" },
        {LDAP_REFERRAL_LIMIT_EXCEEDED,  "Referral Limit Exceeded" },
+#ifdef LDAP_CLIENT_UPDATE
+       {LDAP_CUP_RESOURCES_EXHAUSTED,  "LDAP Client Update Resource Exhausted" },
+       {LDAP_CUP_SECURITY_VIOLATION,   "LDAP Client Update Security Violation" },
+       {LDAP_CUP_INVALID_COOKIE,       "LDAP Client Update Invalid Cookie" },
+       {LDAP_CUP_UNSUPPORTED_SCHEME,   "LDAP Client Update Unsupported Scheme" },
+       {LDAP_CUP_CLIENT_DISCONNECT,    "LDAP Client Update Client Disconnect" },
+       {LDAP_CUP_RELOAD_REQUIRED,      "LDAP Client Update Reload Required" },
+#endif
+       {LDAP_CANCELLED,                "LDAP Cancelled" },
+       {LDAP_NO_SUCH_OPERATION,        "LDAP No Operation to Cancel" },
+       {LDAP_TOO_LATE,                 "LDAP Too Late to Cancel" },
+       {LDAP_CANNOT_CANCEL,            "LDAP Cannot Cancel" },
 
        {-1, NULL}
 };
index 593c57206ccc4a94c12560a3002c4adf1166f09b..33bd0ab159e490793c3840178cc5dc5e2f954dfb 100644 (file)
@@ -109,7 +109,7 @@ do_abandon(
 
 done:
 
-#if LDAP_CLIENT_UPDATE
+#ifdef LDAP_CLIENT_UPDATE
        for ( i = 0; i < nbackends; i++ ) {
                if ( strncmp( backends[i].be_type, "bdb", 3 ) ) continue;
                if ( bdb_abandon( &backends[i], conn, id ) == LDAP_SUCCESS ) {
index 4ca3700ee92e9c7173f4558adbb8270a4d2090e2..8bc54ede34e28fb781d23d7b3a9ffe68bb550330 100644 (file)
@@ -42,7 +42,7 @@ bdb_add(
 #endif
        int             noop = 0;
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        Operation* ps_list;
 #endif
 
@@ -547,10 +547,10 @@ return_results:
        send_ldap_result( conn, op, rc,
                NULL, text, NULL, NULL );
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        if ( rc == LDAP_SUCCESS && !noop ) {
                LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
-                       bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_ADD );
+                       bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_ADD );
                }
        }
 #endif /* LDAP_CLIENT_UPDATE */
index 8ba473fe97a068ae02ad53af265d7a2d9b05cf5c..e306c86438edbe534e50496970ad990a24e02121 100644 (file)
@@ -132,7 +132,7 @@ struct bdb_info {
 
        ID                      bi_lastid;
        ldap_pvt_thread_mutex_t bi_lastid_mutex;
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        LDAP_LIST_HEAD(pl, slap_op) psearch_list;
 #endif
 #ifdef SLAP_IDL_CACHE
index 5d7f432a13e084abe3a5ecd4db842244f5646e51..e31f250f81ff688927d0afad799ddc8124e47803 100644 (file)
@@ -44,7 +44,7 @@ bdb_delete(
 
        int             noop = 0;
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        Operation* ps_list;
 #endif
 
@@ -493,13 +493,13 @@ retry:    /* transaction retry */
 return_results:
        send_ldap_result( conn, op, rc, NULL, text, NULL, NULL );
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
         if ( rc == LDAP_SUCCESS && !noop ) {
                LDAP_LIST_FOREACH( ps_list, &bdb->psearch_list, link ) {
-                       bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_DELETE );
+                       bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_DELETE );
                }
        }
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
 
        if(rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
                ldap_pvt_thread_yield();
index 0ad31a1782fe68c1f27c3b460626535235626efd..2f2bb16acc55c0bcf83fb9de971a98164b75202d 100644 (file)
@@ -95,7 +95,7 @@ bdb_db_init( BackendDB *be )
        bdb->bi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
        bdb->bi_search_stack = NULL;
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        LDAP_LIST_INIT (&bdb->psearch_list);
 #endif
 
index 099ee20279570a43fa19aceed33d95562043e9ad..6217c3651482cf437dc5765cf353cb9ee04130a1 100644 (file)
 #include "idl.h"
 #include "external.h"
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+
+#define IS_BDB_REPLACE (( psearch_type == LDAP_PSEARCH_BY_DELETE ) || \
+                      ( psearch_type == LDAP_PSEARCH_BY_SCOPEOUT ))
+#define IS_BDB_LCUP_REPLACE (( protocol == LDAP_CLIENT_UPDATE ) && IS_BDB_REPLACE )
 
 static int psearch_base_candidate(
        BackendDB       *be,
-       Entry   *e,
+       Entry           *e,
        ID              *ids );
+
 static int psearch_candidates(
-       BackendDB *be,
-       Operation *op,
-       Entry *e,
-       Filter *filter,
-       int scope,
-       int deref,
-       ID      *ids );
+       BackendDB       *be,
+       Operation       *op,
+       Entry           *e,
+       Filter          *filter,
+       int             scope,
+       int             deref,
+       ID              *ids );
 
 int
 bdb_abandon(
@@ -50,6 +55,39 @@ bdb_abandon(
        return LDAP_UNAVAILABLE;
 }
 
+int
+bdb_cancel(
+       BackendDB       *be,
+       Connection      *conn,
+       ber_int_t       id )
+{
+       Operation       *ps_list;
+       struct bdb_info *bdb = (struct bdb_info *) be->be_private;
+
+       LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
+               if ( ps_list->o_connid == conn->c_connid ) {
+                       if ( ps_list->o_msgid == id ) {
+                               ps_list->o_cancel = LDAP_CANCEL_DONE;
+                               LDAP_LIST_REMOVE( ps_list, link );
+
+#if 0
+                               bdb_build_sync_done_ctrl( conn, ps_list, ps_list->ctrls, 1, &latest_entrycsn_bv );
+                               send_search_result( conn, ps_list, LDAP_CANCELLED,
+                                               NULL, NULL, NULL, ps_list->ctrls, ps_list->nentries);
+#endif
+                               send_search_result( conn, ps_list, LDAP_CANCELLED,
+                                               NULL, NULL, NULL, NULL, 0);
+
+
+
+                               slap_op_free ( ps_list );
+                               return LDAP_SUCCESS;
+                       }
+               }
+       }
+       return LDAP_UNAVAILABLE;
+}
+
 int
 bdb_add_psearch_spec(
        BackendDB       *be,
@@ -64,30 +102,33 @@ bdb_add_psearch_spec(
        Filter          *filter,
        struct berval   *fstr,
        AttributeName   *attrs,
-       int             attrsonly )
+       int             attrsonly,
+       int             protocol        )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
 
-       LDAP_LIST_FIRST(&op->psearch_spec) = (struct lcup_search_spec *)
-               calloc ( 1, sizeof ( struct lcup_search_spec ) );
+       LDAP_LIST_FIRST( &op->psearch_spec ) = (struct ldap_psearch_spec *)
+               calloc ( 1, sizeof ( struct ldap_psearch_spec ) );
 
-       LDAP_LIST_FIRST(&op->psearch_spec)->op = op;
+       LDAP_LIST_FIRST( &op->psearch_spec )->op = op;
 
-       LDAP_LIST_FIRST(&op->psearch_spec)->base = ber_dupbv(NULL, base);
-       LDAP_LIST_FIRST(&op->psearch_spec)->nbase = ber_dupbv(NULL, nbase);
+       LDAP_LIST_FIRST( &op->psearch_spec )->base = ber_dupbv(NULL, base);
+       LDAP_LIST_FIRST( &op->psearch_spec )->nbase = ber_dupbv(NULL, nbase);
 
-       LDAP_LIST_FIRST(&op->psearch_spec)->scope = scope;
-       LDAP_LIST_FIRST(&op->psearch_spec)->deref = deref;
-       LDAP_LIST_FIRST(&op->psearch_spec)->slimit = slimit;
-       LDAP_LIST_FIRST(&op->psearch_spec)->tlimit = tlimit;
+       LDAP_LIST_FIRST( &op->psearch_spec )->scope = scope;
+       LDAP_LIST_FIRST( &op->psearch_spec )->deref = deref;
+       LDAP_LIST_FIRST( &op->psearch_spec )->slimit = slimit;
+       LDAP_LIST_FIRST( &op->psearch_spec )->tlimit = tlimit;
 
-       LDAP_LIST_FIRST(&op->psearch_spec)->filter = filter;
-       LDAP_LIST_FIRST(&op->psearch_spec)->filterstr = ber_dupbv(NULL, fstr);
-       LDAP_LIST_FIRST(&op->psearch_spec)->attrs = attrs;
+       LDAP_LIST_FIRST( &op->psearch_spec )->filter = filter;
+       LDAP_LIST_FIRST( &op->psearch_spec )->filterstr = ber_dupbv(NULL, fstr);
+       LDAP_LIST_FIRST( &op->psearch_spec )->attrs = attrs;
 
-       LDAP_LIST_FIRST(&op->psearch_spec)->attrsonly = attrsonly;
+       LDAP_LIST_FIRST( &op->psearch_spec )->attrsonly = attrsonly;
 
-       LDAP_LIST_FIRST(&op->psearch_spec)->entry_count = 0;
+       LDAP_LIST_FIRST( &op->psearch_spec )->entry_count = 0;
+
+       LDAP_LIST_FIRST( &op->psearch_spec )->protocol = protocol;
 
        LDAP_LIST_INSERT_HEAD( &bdb->psearch_list, op, link );
 }
@@ -99,26 +140,29 @@ bdb_psearch(
        Operation       *op,
        Operation       *ps_op,
        Entry           *entry,
-       int             psearch_type )
+       int             psearch_type    )
 {
        struct bdb_info *bdb = (struct bdb_info *) be->be_private;
        int             rc;
-       const char *text = NULL;
+       const char      *text = NULL;
        time_t          stoptime;
        unsigned        cursor;
        ID              id;
        ID              candidates[BDB_IDL_UM_SIZE];
        Entry           *e = NULL;
-       BerVarray v2refs = NULL;
-       Entry   *matched = NULL;
+       BerVarray       v2refs = NULL;
+       Entry           *matched = NULL;
        struct berval   realbase = { 0, NULL };
        int             nentries = 0;
        int             manageDSAit;
 
-       Filter lcupf, csnfnot, csnfeq, csnfand, csnfge;
-       AttributeAssertion aa_ge, aa_eq;
-       struct berval entrycsn_bv = { 0, NULL };
-       struct berval latest_entrycsn_bv = { 0, NULL };
+       Filter          cookief, csnfnot, csnfeq, csnfand, csnfge;
+       AttributeAssertion      aa_ge, aa_eq;
+       struct berval   entrycsn_bv = { 0, NULL };
+       struct berval   latest_entrycsn_bv = { 0, NULL };
+
+        LDAPControl     *ctrls[SLAP_SEARCH_MAX_CTRLS];
+        int             num_ctrls = 0;
 
        struct slap_limits_set *limit = NULL;
        int isroot = 0;
@@ -128,31 +172,18 @@ bdb_psearch(
        DB_LOCK         lock;
 
        Connection      *ps_conn   = ps_op->o_conn;
-       struct berval   *base      = LDAP_LIST_FIRST(&ps_op->psearch_spec)->base;
-       struct berval   *nbase     = LDAP_LIST_FIRST(&ps_op->psearch_spec)->nbase;
-       int             scope      = LDAP_LIST_FIRST(&ps_op->psearch_spec)->scope;
-       int             deref      = LDAP_LIST_FIRST(&ps_op->psearch_spec)->deref;
-       int             slimit     = LDAP_LIST_FIRST(&ps_op->psearch_spec)->slimit;
-       int             tlimit     = LDAP_LIST_FIRST(&ps_op->psearch_spec)->tlimit;
-       Filter          *filter    = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filter;
-       struct berval *filterstr = LDAP_LIST_FIRST(&ps_op->psearch_spec)->filterstr;
-       int             attrsonly  = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrsonly;
+       struct berval   *base      = LDAP_LIST_FIRST( &ps_op->psearch_spec )->base;
+       struct berval   *nbase     = LDAP_LIST_FIRST( &ps_op->psearch_spec )->nbase;
+       int             scope      = LDAP_LIST_FIRST( &ps_op->psearch_spec )->scope;
+       int             deref      = LDAP_LIST_FIRST( &ps_op->psearch_spec )->deref;
+       int             slimit     = LDAP_LIST_FIRST( &ps_op->psearch_spec )->slimit;
+       int             tlimit     = LDAP_LIST_FIRST( &ps_op->psearch_spec )->tlimit;
+       Filter          *filter    = LDAP_LIST_FIRST( &ps_op->psearch_spec )->filter;
+       struct berval   *filterstr = LDAP_LIST_FIRST( &ps_op->psearch_spec )->filterstr;
+       int             attrsonly  = LDAP_LIST_FIRST( &ps_op->psearch_spec )->attrsonly;
+       int             protocol   = LDAP_LIST_FIRST( &ps_op->psearch_spec )->protocol;
        AttributeName   uuid_attr[2];
-       AttributeName   *attrs = uuid_attr;
-
-       if ( psearch_type != LCUP_PSEARCH_BY_DELETE &&
-               psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
-       {
-               attrs = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrs;
-       } else {
-               attrs[0].an_desc = slap_schema.si_ad_entryUUID;
-               attrs[0].an_oc = NULL;
-               ber_dupbv( &attrs[0].an_name, &attrs[0].an_desc->ad_cname );
-               attrs[1].an_desc = NULL;
-               attrs[1].an_oc = NULL;
-               attrs[1].an_name.bv_len = 0;
-               attrs[1].an_name.bv_val = NULL;
-       }
+       AttributeName   *attrs;
 
 #ifdef NEW_LOGGING
        LDAP_LOG ( OPERATION, ENTRY, "bdb_back_search\n", 0, 0, 0 );
@@ -170,10 +201,41 @@ bdb_psearch(
        default:
                send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
                        NULL, "internal error", NULL, NULL );
-               if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
-                    psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
-                       ch_free( attrs[0].an_name.bv_val );
                return rc;
+       }       
+
+        for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ )
+                ctrls[num_ctrls] = NULL;
+        num_ctrls = 0;
+
+       if ( !IS_BDB_REPLACE ) {
+               attrs = LDAP_LIST_FIRST(&ps_op->psearch_spec)->attrs;
+       } else {
+#ifdef LDAP_CLIENT_UPDATE
+               if ( protocol == LDAP_CLIENT_UPDATE ) {
+                       attrs = uuid_attr;
+                       attrs[0].an_desc = slap_schema.si_ad_entryUUID;
+                       attrs[0].an_oc = NULL;
+                       ber_dupbv( &attrs[0].an_name, &attrs[0].an_desc->ad_cname );
+                       attrs[1].an_desc = NULL;
+                       attrs[1].an_oc = NULL;
+                       attrs[1].an_name.bv_len = 0;
+                       attrs[1].an_name.bv_val = NULL;
+               } else
+#endif
+#ifdef LDAP_SYNC
+               if (protocol == LDAP_SYNC ) {
+                       attrs = uuid_attr;
+                       attrs[0].an_desc = NULL;
+                       attrs[0].an_oc = NULL;
+                       attrs[0].an_name.bv_len = 0;
+                       attrs[0].an_name.bv_val = NULL;
+               } else
+#endif
+               {
+                       rc = 1;
+                       goto done;
+               }
        }
 
        if ( nbase->bv_len == 0 ) {
@@ -209,9 +271,10 @@ dn2entry_retry:
                send_ldap_result( ps_conn, ps_op, LDAP_BUSY,
                        NULL, "ldap server busy", NULL, NULL );
                LOCK_ID_FREE( bdb->bi_dbenv, locker );
-               if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
-                    psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+               if ( IS_BDB_LCUP_REPLACE )
                        ch_free( attrs[0].an_name.bv_val );
+#endif
                return LDAP_BUSY;
        case DB_LOCK_DEADLOCK:
        case DB_LOCK_NOTGRANTED:
@@ -228,9 +291,10 @@ dn2entry_retry:
                send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
                        NULL, "internal error", NULL, NULL );
                LOCK_ID_FREE( bdb->bi_dbenv, locker );
-               if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
-                    psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+               if ( IS_BDB_LCUP_REPLACE )
                        ch_free( attrs[0].an_name.bv_val );
+#endif
                return rc;
        }
 
@@ -267,9 +331,10 @@ dn2entry_retry:
                LOCK_ID_FREE( bdb->bi_dbenv, locker );
                if ( refs ) ber_bvarray_free( refs );
                if ( matched_dn.bv_val ) ber_memfree( matched_dn.bv_val );
-               if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
-                    psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+               if ( IS_BDB_LCUP_REPLACE )
                        ch_free( attrs[0].an_name.bv_val );
+#endif
                return rc;
        }
 
@@ -307,9 +372,10 @@ dn2entry_retry:
                LOCK_ID_FREE( bdb->bi_dbenv, locker );
                ber_bvarray_free( refs );
                ber_memfree( matched_dn.bv_val );
-               if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
-                    psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+               if ( IS_BDB_LCUP_REPLACE )
                        ch_free( attrs[0].an_name.bv_val );
+#endif
                return 1;
        }
 
@@ -444,28 +510,61 @@ dn2entry_retry:
                }
        }
 
-       lcupf.f_choice = LDAP_FILTER_AND;
-       lcupf.f_and = &csnfnot;
-       lcupf.f_next = NULL;
-
-       csnfnot.f_choice = LDAP_FILTER_NOT;
-       csnfnot.f_not = &csnfeq;
-       csnfnot.f_next = &csnfand;
-
-       csnfeq.f_choice = LDAP_FILTER_EQUALITY;
-       csnfeq.f_ava = &aa_eq;
-       csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
-       ber_dupbv( &csnfeq.f_av_value, &ps_op->o_clientupdate_state );
-
-       csnfand.f_choice = LDAP_FILTER_AND;
-       csnfand.f_and = &csnfge;
-       csnfand.f_next = NULL;
-
-       csnfge.f_choice = LDAP_FILTER_GE;
-       csnfge.f_ava = &aa_ge;
-       csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
-       ber_dupbv( &csnfge.f_av_value, &ps_op->o_clientupdate_state );
-       csnfge.f_next = filter;
+#ifdef LDAP_CLIENT_UPDATE
+       if ( protocol == LDAP_CLIENT_UPDATE ) {
+               cookief.f_choice = LDAP_FILTER_AND;
+               cookief.f_and = &csnfnot;
+               cookief.f_next = NULL;
+       
+               csnfnot.f_choice = LDAP_FILTER_NOT;
+               csnfnot.f_not = &csnfeq;
+               csnfnot.f_next = &csnfand;
+
+               csnfeq.f_choice = LDAP_FILTER_EQUALITY;
+               csnfeq.f_ava = &aa_eq;
+               csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
+               ber_dupbv( &csnfeq.f_av_value, &ps_op->o_clientupdate_state );
+
+               csnfand.f_choice = LDAP_FILTER_AND;
+               csnfand.f_and = &csnfge;
+               csnfand.f_next = NULL;
+       
+               csnfge.f_choice = LDAP_FILTER_GE;
+               csnfge.f_ava = &aa_ge;
+               csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
+               ber_dupbv( &csnfge.f_av_value, &ps_op->o_clientupdate_state );
+               csnfge.f_next = filter;
+       }
+#endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+       else
+#endif
+#ifdef LDAP_SYNC
+       if ( protocol == LDAP_SYNC ) {
+               cookief.f_choice = LDAP_FILTER_AND;
+               cookief.f_and = &csnfnot;
+               cookief.f_next = NULL;
+       
+               csnfnot.f_choice = LDAP_FILTER_NOT;
+               csnfnot.f_not = &csnfeq;
+               csnfnot.f_next = &csnfand;
+
+               csnfeq.f_choice = LDAP_FILTER_EQUALITY;
+               csnfeq.f_ava = &aa_eq;
+               csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
+               ber_dupbv( &csnfeq.f_av_value, &ps_op->o_sync_state );
+
+               csnfand.f_choice = LDAP_FILTER_AND;
+               csnfand.f_and = &csnfge;
+               csnfand.f_next = NULL;
+       
+               csnfge.f_choice = LDAP_FILTER_GE;
+               csnfge.f_ava = &aa_ge;
+               csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
+               ber_dupbv( &csnfge.f_av_value, &ps_op->o_sync_state );
+               csnfge.f_next = filter;
+       }
+#endif
 
        id = entry->e_id;
 
@@ -604,8 +703,8 @@ dn2entry_retry:
                goto test_done;
        }
 
-       if ( psearch_type != LCUP_PSEARCH_BY_SCOPEOUT ) {
-               rc = test_filter( be, ps_conn, ps_op, e, &lcupf );
+       if ( psearch_type != LDAP_PSEARCH_BY_SCOPEOUT ) {
+               rc = test_filter( be, ps_conn, ps_op, e, &cookief );
        } else {
                rc = LDAP_COMPARE_TRUE;
        }
@@ -647,144 +746,87 @@ dn2entry_retry:
                                } else
 #endif
                                {
-                                       if ( psearch_type == LCUP_PSEARCH_BY_ADD ||
-                                            psearch_type == LCUP_PSEARCH_BY_DELETE ||
-                                            psearch_type == LCUP_PSEARCH_BY_MODIFY ||
-                                            psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
-                                       {
-                                               Attribute* a;
-                                               int ret;
-                                               int res;
-                                               const char *text = NULL;
-                                               LDAPControl *ctrls[2];
-                                               struct berval *bv;
-                                               char berbuf[LBER_ELEMENT_SIZEOF];
-                                               BerElement *ber = (BerElement *)berbuf;
-                                               
-                                               ber_init2( ber, NULL, LBER_USE_DER );
-
-                                               LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count++;
-
-                                               ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
-                                               ctrls[1] = NULL;
-
-                                               if ( LDAP_LIST_FIRST(
-                                                       &ps_op->psearch_spec)->entry_count %
-                                                               ps_op->o_clientupdate_interval == 0 )
-                                               {
-                                                       /* Send cookie */
-                                                       for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
-                                                               AttributeDescription *desc = a->a_desc;
-                                                               if ( desc == slap_schema.si_ad_entryCSN ) {
-                                                                       ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
-                                                                       if ( latest_entrycsn_bv.bv_val == NULL ) {
-                                                                               ber_dupbv( &latest_entrycsn_bv,
-                                                                                       &entrycsn_bv );
-                                                                       } else {
-                                                                               res = value_match( &ret, desc,
-                                                                                       desc->ad_type->sat_ordering,
-                                                                                       SLAP_MR_ASSERTION_SYNTAX_MATCH,
-                                                                                       &entrycsn_bv, &latest_entrycsn_bv,
-                                                                                       &text );
-                                                                               if ( res != LDAP_SUCCESS ) {
-                                                                                       ret = 0;
-#ifdef NEW_LOGGING
-                                                                                       LDAP_LOG ( OPERATION, RESULTS, 
-                                                                                               "bdb_search: "
-                                                                                               "value_match failed\n",
-                                                                                               0, 0, 0 );
-#else
-                                                                                       Debug( LDAP_DEBUG_TRACE,
-                                                                                               "bdb_search: "
-                                                                                               "value_match failed\n",
-                                                                                               0, 0, 0 );
-#endif
-                                                                               }
-
-                                                                               if ( ret > 0 ) {
-                                                                                       ch_free(latest_entrycsn_bv.bv_val);
-                                                                                       latest_entrycsn_bv.bv_val = NULL;
-                                                                                       ber_dupbv( &latest_entrycsn_bv,
-                                                                                               &entrycsn_bv );
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }
-
-                                                       if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
-                                                               psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
-                                                       {
-                                                               ber_printf( ber, "{bb{sON}N}",
-                                                                       SLAP_LCUP_STATE_UPDATE_FALSE,
-                                                                       SLAP_LCUP_ENTRY_DELETED_FALSE,
-                                                                       LCUP_COOKIE_OID, &entrycsn_bv );
-                                                       } else {
-                                                               ber_printf( ber, "{bb{sON}N}",
-                                                                       SLAP_LCUP_STATE_UPDATE_FALSE,
-                                                                       SLAP_LCUP_ENTRY_DELETED_TRUE,
-                                                                       LCUP_COOKIE_OID, &entrycsn_bv );
-                                                       }
-
-                                                       ch_free( entrycsn_bv.bv_val );
-                                                       entrycsn_bv.bv_val = NULL;
-
-                                               } else {
-                                                       /* Do not send cookie */
-                                                       if ( psearch_type != LCUP_PSEARCH_BY_DELETE ||
-                                                               psearch_type != LCUP_PSEARCH_BY_SCOPEOUT )
-                                                       {
-                                                               ber_printf( ber, "{bbN}",
-                                                                       SLAP_LCUP_STATE_UPDATE_FALSE,
-                                                                       SLAP_LCUP_ENTRY_DELETED_FALSE );
-                                                       } else {
-                                                               ber_printf( ber, "{bbN}",
-                                                                       SLAP_LCUP_STATE_UPDATE_FALSE,
-                                                                       SLAP_LCUP_ENTRY_DELETED_TRUE );
-                                                       }
-                                               }
-
-                                               ctrls[0]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
-                                               ctrls[0]->ldctl_iscritical = ps_op->o_clientupdate;
-                                               ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
-
-                                               if ( ret < 0 ) {
-                                                       ber_free_buf( ber );
-#ifdef NEW_LOGGING
-                                                       LDAP_LOG ( OPERATION, RESULTS, 
-                                                               "bdb_search: ber_flatten2 failed\n",
-                                                               0, 0, 0 );
-#else
-                                                       Debug( LDAP_DEBUG_TRACE,
-                                                               "bdb_search: ber_flatten2 failed\n",
-                                                               0, 0, 0 );
+#ifdef LDAP_SYNC
+                                               int premodify_found = 0;
+                                               int entry_sync_state;
 #endif
-                                                       send_ldap_result( ps_conn, ps_op, rc=LDAP_OTHER,
-                                                               NULL, "internal error", NULL, NULL );
-                                                       goto done;
-                                               }
-
-                                               result = send_search_entry( be, ps_conn, ps_op,
-                                                       e, attrs, attrsonly, ctrls);
-
-                                               ber_free_buf( ber );
-                                               ch_free( ctrls[0] );
 
-                                               if ( psearch_type == LCUP_PSEARCH_BY_MODIFY ) {
+                                       if ( psearch_type == LDAP_PSEARCH_BY_ADD ||
+                                            psearch_type == LDAP_PSEARCH_BY_DELETE ||
+                                            psearch_type == LDAP_PSEARCH_BY_MODIFY ||
+                                            psearch_type == LDAP_PSEARCH_BY_SCOPEOUT )
+                                       {
+                                               if ( psearch_type == LDAP_PSEARCH_BY_MODIFY ) {
                                                        struct psid_entry* psid_e;
-                                                       LDAP_LIST_FOREACH( psid_e, &op->premodify_list,
-                                                               link)
+                                                       LDAP_LIST_FOREACH( psid_e, &op->premodify_list, link)
                                                        {
-                                                               if( psid_e->ps ==
-                                                                       LDAP_LIST_FIRST(&ps_op->psearch_spec))
+                                                               if( psid_e->ps == LDAP_LIST_FIRST(&ps_op->psearch_spec))
                                                                {
+#ifdef LDAP_SYNC
+                                                                       premodify_found = 1;
+#endif
                                                                        LDAP_LIST_REMOVE(psid_e, link);
                                                                        break;
                                                                }
                                                        }
                                                        if (psid_e != NULL) free (psid_e);
                                                }
+#ifdef LDAP_SYNC
+                                               if ( psearch_type == LDAP_PSEARCH_BY_ADD )
+                                                       entry_sync_state = LDAP_SYNC_ADD;
+                                               else if ( psearch_type == LDAP_PSEARCH_BY_DELETE )
+                                                       entry_sync_state = LDAP_SYNC_DELETE;
+                                               else if ( psearch_type == LDAP_PSEARCH_BY_MODIFY ) {
+                                                       if ( premodify_found )
+                                                               entry_sync_state = LDAP_SYNC_MODIFY;
+                                                       else
+                                                               entry_sync_state = LDAP_SYNC_ADD;
+                                               } else if ( psearch_type == LDAP_PSEARCH_BY_SCOPEOUT )
+                                                       entry_sync_state = LDAP_SYNC_DELETE;
+                                               else {
+                                                       rc = 1;
+                                                       goto done;
+                                               }
+#endif
+
+#ifdef LDAP_CLIENT_UPDATE
+                                               if ( protocol == LDAP_CLIENT_UPDATE ) {
+                                                       int entry_count = ++(LDAP_LIST_FIRST(&ps_op->psearch_spec)->entry_count);
+                                                       if ( IS_BDB_REPLACE ) {
+                                                               rc = bdb_build_lcup_update_ctrl( ps_conn, ps_op, e, entry_count, ctrls,
+                                                                               num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_TRUE );
+                                                       } else {
+                                                               rc = bdb_build_lcup_update_ctrl( ps_conn, ps_op, e, entry_count, ctrls,
+                                                                               num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_FALSE );
+                                                       }
+                                                       if ( rc != LDAP_SUCCESS )
+                                                               goto done;
+                                                       result = send_search_entry( be, ps_conn, ps_op, e, attrs, attrsonly, ctrls );
+                                                       if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+                                                               ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+                                                       ch_free( ctrls[--num_ctrls] );
+                                                       ctrls[num_ctrls] = NULL;
+                                               } else
+#endif
+#ifdef LDAP_SYNC
+                                               if ( protocol == LDAP_SYNC ) {
+                                                       rc = bdb_build_sync_state_ctrl( ps_conn, ps_op, e, entry_sync_state, ctrls,
+                                                                                       num_ctrls++, 1, &latest_entrycsn_bv );
+                                                       if ( rc != LDAP_SUCCESS )
+                                                               goto done;
+                                                       result = send_search_entry( be, ps_conn, ps_op, e, attrs, attrsonly, ctrls );
+                                                       if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+                                                               ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+                                                       ch_free( ctrls[--num_ctrls] );
+                                                       ctrls[num_ctrls] = NULL;
+                                               } else
+#endif
+                                               {
+                                                       rc = 1;
+                                                       goto done;
+                                               }
 
-                                       } else if ( psearch_type == LCUP_PSEARCH_BY_PREMODIFY ) {
+                                       } else if ( psearch_type == LDAP_PSEARCH_BY_PREMODIFY ) {
                                                struct psid_entry* psid_e;
                                                psid_e = (struct psid_entry *) calloc (1,
                                                        sizeof(struct psid_entry));
@@ -844,9 +886,10 @@ done:
 
        if( v2refs ) ber_bvarray_free( v2refs );
        if( realbase.bv_val ) ch_free( realbase.bv_val );
-       if ( psearch_type == LCUP_PSEARCH_BY_DELETE ||
-            psearch_type == LCUP_PSEARCH_BY_SCOPEOUT )
+#ifdef LDAP_CLIENT_UPDATE
+       if ( IS_BDB_LCUP_REPLACE )
                ch_free( attrs[0].an_name.bv_val );
+#endif
 
        return rc;
 }
@@ -1034,4 +1077,4 @@ static int psearch_candidates(
 }
 
 
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
index 92f376fa17d1b2c09c17ed28bc8db41866724ba1..400b143596205e79842c570e28f09689679d9f75 100644 (file)
@@ -277,7 +277,7 @@ bdb_modify(
 
        int             noop = 0;
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        Operation* ps_list;
        struct psid_entry* pm_list;
        struct psid_entry* pm_prev;
@@ -302,7 +302,7 @@ retry:      /* transaction retry */
                        "bdb_modify: retrying...\n", 0, 0, 0);
 #endif
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
                pm_list = LDAP_LIST_FIRST(&op->premodify_list);
                while ( pm_list != NULL ) {
                        LDAP_LIST_REMOVE ( pm_list, link );
@@ -423,13 +423,13 @@ retry:    /* transaction retry */
                goto done;
        }
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        if ( rc == LDAP_SUCCESS && !op->o_noop ) {
                LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
-                       bdb_psearch(be, conn, op, ps_list, e, LCUP_PSEARCH_BY_PREMODIFY );
+                       bdb_psearch(be, conn, op, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
                }
        }
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
        
        /* Modify the entry */
        rc = bdb_modify_internal( be, conn, op, ltid, modlist, e,
@@ -518,23 +518,23 @@ return_results:
        send_ldap_result( conn, op, rc,
                NULL, text, NULL, NULL );
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        if ( rc == LDAP_SUCCESS && !op->o_noop ) {
                /* Loop through in-scope entries for each psearch spec */
                LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
-                       bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_MODIFY );
+                       bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_MODIFY );
                }
                pm_list = LDAP_LIST_FIRST(&op->premodify_list);
                while ( pm_list != NULL ) {
                        bdb_psearch(be, conn, op, pm_list->ps->op,
-                                               e, LCUP_PSEARCH_BY_SCOPEOUT);
+                                               e, LDAP_PSEARCH_BY_SCOPEOUT);
                        LDAP_LIST_REMOVE ( pm_list, link );
                        pm_prev = pm_list;
                        pm_list = LDAP_LIST_NEXT ( pm_list, link );
                        free (pm_prev);
                }
        }
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
 
        if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
                ldap_pvt_thread_yield();
@@ -544,7 +544,7 @@ return_results:
 
 done:
        if( ltid != NULL ) {
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
                pm_list = LDAP_LIST_FIRST(&op->premodify_list);
                while ( pm_list != NULL ) {
                        LDAP_LIST_REMOVE ( pm_list, link );
index 60019a526478e4eb0f6cdae5709eff3282603c7d..23d4d6cb84fc939cedc1752919869e627b00eddc 100644 (file)
@@ -62,7 +62,7 @@ bdb_modrdn(
 
        int             noop = 0;
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
         Operation* ps_list;
         struct psid_entry* pm_list;
         struct psid_entry* pm_prev;
@@ -95,7 +95,7 @@ retry:        /* transaction retry */
                Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn: retrying...\n", 0, 0, 0 );
 #endif
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
                 pm_list = LDAP_LIST_FIRST(&op->premodify_list);
                 while ( pm_list != NULL ) {
                         LDAP_LIST_REMOVE ( pm_list, link );
@@ -731,13 +731,13 @@ retry:    /* transaction retry */
                goto return_results;
        }
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        if ( rc == LDAP_SUCCESS && !op->o_noop ) {
                LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
-                       bdb_psearch(be, conn, op, ps_list, e, LCUP_PSEARCH_BY_PREMODIFY );
+                       bdb_psearch(be, conn, op, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
                }
        }
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
 
        /* modify entry */
        rc = bdb_modify_internal( be, conn, op, ltid, &mod[0], e,
@@ -833,23 +833,23 @@ return_results:
        send_ldap_result( conn, op, rc,
                NULL, text, NULL, NULL );
 
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
        if ( rc == LDAP_SUCCESS && !op->o_noop ) {
                /* Loop through in-scope entries for each psearch spec */
                LDAP_LIST_FOREACH ( ps_list, &bdb->psearch_list, link ) {
-                       bdb_psearch( be, conn, op, ps_list, e, LCUP_PSEARCH_BY_MODIFY );
+                       bdb_psearch( be, conn, op, ps_list, e, LDAP_PSEARCH_BY_MODIFY );
                }
                pm_list = LDAP_LIST_FIRST(&op->premodify_list);
                while ( pm_list != NULL ) {
                        bdb_psearch(be, conn, op, pm_list->ps->op,
-                                               e, LCUP_PSEARCH_BY_SCOPEOUT);
+                                               e, LDAP_PSEARCH_BY_SCOPEOUT);
                        LDAP_LIST_REMOVE ( pm_list, link );
                        pm_prev = pm_list;
                        pm_list = LDAP_LIST_NEXT ( pm_list, link );
                         free (pm_prev);
                }
        }
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
 
        if( rc == LDAP_SUCCESS && bdb->bi_txn_cp ) {
                ldap_pvt_thread_yield();
@@ -893,7 +893,7 @@ done:
        }
 
        if( ltid != NULL ) {
-#ifdef LDAP_CLIENT_UPDATE
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
                 pm_list = LDAP_LIST_FIRST(&op->premodify_list);
                 while ( pm_list != NULL ) {
                         LDAP_LIST_REMOVE ( pm_list, link );
index 9365b4f3b230f6093ffe2b033dd5bbce7b9f4e96..5ec4228d434f27007586aed40c257c16dfbbaa35 100644 (file)
@@ -364,13 +364,19 @@ int bdb_cache_delete_entry(
 );
 void bdb_cache_release_all( Cache *cache );
 
+/*
+ * lcup.c
+ */
+
 #ifdef LDAP_CLIENT_UPDATE
 int bdb_abandon(
        BackendDB       *be,
        Connection      *conn,
        ber_int_t       id
 );
+#endif
 
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
 int bdb_add_psearch_spec(
        BackendDB       *be,
        Connection      *conn,
@@ -384,7 +390,8 @@ int bdb_add_psearch_spec(
        Filter          *filter,
        struct berval   *fstr,
        AttributeName   *attrs,
-       int             attrsonly
+       int             attrsonly,
+       int             protocol
 );
 
 int bdb_psearch(
@@ -395,7 +402,66 @@ int bdb_psearch(
        Entry           *entry,
        int             psearch_type
 );
+#endif
+
+/*
+ * search.c
+ */
 
+#ifdef LDAP_CLIENT_UPDATE
+int
+bdb_build_lcup_update_ctrl(
+       Connection      *conn,
+       Operation       *op,
+       Entry           *e,
+       int             entry_count,
+       LDAPControl     **ctrls,
+       int             num_ctrls,
+       struct berval   *latest_entrycsn_bv,
+       int             isdeleted       );
+
+int
+bdb_build_lcup_done_ctrl(
+       Connection      *conn,
+       Operation       *op,
+       LDAPControl     **ctrls,
+       int             num_ctrls,
+       struct berval   *latest_entrycsn_bv     );
+#endif
+
+#ifdef LDAP_SYNC
+int
+bdb_build_sync_state_ctrl(
+       Connection      *conn,
+       Operation       *op,
+       Entry           *e,
+       int             entry_sync_state,
+       LDAPControl     **ctrls,
+       int             num_ctrls,
+       int             send_cookie,
+       struct berval   *latest_entrycsn_bv     );
+
+int
+bdb_build_sync_done_ctrl(
+       Connection      *conn,
+       Operation       *op,
+       LDAPControl     **ctrls,
+       int             num_ctrls,
+       int             send_cookie,
+       struct berval   *latest_entrycsn_bv     );
+
+int
+bdb_send_ldap_intermediate(
+       Connection  *conn,
+       Operation   *op,
+       ber_int_t   err,
+       const char  *matched,
+       const char  *text,
+       BerVarray   refs,
+       const char  *rspoid,
+       int         state,
+       struct berval *cookie,
+       LDAPControl **ctrls     );
 #endif
 
 #ifdef BDB_REUSE_LOCKERS
index 9916cdb22e4e8dbfc58eb10c2ef7af2ed855c790..14df815a201e6bb3843a5e5f2b1cec46c6c41704 100644 (file)
@@ -65,13 +65,20 @@ bdb_search(
        int             tentries = 0;
        ID              lastid = NOID;
 
-#ifdef LDAP_CLIENT_UPDATE
-       Filter lcupf, csnfnot, csnfeq, csnfand, csnfge;
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+       Filter          cookief, csnfnot, csnfeq, csnfand, csnfge;
        AttributeAssertion aa_ge, aa_eq;
        int             entry_count = 0;
-       struct berval entrycsn_bv = { 0, NULL };
-       struct berval latest_entrycsn_bv = { 0, NULL };
-#endif /* LDAP_CLIENT_UPDATE */
+       struct berval   latest_entrycsn_bv = { 0, NULL };
+       LDAPControl     *ctrls[SLAP_SEARCH_MAX_CTRLS];
+       int             num_ctrls = 0;
+#endif
+
+#ifdef LDAP_SYNC
+       int             rc_sync = 0;
+       int             entry_sync_state;
+       AttributeName   null_attr;
+#endif
 
        struct slap_limits_set *limit = NULL;
        int isroot = 0;
@@ -88,11 +95,32 @@ bdb_search(
 
 #ifdef LDAP_CLIENT_UPDATE
        if ( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) {
-               bdb_add_psearch_spec( be, conn, op, base, base, scope,
-                       deref, slimit, tlimit, filter, filterstr, attrs, attrsonly );
+               bdb_add_psearch_spec( be, conn, op, base, base, scope, deref, slimit,
+                               tlimit, filter, filterstr, attrs, attrsonly, LDAP_CLIENT_UPDATE );
                return LDAP_SUCCESS;
        }
 #endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+       else
+#endif
+#ifdef LDAP_SYNC
+       /* psearch needs to be registered before refresh begins */
+       /* psearch and refresh transmission is serialized in send_ldap_ber() */
+       if ( op->o_sync_mode & SLAP_SYNC_PERSIST ) {
+               bdb_add_psearch_spec( be, conn, op, base, base, scope, deref, slimit,
+                               tlimit, filter, filterstr, attrs, attrsonly, LDAP_SYNC );
+       }
+       null_attr.an_desc = NULL;
+       null_attr.an_oc = NULL;
+       null_attr.an_name.bv_len = 0;
+       null_attr.an_name.bv_val = NULL;
+#endif
+
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+       for ( num_ctrls = 0; num_ctrls < SLAP_SEARCH_MAX_CTRLS; num_ctrls++ )
+               ctrls[num_ctrls] = NULL;
+       num_ctrls = 0;
+#endif
 
 
        manageDSAit = get_manageDSAit( op );
@@ -394,9 +422,9 @@ dn2entry_retry:
 
 #ifdef LDAP_CLIENT_UPDATE
        if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
-               lcupf.f_choice = LDAP_FILTER_AND;
-               lcupf.f_and = &csnfnot;
-               lcupf.f_next = NULL;
+               cookief.f_choice = LDAP_FILTER_AND;
+               cookief.f_and = &csnfnot;
+               cookief.f_next = NULL;
 
                csnfnot.f_choice = LDAP_FILTER_NOT;
                csnfnot.f_not = &csnfeq;
@@ -417,7 +445,36 @@ dn2entry_retry:
                ber_dupbv( &csnfge.f_av_value, &op->o_clientupdate_state );
                csnfge.f_next = filter;
        }
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+       else
+#endif
+#ifdef LDAP_SYNC
+       if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+               cookief.f_choice = LDAP_FILTER_AND;
+               cookief.f_and = &csnfnot;
+               cookief.f_next = NULL;
+
+               csnfnot.f_choice = LDAP_FILTER_NOT;
+               csnfnot.f_not = &csnfeq;
+               csnfnot.f_next = &csnfand;
+
+               csnfeq.f_choice = LDAP_FILTER_EQUALITY;
+               csnfeq.f_ava = &aa_eq;
+               csnfeq.f_av_desc = slap_schema.si_ad_entryCSN;
+               ber_dupbv( &csnfeq.f_av_value, &op->o_sync_state );
+
+               csnfand.f_choice = LDAP_FILTER_AND;
+               csnfand.f_and = &csnfge;
+               csnfand.f_next = NULL;
+
+               csnfge.f_choice = LDAP_FILTER_GE;
+               csnfge.f_ava = &aa_ge;
+               csnfge.f_av_desc = slap_schema.si_ad_entryCSN;
+               ber_dupbv( &csnfge.f_av_value, &op->o_sync_state );
+               csnfge.f_next = filter;
+       }
+#endif
 
        for ( id = bdb_idl_first( candidates, &cursor );
                id != NOID;
@@ -601,9 +658,22 @@ id2entry_retry:
                /* if it matches the filter and scope, send it */
 #ifdef LDAP_CLIENT_UPDATE
                if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
-                       rc = test_filter( be, conn, op, e, &lcupf );
+                       rc = test_filter( be, conn, op, e, &cookief );
+               } else
+#endif
+#ifdef LDAP_SYNC
+               if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+                       rc_sync = test_filter( be, conn, op, e, &cookief );
+                       rc      = test_filter( be, conn, op, e, filter );
+                       if ( rc == LDAP_COMPARE_TRUE ) {
+                               if ( rc_sync == LDAP_COMPARE_TRUE ) {
+                                       entry_sync_state = LDAP_SYNC_ADD;
+                               } else {
+                                       entry_sync_state = LDAP_SYNC_PRESENT;
+                               }
+                       }
                } else
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
                {
                        rc = test_filter( be, conn, op, e, filter );
                }
@@ -658,100 +728,41 @@ id2entry_retry:
                                        {
 #ifdef LDAP_CLIENT_UPDATE
                                                if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
-                                                       Attribute* a;
-                                                       int ret;
-                                                       int res;
-                                                       const char *text = NULL;
-                                                       LDAPControl *ctrls[2];
-                                                       char berbuf[LBER_ELEMENT_SIZEOF];
-                                                       BerElement *ber = (BerElement *)berbuf;
-
-                                                       ber_init2( ber, 0, LBER_USE_DER );
-
-                                                       entry_count++;
-
-                                                       ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
-                                                       ctrls[1] = NULL;
-
-                                                       if ( entry_count % op->o_clientupdate_interval == 0 ) {
-                                                               /* Send cookie */
-                                                               for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
-                                                                       AttributeDescription *desc = a->a_desc;
-                                                                       if ( desc == slap_schema.si_ad_entryCSN ) {
-                                                                               ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
-                                                                               if ( latest_entrycsn_bv.bv_val == NULL ) {
-                                                                                       ber_dupbv( &latest_entrycsn_bv, &entrycsn_bv );
-                                                                               } else {
-                                                                                       res = value_match( &ret, desc,
-                                                                                               desc->ad_type->sat_ordering,
-                                                                                               SLAP_MR_ASSERTION_SYNTAX_MATCH,
-                                                                                               &entrycsn_bv, &latest_entrycsn_bv, &text );
-                                                                                       if ( res != LDAP_SUCCESS ) {
-                                                                                               ret = 0;
-#ifdef NEW_LOGGING
-                                                                                               LDAP_LOG ( OPERATION, RESULTS, 
-                                                                                                       "bdb_search: value_match failed\n",
-                                                                                                       0, 0, 0 );
-#else
-                                                                                               Debug( LDAP_DEBUG_TRACE,
-                                                                                                       "bdb_search: value_match failed\n",
-                                                                                                       0, 0, 0 );
-#endif
-                                                                                       }
-
-                                                                                       if ( ret > 0 ) {
-                                                                                               ch_free( latest_entrycsn_bv.bv_val );
-                                                                                               latest_entrycsn_bv.bv_val = NULL;
-                                                                                               ber_dupbv( &latest_entrycsn_bv,
-                                                                                                       &entrycsn_bv );
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               }
-
-                                                               ber_printf( ber,
-                                                                       "{bb{sON}N}",
-                                                                       SLAP_LCUP_STATE_UPDATE_FALSE,
-                                                                       SLAP_LCUP_ENTRY_DELETED_FALSE,
-                                                                       LCUP_COOKIE_OID, &entrycsn_bv );
-
-                                                               ch_free( entrycsn_bv.bv_val );
-                                                               entrycsn_bv.bv_val = NULL;
-
-                                                       } else {
-                                                               /* Do not send cookie */
-                                                               ber_printf( ber,
-                                                                       "{bbN}",
-                                                                       SLAP_LCUP_STATE_UPDATE_FALSE,
-                                                                       SLAP_LCUP_ENTRY_DELETED_FALSE );
-                                                       }
+                                                       rc = bdb_build_lcup_update_ctrl( conn, op, e, ++entry_count, ctrls,
+                                                                       num_ctrls++, &latest_entrycsn_bv, SLAP_LCUP_ENTRY_DELETED_FALSE );
+                                                       if ( rc != LDAP_SUCCESS )
+                                                               goto done;
+                                                       result = send_search_entry( be, conn, op,
+                                                                       e, attrs, attrsonly, ctrls);
 
-                                                       ctrls[0]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
-                                                       ctrls[0]->ldctl_iscritical = op->o_clientupdate;
-                                                       ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
-                                                       if ( ret < 0 ) {
-                                                               ber_free_buf( ber );
-#ifdef NEW_LOGGING
-                                                               LDAP_LOG ( OPERATION, RESULTS, 
-                                                                       "bdb_search: ber_flatten2 failed\n",
-                                                                       0, 0, 0 );
-#else
-                                                               Debug( LDAP_DEBUG_TRACE,
-                                                                       "bdb_search: ber_flatten2 failed\n",
-                                                                       0, 0, 0 );
+                                                       if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+                                                               ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+                                                       ch_free( ctrls[--num_ctrls] );
+                                                       ctrls[num_ctrls] = NULL;
+                                               } else
 #endif
-                                                               send_ldap_result( conn, op, rc=LDAP_OTHER,
-                                                                       NULL, "internal error", NULL, NULL );
+#ifdef LDAP_SYNC
+                                               if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+                                                       rc = bdb_build_sync_state_ctrl( conn, op, e, entry_sync_state, ctrls,
+                                                                       num_ctrls++, 0, &latest_entrycsn_bv );
+                                                       if ( rc != LDAP_SUCCESS )
                                                                goto done;
-                                                       }
 
-                                                       result = send_search_entry( be, conn, op,
-                                                               e, attrs, attrsonly, ctrls);
+                                                       if ( rc_sync == LDAP_COMPARE_TRUE ) { /* ADD */
+                                                               result = send_search_entry( be, conn, op,
+                                                                               e, attrs, attrsonly, ctrls);
+                                                       } else { /* PRESENT */
+                                                               result = send_search_entry( be, conn, op,
+                                                                               e, &null_attr, attrsonly, ctrls);
+                                                       }
 
-                                                       ber_free_buf( ber );
-                                                       ch_free( ctrls[0] );
+                                                       if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+                                                               ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+                                                       ch_free( ctrls[--num_ctrls] );
+                                                       ctrls[num_ctrls] = NULL;
                                                } else
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+
                                                {
                                                        result = send_search_entry( be, conn, op,
                                                                e, attrs, attrsonly, NULL);
@@ -806,47 +817,44 @@ loop_continue:
 
 #ifdef LDAP_CLIENT_UPDATE
        if ( op->o_clientupdate_type & SLAP_LCUP_SYNC ) {
-               int ret;
-               LDAPControl *ctrls[2];
-               char berbuf[LBER_ELEMENT_SIZEOF];
-               BerElement *ber = (BerElement *)berbuf;
-
-               ber_init2( ber, NULL, LBER_USE_DER );
+               bdb_build_lcup_done_ctrl( conn, op, ctrls, num_ctrls++, &latest_entrycsn_bv );
 
-               ctrls[0] = ch_malloc ( sizeof ( LDAPControl ) );
-               ctrls[1] = NULL;
-
-               ber_printf( ber, "{sO", LCUP_COOKIE_OID, &latest_entrycsn_bv );
-               ber_printf( ber, "N}" );
+               send_search_result( conn, op,
+                               v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+                               NULL, NULL, v2refs, ctrls, nentries );
 
-               ctrls[0]->ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE_DONE;
-               ctrls[0]->ldctl_iscritical = op->o_clientupdate;
-               ret = ber_flatten2( ber, &ctrls[0]->ldctl_value, 0 );
+               ch_free( latest_entrycsn_bv.bv_val );
+               latest_entrycsn_bv.bv_val = NULL;
 
-               if ( ret < 0 ) {
-                       ber_free_buf( ber );
-#ifdef NEW_LOGGING
-                       LDAP_LOG ( OPERATION, RESULTS, 
-                               "bdb_search: ber_flatten2 failed\n", 0, 0, 0 );
-#else
-                       Debug( LDAP_DEBUG_TRACE, "bdb_search: ber_flatten2 failed\n",
-                               0, 0, 0 );
+               if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+                               ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+               ch_free( ctrls[--num_ctrls] );
+               ctrls[num_ctrls] = NULL;
+       } else
 #endif
-                       send_ldap_result( conn, op, rc=LDAP_OTHER,
-                               NULL, "internal error", NULL, NULL );
-                       goto done;
+#ifdef LDAP_SYNC
+       if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+               if ( op->o_sync_mode & SLAP_SYNC_PERSIST ) {
+                       /* refreshAndPersist mode */
+                       bdb_send_ldap_intermediate( conn, op,
+                               LDAP_SUCCESS, NULL, NULL, NULL, LDAP_SYNC_INFO,
+                               LDAP_SYNC_REFRESH_DONE, &latest_entrycsn_bv, NULL );
+               } else {
+                       /* refreshOnly mode */
+                       bdb_build_sync_done_ctrl( conn, op, ctrls, num_ctrls++, 1, &latest_entrycsn_bv );
+                       send_search_result( conn, op,
+                                       v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+                                       NULL, NULL, v2refs, ctrls, nentries );
+                       if ( ctrls[num_ctrls-1]->ldctl_value.bv_val != NULL )
+                               ch_free( ctrls[num_ctrls-1]->ldctl_value.bv_val );
+                       ch_free( ctrls[--num_ctrls] );
+                       ctrls[num_ctrls] = NULL;
                }
 
-               send_search_result( conn, op,
-                       v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
-                       NULL, NULL, v2refs, ctrls, nentries );
-
                ch_free( latest_entrycsn_bv.bv_val );
                latest_entrycsn_bv.bv_val = NULL;
-               ch_free( ctrls[0] );
-               ber_free_buf( ber );
        } else
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
        {
                send_search_result( conn, op,
                        v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
@@ -871,7 +879,21 @@ done:
                        ch_free( csnfge.f_av_value.bv_val );
                }
        }
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+       else
+#endif
+#ifdef LDAP_SYNC
+       if ( op->o_sync_mode & SLAP_SYNC_REFRESH ) {
+               if ( csnfeq.f_ava != NULL && csnfeq.f_av_value.bv_val != NULL ) {
+                       ch_free( csnfeq.f_av_value.bv_val );
+               }
+
+               if ( csnfge.f_ava != NULL && csnfge.f_av_value.bv_val != NULL ) {
+                       ch_free( csnfge.f_av_value.bv_val );
+               }
+       }
+#endif
 
        LOCK_ID_FREE (bdb->bi_dbenv, locker );
 
@@ -1159,3 +1181,333 @@ done:
        (void) ber_free_buf( ber );
 }                      
 
+#ifdef LDAP_CLIENT_UPDATE
+int
+bdb_build_lcup_update_ctrl(
+       Connection      *conn,
+       Operation       *op,
+       Entry           *e,
+       int             entry_count,
+       LDAPControl     **ctrls,
+       int             num_ctrls,
+       struct berval   *latest_entrycsn_bv,
+       int             isdeleted       )
+{
+       Attribute* a;
+       int ret;
+       int res;
+       int rc;
+       const char *text = NULL;
+
+       char berbuf[LBER_ELEMENT_SIZEOF];
+       BerElement *ber = (BerElement *)berbuf;
+
+       struct berval entrycsn_bv = { 0, NULL };
+
+       ber_init2( ber, 0, LBER_USE_DER );
+
+       ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
+
+       for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
+               AttributeDescription *desc = a->a_desc;
+               if ( desc == slap_schema.si_ad_entryCSN ) {
+                       ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
+                       if ( latest_entrycsn_bv->bv_val == NULL ) {
+                               ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
+                       } else {
+                               res = value_match( &ret, desc,
+                                       desc->ad_type->sat_ordering,
+                                       SLAP_MR_ASSERTION_SYNTAX_MATCH,
+                                       &entrycsn_bv, latest_entrycsn_bv, &text );
+                               if ( res != LDAP_SUCCESS ) {
+                                       ret = 0;
+#ifdef NEW_LOGGING
+                                       LDAP_LOG ( OPERATION, RESULTS, 
+                                               "bdb_search: value_match failed\n",
+                                               0, 0, 0 );
+#else
+                                       Debug( LDAP_DEBUG_TRACE,
+                                               "bdb_search: value_match failed\n",
+                                               0, 0, 0 );
+#endif
+                               }
+
+                               if ( ret > 0 ) {
+                                       ch_free( latest_entrycsn_bv->bv_val );
+                                       latest_entrycsn_bv->bv_val = NULL;
+                                       ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
+                               }
+                       }
+               }
+       }
+
+       if ( entry_count % op->o_clientupdate_interval == 0 )
+               ber_printf( ber,
+                       "{bb{sON}N}",
+                       SLAP_LCUP_STATE_UPDATE_FALSE,
+                       isdeleted,
+                       LDAP_LCUP_COOKIE_OID, &entrycsn_bv );
+       else /* Do not send cookie */
+               ber_printf( ber,
+                       "{bbN}",
+                       SLAP_LCUP_STATE_UPDATE_FALSE,
+                       isdeleted );
+
+       ch_free( entrycsn_bv.bv_val );
+       entrycsn_bv.bv_val = NULL;
+
+       ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_ENTRY_UPDATE;
+       ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
+       ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
+
+       ber_free_buf( ber );
+
+       if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG ( OPERATION, RESULTS, 
+                       "bdb_build_lcup_ctrl: ber_flatten2 failed\n",
+                       0, 0, 0 );
+#else
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_build_lcup_ctrl: ber_flatten2 failed\n",
+                       0, 0, 0 );
+#endif
+               send_ldap_result( conn, op, rc=LDAP_OTHER,
+                       NULL, "internal error", NULL, NULL );
+               return ret;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+int
+bdb_build_lcup_done_ctrl(
+       Connection      *conn,
+       Operation       *op,
+       LDAPControl     **ctrls,
+       int             num_ctrls,
+       struct berval   *latest_entrycsn_bv     )
+{
+       int ret, rc;
+       char berbuf[LBER_ELEMENT_SIZEOF];
+       BerElement *ber = (BerElement *)berbuf;
+
+       ber_init2( ber, NULL, LBER_USE_DER );
+
+       ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
+
+       ber_printf( ber, "{sO", LDAP_LCUP_COOKIE_OID, latest_entrycsn_bv );
+       ber_printf( ber, "N}" );
+
+       ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_CLIENT_UPDATE_DONE;
+       ctrls[num_ctrls]->ldctl_iscritical = op->o_clientupdate;
+       ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
+
+       ber_free_buf( ber );
+
+       if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG ( OPERATION, RESULTS, 
+                       "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
+#else
+               Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
+                       0, 0, 0 );
+#endif
+               send_ldap_result( conn, op, rc=LDAP_OTHER,
+                       NULL, "internal error", NULL, NULL );
+               return ret;
+       }
+
+       return LDAP_SUCCESS;
+}
+#endif
+
+#ifdef LDAP_SYNC
+int
+bdb_build_sync_state_ctrl(
+       Connection      *conn,
+       Operation       *op,
+       Entry           *e,
+       int             entry_sync_state,
+       LDAPControl     **ctrls,
+       int             num_ctrls,
+       int             send_cookie,
+       struct berval   *latest_entrycsn_bv     )
+{
+       Attribute* a;
+       int ret;
+       int res;
+       int rc;
+       const char *text = NULL;
+
+       char berbuf[LBER_ELEMENT_SIZEOF];
+       BerElement *ber = (BerElement *)berbuf;
+
+       struct berval entryuuid_bv      = { 0, NULL };
+       struct berval entrycsn_bv       = { 0, NULL };
+
+       ber_init2( ber, 0, LBER_USE_DER );
+
+       ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
+
+       for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
+               AttributeDescription *desc = a->a_desc;
+               if ( desc == slap_schema.si_ad_entryCSN ) {
+                       ber_dupbv( &entrycsn_bv, &a->a_vals[0] );
+                       if ( latest_entrycsn_bv->bv_val == NULL ) {
+                               ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
+                       } else {
+                               res = value_match( &ret, desc,
+                                               desc->ad_type->sat_ordering,
+                                               SLAP_MR_ASSERTION_SYNTAX_MATCH,
+                                               &entrycsn_bv, latest_entrycsn_bv, &text );
+                               if ( res != LDAP_SUCCESS ) {
+                                       ret = 0;
+#ifdef NEW_LOGGING
+                                       LDAP_LOG ( OPERATION, RESULTS,
+                                                       "bdb_search: value_match failed\n",
+                                                       0, 0, 0 );
+#else
+                                       Debug( LDAP_DEBUG_TRACE,
+                                                       "bdb_search: value_match failed\n",
+                                                       0, 0, 0 );
+#endif
+                               }
+                               if ( ret > 0 ) {
+                                       ch_free( latest_entrycsn_bv->bv_val );
+                                       latest_entrycsn_bv->bv_val = NULL;
+                                       ber_dupbv( latest_entrycsn_bv, &entrycsn_bv );
+                               }
+                       }
+               } else if ( desc == slap_schema.si_ad_entryUUID ) {
+                       ber_dupbv( &entryuuid_bv, &a->a_vals[0] );
+               }
+       }
+
+       if ( send_cookie )
+               ber_printf( ber, "{eOON}", entry_sync_state, &entryuuid_bv, &entrycsn_bv );
+       else
+               ber_printf( ber, "{eON}", entry_sync_state, &entryuuid_bv );
+
+       ch_free( entrycsn_bv.bv_val );
+       entrycsn_bv.bv_val = NULL;
+       ch_free( entryuuid_bv.bv_val );
+       entryuuid_bv.bv_val = NULL;
+
+       ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_STATE;
+       ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
+       ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
+
+       ber_free_buf( ber );
+
+       if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG ( OPERATION, RESULTS, 
+                       "bdb_build_sync_ctrl: ber_flatten2 failed\n",
+                       0, 0, 0 );
+#else
+               Debug( LDAP_DEBUG_TRACE,
+                       "bdb_build_sync_ctrl: ber_flatten2 failed\n",
+                       0, 0, 0 );
+#endif
+               send_ldap_result( conn, op, rc=LDAP_OTHER,
+                       NULL, "internal error", NULL, NULL );
+               return ret;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+int
+bdb_build_sync_done_ctrl(
+       Connection      *conn,
+       Operation       *op,
+       LDAPControl     **ctrls,
+       int             num_ctrls,
+       int             send_cookie,
+       struct berval   *latest_entrycsn_bv     )
+{
+       int ret,rc;
+       char berbuf[LBER_ELEMENT_SIZEOF];
+       BerElement *ber = (BerElement *)berbuf;
+
+       ber_init2( ber, NULL, LBER_USE_DER );
+
+       ctrls[num_ctrls] = ch_malloc ( sizeof ( LDAPControl ) );
+
+       if ( send_cookie ) {
+               ber_printf( ber, "{ON}", latest_entrycsn_bv );
+       } else {
+               ber_printf( ber, "{N}" );
+       }
+
+       ctrls[num_ctrls]->ldctl_oid = LDAP_CONTROL_SYNC_DONE;
+       ctrls[num_ctrls]->ldctl_iscritical = op->o_sync;
+       ret = ber_flatten2( ber, &ctrls[num_ctrls]->ldctl_value, 1 );
+
+       ber_free_buf( ber );
+
+       if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG ( OPERATION, RESULTS, 
+                       "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
+#else
+               Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
+                       0, 0, 0 );
+#endif
+               send_ldap_result( conn, op, rc=LDAP_OTHER,
+                       NULL, "internal error", NULL, NULL );
+               return ret;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+int
+bdb_send_ldap_intermediate(
+       Connection  *conn,
+       Operation   *op,
+       ber_int_t   err,
+       const char  *matched,
+       const char  *text,
+       BerVarray   refs,
+       const char  *rspoid,
+       int         state,
+       struct berval *cookie,
+       LDAPControl **ctrls     )
+{
+       char berbuf[LBER_ELEMENT_SIZEOF];
+       BerElement *ber = (BerElement *)berbuf;
+       struct berval rspdata;
+
+       int ret, rc;
+
+       ber_init2( ber, NULL, LBER_USE_DER );
+
+       if ( cookie == NULL )
+               ber_printf( ber, "{eN}", state );
+       else
+               ber_printf( ber, "{eON}", state, cookie );
+
+       ret = ber_flatten2( ber, &rspdata, 0 );
+
+       if ( ret < 0 ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG ( OPERATION, RESULTS, 
+                       "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n", 0, 0, 0 );
+#else
+               Debug( LDAP_DEBUG_TRACE, "bdb_build_lcup_done_ctrl: ber_flatten2 failed\n",
+                       0, 0, 0 );
+#endif
+               send_ldap_result( conn, op, rc=LDAP_OTHER,
+                       NULL, "internal error", NULL, NULL );
+               return ret;
+       }
+
+       send_ldap_intermediate_resp( conn, op, err, matched, text, refs, rspoid, &rspdata, ctrls );
+
+       ber_free_buf( ber );
+
+       return LDAP_SUCCESS;
+}
+#endif
index f9f12ea9e74e8124a59f1947bd7e8a6124ca6fc8..34c071d3c81231945846dfdc78676678cf031c88 100644 (file)
@@ -35,6 +35,7 @@ int cancel_extop(
        int found = 0;
        int opid;
        BerElement *ber;
+       int i;
 
        assert( reqoid != NULL );
        assert( strcmp( LDAP_EXOP_X_CANCEL, reqoid ) == 0 );
@@ -86,9 +87,22 @@ int cancel_extop(
        }
 
        if ( !found ) {
+#ifdef LDAP_SYNC
+               for ( i = 0; i < nbackends; i++ ) {
+                       if ( strncmp( backends[i].be_type, "bdb", 3 ) ) continue;
+                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+                       if ( bdb_cancel( &backends[i], conn, opid ) == LDAP_SUCCESS ) {
+                               return LDAP_SUCCESS;
+                       } else {
+                               *text = "message ID not found";
+                               return LDAP_NO_SUCH_OPERATION;
+                       }
+               }
+#else
                *text = "message ID not found";
                ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-               return LDAP_NO_SUCH_OPERATION;
+               return LDAP_NO_SUCH_OPERATION;
+#endif
        }
 
        if ( op->o_cancel != LDAP_CANCEL_NONE ) {
@@ -114,3 +128,4 @@ int cancel_extop(
 
        return rc;
 }
+
index 0f54d412ebe25e5f83f2bd3b420f13a79397c8cf..c94ceb3d53b43f10844b22440df0ba88bdb8ac6e 100644 (file)
@@ -1040,12 +1040,26 @@ operations_error:
 
        LDAP_STAILQ_REMOVE( &conn->c_ops, arg->co_op, slap_op, o_next);
        LDAP_STAILQ_NEXT(arg->co_op, o_next) = NULL;
+
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+       if ( arg->co_op->o_cancel == LDAP_CANCEL_ACK )
+               goto co_op_free;
+#endif
 #ifdef LDAP_CLIENT_UPDATE
-       if ( !( arg->co_op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
-#endif /* LDAP_CLIENT_UPDATE */
-       {
-               slap_op_free( arg->co_op );
-       }
+       if ( ( arg->co_op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
+               goto no_co_op_free;
+#endif
+#ifdef LDAP_SYNC
+       if ( ( arg->co_op->o_sync_mode & SLAP_SYNC_PERSIST ) )
+               goto no_co_op_free;
+#endif
+
+co_op_free:
+
+       slap_op_free( arg->co_op );
+
+no_co_op_free:
+
        arg->co_op = NULL;
        arg->co_conn = NULL;
        free( (char *) arg );
index b068b1a7f09436054ea3ed60a8258b499a3e930d..2b20550968d6ba1dcf2f313a66da66c750541920 100644 (file)
@@ -58,6 +58,9 @@ static SLAP_CTRL_PARSE_FN parseSubentries;
 #ifdef LDAP_CLIENT_UPDATE
 static SLAP_CTRL_PARSE_FN parseClientUpdate;
 #endif
+#ifdef LDAP_SYNC
+static SLAP_CTRL_PARSE_FN parseLdupSync;
+#endif
 
 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
 
@@ -108,7 +111,12 @@ static struct slap_control {
        { LDAP_CONTROL_CLIENT_UPDATE,
                SLAP_CTRL_SEARCH, NULL,
                parseClientUpdate },
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#ifdef LDAP_SYNC
+       { LDAP_CONTROL_SYNC,
+               SLAP_CTRL_SEARCH, NULL,
+               parseLdupSync },
+#endif
        { NULL, 0, NULL, 0 }
 };
 
@@ -829,6 +837,13 @@ static int parseClientUpdate (
                return LDAP_PROTOCOL_ERROR;
        }
 
+#ifdef LDAP_SYNC
+       if ( op->o_sync != SLAP_NO_CONTROL ) {
+               *text = "LDAP Client Update and Sync controls used together";
+               return LDAP_PROTOCOL_ERROR;
+       }
+#endif
+
        if ( ctrl->ldctl_value.bv_len == 0 ) {
                *text = "LCUP client update control value is empty (or absent)";
                return LDAP_PROTOCOL_ERROR;
@@ -897,7 +912,7 @@ static int parseClientUpdate (
                return LDAP_PROTOCOL_ERROR;
        }
 
-       if ( tag == LDAP_TAG_COOKIE ) {
+       if ( tag == LDAP_LCUP_TAG_COOKIE ) {
                if ( (tag = ber_scanf( ber, /*{*/ "{mm}}",
                                        &scheme, &cookie )) == LBER_ERROR ) {
                        *text = "LCUP client update control : decoding error";
@@ -931,4 +946,113 @@ static int parseClientUpdate (
 
        return LDAP_SUCCESS;
 }
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+
+#ifdef LDAP_SYNC
+static int parseLdupSync (
+       Connection *conn,
+       Operation *op,
+       LDAPControl *ctrl,
+       const char **text )
+{
+       ber_tag_t tag;
+       BerElement *ber;
+       ber_int_t mode;
+       ber_len_t len;
+       struct berval cookie = { 0, NULL };
+
+       if ( op->o_sync != SLAP_NO_CONTROL ) {
+               *text = "LDAP Sync control specified multiple times";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+#ifdef LDAP_CLIENT_UPDATE
+       if ( op->o_clientupdate != SLAP_NO_CONTROL ) {
+               *text = "LDAP Sync and LDAP Client Update controls used together";
+               return LDAP_PROTOCOL_ERROR;
+       }
+#endif
+
+       if ( ctrl->ldctl_value.bv_len == 0 ) {
+               *text = "LDAP Sync control value is empty (or absent)";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       /* Parse the control value
+        *      syncRequestValue ::= SEQUENCE {
+        *              mode   ENUMERATED {
+        *                      -- 0 unused
+        *                      refreshOnly             (1),
+        *                      -- 2 reserved
+        *                      refreshAndPersist       (3)
+        *              },
+        *              cookie  syncCookie OPTIONAL
+        *      }
+        */
+
+       ber = ber_init( &ctrl->ldctl_value );
+       if( ber == NULL ) {
+               *text = "internal error";
+               return LDAP_OTHER;
+       }
+
+       if ( (tag = ber_scanf( ber, "{i" /*}*/, &mode )) == LBER_ERROR ) {
+               *text = "LDAP Sync control : mode decoding error";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       switch( mode ) {
+       case LDAP_SYNC_REFRESH_ONLY:
+               mode = SLAP_SYNC_REFRESH;
+               break;
+       case LDAP_SYNC_REFRESH_AND_PERSIST:
+               mode = SLAP_SYNC_REFRESH_AND_PERSIST;
+               break;
+       default:
+               *text = "LDAP Sync control : unknown update mode";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       tag = ber_peek_tag( ber, &len );
+
+       if ( tag == LDAP_SYNC_TAG_COOKIE ) {
+               if (( ber_scanf( ber, /*{*/ "m}",
+                                       &cookie )) == LBER_ERROR ) {
+                       *text = "LDAP Sync control : cookie decoding error";
+                       return LDAP_PROTOCOL_ERROR;
+               }
+       } else {
+               if (( ber_scanf( ber, /*{*/ "}")) == LBER_ERROR ) {
+                       *text = "LDAP Sync control : decoding error";
+                       return LDAP_PROTOCOL_ERROR;
+               }
+               cookie.bv_len = 0;
+               cookie.bv_val = NULL;
+       }
+
+       /* TODO : Cookie Scheme Validation */
+#if 0
+       if ( lcup_cookie_scheme_validate(scheme) != LDAP_SUCCESS ) {
+               *text = "Unsupported LCUP cookie scheme";
+               return LCUP_UNSUPPORTED_SCHEME;
+       }
+
+       if ( lcup_cookie_validate(scheme, cookie) != LDAP_SUCCESS ) {
+               *text = "Invalid LCUP cookie";
+               return LCUP_INVALID_COOKIE;
+       }
+#endif
+
+       ber_dupbv( &op->o_sync_state, &cookie );
+
+       (void) ber_free( ber, 1 );
+
+       op->o_sync_mode = (char) mode;
+
+       op->o_sync = ctrl->ldctl_iscritical
+               ? SLAP_CRITICAL_CONTROL
+               : SLAP_NONCRITICAL_CONTROL;
+
+       return LDAP_SUCCESS;
+}
+#endif
index e7b9600af0ab94eabdef9b66969b8ee8a67f109d..42f52b2c71dc619c01d2a6d7fa5e45893d484541 100644 (file)
@@ -46,7 +46,12 @@ slap_op_free( Operation *op )
        if ( op->o_clientupdate_state.bv_val != NULL ) {
                free( op->o_clientupdate_state.bv_val );
        }
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
+#ifdef LDAP_SYNC
+       if ( op->o_sync_state.bv_val != NULL ) {
+               free( op->o_sync_state.bv_val );
+       }
+#endif
 
 #if defined( LDAP_SLAPI )
        if ( op->o_pb != NULL ) {
index b679e1270e5bcf255f0a99fb92311659a8a041f4..d6e0bf9c476c4ba5665371ab703c246ec320bd23 100644 (file)
@@ -415,20 +415,28 @@ do_search(
 #endif /* LDAP_SLAPI */
 
 return_results:;
+
 #ifdef LDAP_CLIENT_UPDATE
-       if ( !( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
-#endif /* LDAP_CLIENT_UPDATE */
-       {
-               if( pbase.bv_val != NULL) free( pbase.bv_val );
-               if( nbase.bv_val != NULL) free( nbase.bv_val );
+       if ( ( op->o_clientupdate_type & SLAP_LCUP_PERSIST ) )
+               return rc;
+#endif
+#if defined(LDAP_CLIENT_UPDATE) && defined(LDAP_SYNC)
+       else
+#endif
+#ifdef LDAP_SYNC
+       if ( ( op->o_sync_mode & SLAP_SYNC_PERSIST ) )
+               return rc;
+#endif
+
+       if( pbase.bv_val != NULL) free( pbase.bv_val );
+       if( nbase.bv_val != NULL) free( nbase.bv_val );
 
-               if( fstr.bv_val != NULL) free( fstr.bv_val );
-               if( filter != NULL) filter_free( filter );
-               if( an != NULL ) free( an );
+       if( fstr.bv_val != NULL) free( fstr.bv_val );
+       if( filter != NULL) filter_free( filter );
+       if( an != NULL ) free( an );
 #ifdef LDAP_SLAPI
-               if( attrs != NULL) ch_free( attrs );
+       if( attrs != NULL) ch_free( attrs );
 #endif /* LDAP_SLAPI */
-       }
 
        return rc;
 }
index 152f971462fd3774a753250608d3f99c7e9b45b8..c09d1bf0cf4f4f1642df0324643953018052b154 100644 (file)
@@ -1615,14 +1615,14 @@ typedef struct slap_paged_state {
 } PagedResultsState;
 
 
-#ifdef LDAP_CLIENT_UPDATE
-#define LCUP_PSEARCH_BY_ADD 0x01
-#define LCUP_PSEARCH_BY_DELETE 0x02
-#define LCUP_PSEARCH_BY_PREMODIFY 0x03
-#define LCUP_PSEARCH_BY_MODIFY 0x04
-#define LCUP_PSEARCH_BY_SCOPEOUT 0x05
-
-struct lcup_search_spec {
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+#define LDAP_PSEARCH_BY_ADD            0x01
+#define LDAP_PSEARCH_BY_DELETE         0x02
+#define LDAP_PSEARCH_BY_PREMODIFY      0x03
+#define LDAP_PSEARCH_BY_MODIFY         0x04
+#define LDAP_PSEARCH_BY_SCOPEOUT       0x05
+
+struct ldap_psearch_spec {
        struct slap_op  *op;
        struct berval   *base;
        struct berval   *nbase;
@@ -1634,17 +1634,16 @@ struct lcup_search_spec {
        struct berval   *filterstr;
        AttributeName   *attrs;
        int             attrsonly;
-       struct lcup_entry *elist;
-       ldap_pvt_thread_mutex_t elist_mutex;
+       int             protocol;
        int             entry_count;
-       LDAP_LIST_ENTRY(lcup_search_spec) link;
+       LDAP_LIST_ENTRY(ldap_psearch_spec) link;
 };
 
 struct psid_entry {
-       struct lcup_search_spec* ps;
+       struct ldap_psearch_spec* ps;
        LDAP_LIST_ENTRY(psid_entry) link;
 };
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
 
 
 /*
@@ -1691,13 +1690,26 @@ typedef struct slap_op {
 #define SLAP_LCUP_NONE                         (0x0)
 #define SLAP_LCUP_SYNC                                 (0x1)
 #define SLAP_LCUP_PERSIST                      (0x2)
-#define SLAP_LCUP_SYNC_AND_PERSIST     (0x3)
+#define SLAP_LCUP_SYNC_AND_PERSIST             (0x3)
        ber_int_t o_clientupdate_interval;
        struct berval o_clientupdate_state;
-       LDAP_LIST_HEAD(lss, lcup_search_spec) psearch_spec;
+#endif
+
+#ifdef LDAP_SYNC
+       char o_sync;
+       char o_sync_mode;
+#define SLAP_SYNC_NONE                         (0x0)
+#define SLAP_SYNC_REFRESH                      (0x1)
+#define SLAP_SYNC_PERSIST                      (0x2)
+#define SLAP_SYNC_REFRESH_AND_PERSIST          (0x3)
+       struct berval o_sync_state;
+#endif
+
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+       LDAP_LIST_HEAD(lss, ldap_psearch_spec) psearch_spec;
        LDAP_LIST_HEAD(pe, psid_entry) premodify_list;
        LDAP_LIST_ENTRY(slap_op) link;
-#endif /* LDAP_CLIENT_UPDATE */
+#endif
 
 #ifdef LDAP_CONNECTIONLESS
        Sockaddr        o_peeraddr;     /* UDP peer address               */
@@ -1997,6 +2009,10 @@ enum {
 #define SLAP_LCUP_ENTRY_DELETED_FALSE  0
 #endif /* LDAP_CLIENT_UPDATE */
 
+#if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
+#define SLAP_SEARCH_MAX_CTRLS   10
+#endif
+
 LDAP_END_DECL
 
 #include "proto-slap.h"