Diff for /servers/slapd/back-meta/compare.c between versions 1.50 and 1.50.2.7

version 1.50, 2006/01/03 22:12:20 version 1.50.2.7, 2008/02/12 00:25:47
Line 1 Line 1
 /* $OpenLDAP: pkg/ldap/servers/slapd/back-meta/compare.c,v 1.49 2005/12/13 19:11:27 ando Exp $ */  /* $OpenLDAP: pkg/ldap/servers/slapd/back-meta/compare.c,v 1.50.2.6 2008/02/11 23:26:46 kurt Exp $ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.  /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *   *
  * Copyright 1999-2006 The OpenLDAP Foundation.   * Copyright 1999-2008 The OpenLDAP Foundation.
  * Portions Copyright 2001-2003 Pierangelo Masarati.   * Portions Copyright 2001-2003 Pierangelo Masarati.
  * Portions Copyright 1999-2003 Howard Chu.   * Portions Copyright 1999-2003 Howard Chu.
  * All rights reserved.   * All rights reserved.
Line 34 Line 34
 int  int
 meta_back_compare( Operation *op, SlapReply *rs )  meta_back_compare( Operation *op, SlapReply *rs )
 {  {
         metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;          metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
         metaconn_t              *mc = NULL;          metatarget_t    *mt;
         char                    *match = NULL,          metaconn_t      *mc;
                                 *err = NULL;          int             rc = 0;
         struct berval           mmatch = BER_BVNULL;          int             candidate = -1;
         int                     ncandidates = 0,          struct berval   mdn = BER_BVNULL;
                                 last = 0,          dncookie        dc;
                                 i,          struct berval   mapped_attr = op->orc_ava->aa_desc->ad_cname;
                                 count = 0,          struct berval   mapped_value = op->orc_ava->aa_value;
                                 rc,          int             msgid;
                                 cres = LDAP_SUCCESS,          int             do_retry = 1;
                                 rres = LDAP_SUCCESS,          LDAPControl     **ctrls = NULL;
                                 *msgid;  
         dncookie                dc;  
   
         SlapReply               *candidates = meta_back_candidates_get( op );          mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
   
         mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_SENDERR );  
         if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {          if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
                 return rs->sr_err;                  return rs->sr_err;
         }          }
           
         msgid = ch_calloc( sizeof( int ), mi->mi_ntargets );          assert( mc->mc_conns[ candidate ].msc_ld != NULL );
         if ( msgid == NULL ) {  
                 send_ldap_error( op, rs, LDAP_OTHER, NULL );  
                 rc = LDAP_OTHER;  
                 goto done;  
         }  
   
         /*          /*
          * start an asynchronous compare for each candidate target           * Rewrite the modify dn, if needed
          */           */
           mt = mi->mi_targets[ candidate ];
           dc.target = mt;
         dc.conn = op->o_conn;          dc.conn = op->o_conn;
         dc.rs = rs;          dc.rs = rs;
         dc.ctx = "compareDN";          dc.ctx = "compareDN";
   
         for ( i = 0; i < mi->mi_ntargets; i++ ) {          switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
                 struct berval           mdn = BER_BVNULL;          case LDAP_UNWILLING_TO_PERFORM:
                 struct berval           mapped_attr = op->orc_ava->aa_desc->ad_cname;                  rc = 1;
                 struct berval           mapped_value = op->orc_ava->aa_value;                  goto cleanup;
   
                 if ( candidates[ i ].sr_tag != META_CANDIDATE ) {  
                         msgid[ i ] = -1;  
                         continue;  
                 }  
   
                 /*  
                  * Rewrite the compare dn, if needed  
                  */  
                 dc.target = &mi->mi_targets[ i ];  
   
                 switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {  
                 case LDAP_UNWILLING_TO_PERFORM:  
                         rc = 1;  
                         goto finish;  
   
                 default:  
                         break;  
                 }  
   
                 /*  
                  * if attr is objectClass, try to remap the value  
                  */  
                 if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {  
                         ldap_back_map( &mi->mi_targets[ i ].mt_rwmap.rwm_oc,  
                                         &op->orc_ava->aa_value,  
                                         &mapped_value, BACKLDAP_MAP );  
   
                         if ( BER_BVISNULL( &mapped_value ) || mapped_value.bv_val[0] == '\0' ) {  
                                 continue;  
                         }  
                 /*  
                  * else try to remap the attribute  
                  */  
                 } else {  
                         ldap_back_map( &mi->mi_targets[ i ].mt_rwmap.rwm_at,  
                                 &op->orc_ava->aa_desc->ad_cname,  
                                 &mapped_attr, BACKLDAP_MAP );  
                         if ( BER_BVISNULL( &mapped_attr ) || mapped_attr.bv_val[0] == '\0' ) {  
                                 continue;  
                         }  
   
                         if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )  
                         {  
                                 dc.ctx = "compareAttrDN";  
   
                                 switch ( ldap_back_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) )  
                                 {  
                                 case LDAP_UNWILLING_TO_PERFORM:  
                                         rc = 1;  
                                         goto finish;  
   
                                 default:  
                                         break;  
                                 }  
                         }  
                 }  
                   
                 /*  
                  * the compare op is spawned across the targets and the first  
                  * that returns determines the result; a constraint on unicity  
                  * of the result ought to be enforced  
                  */  
                  rc = ldap_compare_ext( mc->mc_conns[ i ].msc_ld, mdn.bv_val,  
                                 mapped_attr.bv_val, &mapped_value,  
                                 op->o_ctrls, NULL, &msgid[ i ] );  
   
                 if ( mdn.bv_val != op->o_req_dn.bv_val ) {  
                         free( mdn.bv_val );  
                         BER_BVZERO( &mdn );  
                 }  
   
                 if ( mapped_attr.bv_val != op->orc_ava->aa_desc->ad_cname.bv_val ) {  
                         free( mapped_attr.bv_val );  
                         BER_BVZERO( &mapped_attr );  
                 }  
   
                 if ( mapped_value.bv_val != op->orc_ava->aa_value.bv_val ) {          default:
                         free( mapped_value.bv_val );                  break;
                         BER_BVZERO( &mapped_value );  
                 }  
   
                 if ( rc != LDAP_SUCCESS ) {  
                         /* FIXME: what should we do with the error? */  
                         continue;  
                 }  
   
                 ++ncandidates;  
         }          }
   
         /*          /*
          * wait for replies           * if attr is objectClass, try to remap the value
          */           */
         for ( rc = 0, count = 0; ncandidates > 0; ) {          if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
                   ldap_back_map( &mt->mt_rwmap.rwm_oc,
                                   &op->orc_ava->aa_value,
                                   &mapped_value, BACKLDAP_MAP );
   
                 /*                  if ( BER_BVISNULL( &mapped_value ) || BER_BVISEMPTY( &mapped_value ) ) {
                  * FIXME: should we check for abandon?                          goto cleanup;
                  */                  }
                 for ( i = 0; i < mi->mi_ntargets; i++ ) {  
                         metasingleconn_t        *msc = &mc->mc_conns[ i ];  
                         int                     lrc;  
                         LDAPMessage             *res = NULL;  
                         struct timeval          tv;  
   
                         LDAP_BACK_TV_SET( &tv );          /*
            * else try to remap the attribute
            */
           } else {
                   ldap_back_map( &mt->mt_rwmap.rwm_at,
                           &op->orc_ava->aa_desc->ad_cname,
                           &mapped_attr, BACKLDAP_MAP );
                   if ( BER_BVISNULL( &mapped_attr ) || BER_BVISEMPTY( &mapped_attr ) ) {
                           goto cleanup;
                   }
   
                         if ( msgid[ i ] == -1 ) {                  if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
                                 continue;                  {
                         }                          dc.ctx = "compareAttrDN";
   
                         lrc = ldap_result( msc->msc_ld, msgid[ i ],                          switch ( ldap_back_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) )
                                         LDAP_MSG_ALL, &tv, &res );                          {
                           case LDAP_UNWILLING_TO_PERFORM:
                                   rc = 1;
                                   goto cleanup;
   
                         if ( lrc == 0 ) {                          default:
                                 assert( res == NULL );  
                                 continue;  
   
                         } else if ( lrc == -1 ) {  
                                 /* we do not retry in this case;  
                                  * only for unique operations... */  
                                 ldap_get_option( msc->msc_ld,  
                                         LDAP_OPT_ERROR_NUMBER, &rs->sr_err );  
                                 rres = slap_map_api2result( rs );  
                                 rres = rc;  
                                 rc = -1;  
                                 goto finish;  
   
                         } else if ( lrc == LDAP_RES_COMPARE ) {  
                                 if ( count > 0 ) {  
                                         rres = LDAP_OTHER;  
                                         rc = -1;  
                                         goto finish;  
                                 }  
   
                                 rc = ldap_parse_result( msc->msc_ld, res,  
                                                 &rs->sr_err,  
                                                 NULL, NULL, NULL, NULL, 1 );  
                                 if ( rc != LDAP_SUCCESS ) {  
                                         rres = rc;  
                                         rc = -1;  
                                         goto finish;  
                                 }  
                                   
                                 switch ( rs->sr_err ) {  
                                 case LDAP_COMPARE_TRUE:  
                                 case LDAP_COMPARE_FALSE:  
   
                                         /*  
                                          * true or false, got it;  
                                          * sending to cache ...  
                                          */  
                                         if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) {  
                                                 ( void )meta_dncache_update_entry( &mi->mi_cache, &op->o_req_ndn, i );  
                                         }  
   
                                         count++;  
                                         rc = 0;  
                                         break;  
   
                                 default:  
                                         rres = slap_map_api2result( rs );  
   
                                         if ( err != NULL ) {  
                                                 free( err );  
                                         }  
                                         ldap_get_option( msc->msc_ld,  
                                                 LDAP_OPT_ERROR_STRING, &err );  
   
                                         if ( match != NULL ) {  
                                                 free( match );  
                                         }  
                                         ldap_get_option( msc->msc_ld,  
                                                 LDAP_OPT_MATCHED_DN, &match );  
                                           
                                         last = i;  
                                         break;  
                                 }  
                                 msgid[ i ] = -1;  
                                 --ncandidates;  
   
                         } else {  
                                 msgid[ i ] = -1;  
                                 --ncandidates;  
                                 if ( res ) {  
                                         ldap_msgfree( res );  
                                 }  
                                 break;                                  break;
                         }                          }
                 }                  }
         }          }
   
 finish:;  retry:;
           ctrls = op->o_ctrls;
           rc = meta_back_controls_add( op, rs, mc, candidate, &ctrls );
           if ( rc != LDAP_SUCCESS ) {
                   send_ldap_result( op, rs );
                   goto cleanup;
           }
   
         /*          rs->sr_err = ldap_compare_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
          * Rewrite the matched portion of the search base, if required                          mapped_attr.bv_val, &mapped_value,
          *                           ctrls, NULL, &msgid );
          * FIXME: only the last one gets caught!  
          */          rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
         if ( count == 1 ) {                  mt->mt_timeout[ SLAP_OP_COMPARE ], LDAP_BACK_SENDRESULT );
                 if ( match != NULL ) {          if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                         free( match );                  do_retry = 0;
                         match = NULL;                  if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                 }                          /* if the identity changed, there might be need to re-authz */
                                           (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
                 /*                          goto retry;
                  * the result of the compare is assigned to the res code  
                  * that will be returned  
                  */  
                 rres = cres;  
                   
                 /*  
                  * At least one compare failed with matched portion,  
                  * and none was successful  
                  */  
         } else if ( match != NULL && match[ 0 ] != '\0' ) {  
                 struct berval matched, pmatched;  
   
                 ber_str2bv( match, 0, 0, &matched );  
   
                 dc.ctx = "matchedDN";  
                 ldap_back_dn_massage( &dc, &matched, &mmatch );  
                 if ( dnPretty( NULL, &mmatch, &pmatched, NULL ) == LDAP_SUCCESS ) {  
                         if ( mmatch.bv_val != match ) {  
                                 free( mmatch.bv_val );  
                         }  
                         mmatch = pmatched;  
                 }                  }
         }          }
   
         if ( rres != LDAP_SUCCESS ) {  cleanup:;
                 rs->sr_err = rres;          (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
         }  
         rs->sr_matched = mmatch.bv_val;          if ( mdn.bv_val != op->o_req_dn.bv_val ) {
         send_ldap_result( op, rs );                  free( mdn.bv_val );
         rs->sr_matched = NULL;  
   
         if ( match != NULL ) {  
                 if ( mmatch.bv_val != match ) {  
                         free( mmatch.bv_val );  
                 }  
                 free( match );  
         }          }
   
         if ( msgid ) {          if ( op->orc_ava->aa_value.bv_val != mapped_value.bv_val ) {
                 free( msgid );                  free( mapped_value.bv_val );
         }          }
   
 done:;          if ( mc ) {
         meta_back_release_conn( op, mc );                  meta_back_release_conn( mi, mc );
           }
   
         return rc;          return rs->sr_err;
 }  }
   

Removed from v.1.50  
changed lines
  Added in v.1.50.2.7


______________
© Copyright 1998-2020, OpenLDAP Foundation, info@OpenLDAP.org