Back to index

openldap  2.4.31
Functions | Variables
search.cpp File Reference
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/errno.h>
#include "lutil.h"
#include "back-ndb.h"

Go to the source code of this file.

Functions

static int ndb_dn2bound (NdbIndexScanOperation *myop, NdbRdns *rdns)
static int ndb_filter_check (struct ndb_info *ni, Filter *f, NdbOcInfo **oci, int *indexed, int *ocfilter)
static int ndb_filter_set (Operation *op, struct ndb_info *ni, Filter *f, int indexed, NdbIndexScanOperation *scan, NdbScanFilter *sf, int *bounds)
static int ndb_oc_search (Operation *op, SlapReply *rs, Ndb *ndb, NdbTransaction *txn, NdbRdns *rbase, NdbOcInfo *oci, int indexed)
int ndb_back_search (Operation *op, SlapReply *rs)
int ndb_has_children (NdbArgs *NA, int *hasChildren)
int ndb_has_subordinates (Operation *op, Entry *e, int *hasSubordinates)
int ndb_operational (Operation *op, SlapReply *rs)

Variables

NdbInterpretedCode * ndb_lastrow_code

Function Documentation

int ndb_back_search ( Operation op,
SlapReply rs 
)

Definition at line 502 of file search.cpp.

{
       struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
       NdbTransaction *txn;
       NdbIndexScanOperation *scan;
       NdbScanFilter *sf = NULL;
       Entry e = {0};
       int rc, i, ocfilter, indexed;
       struct berval matched;
       NdbRecAttr *scanID, *scanOC, *scanDN[NDB_MAX_RDNS];
       char dnBuf[2048], *ptr;
       char idbuf[2*sizeof(ID)];
       char ocbuf[NDB_OC_BUFLEN];
       NdbRdns rdns;
       NdbOcInfo *oci;
       NdbArgs NA;
       slap_mask_t mask;
       time_t stoptime;
       int manageDSAit;

       rc = ndb_thread_handle( op, &NA.ndb );
       rdns.nr_num = 0;

       manageDSAit = get_manageDSAit( op );

       txn = NA.ndb->startTransaction();
       if ( !txn ) {
              Debug( LDAP_DEBUG_TRACE,
                     LDAP_XSTRING(ndb_back_search) ": startTransaction failed: %s (%d)\n",
                     NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 );
              rs->sr_err = LDAP_OTHER;
              rs->sr_text = "internal error";
              goto leave;
       }

       NA.txn = txn;
       e.e_name = op->o_req_dn;
       e.e_nname = op->o_req_ndn;
       NA.e = &e;
       NA.rdns = &rdns;
       NA.ocs = NULL;

       rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched );
       if ( rs->sr_err ) {
              if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
                     rs->sr_matched = matched.bv_val;
                     if ( NA.ocs )
                            ndb_check_referral( op, rs, &NA );
              }
              goto leave;
       }

       if ( !access_allowed_mask( op, &e, slap_schema.si_ad_entry,
              NULL, ACL_SEARCH, NULL, &mask )) {
              if ( !ACL_GRANT( mask, ACL_DISCLOSE ))
                     rs->sr_err = LDAP_NO_SUCH_OBJECT;
              else
                     rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
              ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
              goto leave;
       }

       rs->sr_err = ndb_entry_get_data( op, &NA, 0 );
       ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
       if ( rs->sr_err )
              goto leave;

       if ( !manageDSAit && is_entry_referral( &e )) {
              rs->sr_ref = get_entry_referrals( op, &e );
              rs->sr_err = LDAP_REFERRAL;
              if ( rs->sr_ref )
                     rs->sr_flags |= REP_REF_MUSTBEFREED;
              rs->sr_matched = e.e_name.bv_val;
              attrs_free( e.e_attrs );
              e.e_attrs = NULL;
              goto leave;
       }

       if ( !manageDSAit && is_entry_glue( &e )) {
              rs->sr_err = LDAP_NO_SUCH_OBJECT;
              goto leave;
       }

       if ( get_assert( op ) && test_filter( op, &e, (Filter *)get_assertion( op )) !=
              LDAP_COMPARE_TRUE ) {
              rs->sr_err = LDAP_ASSERTION_FAILED;
              attrs_free( e.e_attrs );
              e.e_attrs = NULL;
              goto leave;
       }

       /* admin ignores tlimits */
       stoptime = op->o_time + op->ors_tlimit;

       if ( op->ors_scope == LDAP_SCOPE_BASE ) {
              rc = test_filter( op, &e, op->ors_filter );
              if ( rc == LDAP_COMPARE_TRUE ) {
                     rs->sr_entry = &e;
                     rs->sr_attrs = op->ors_attrs;
                     rs->sr_flags = 0;
                     send_search_entry( op, rs );
                     rs->sr_entry = NULL;
              }
              attrs_free( e.e_attrs );
              e.e_attrs = NULL;
              rs->sr_err = LDAP_SUCCESS;
              goto leave;
       } else {
              attrs_free( e.e_attrs );
              e.e_attrs = NULL;
              if ( rdns.nr_num == NDB_MAX_RDNS ) {
                     if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ||
                            op->ors_scope == LDAP_SCOPE_CHILDREN )
                     rs->sr_err = LDAP_SUCCESS;
                     goto leave;
              }
       }

       /* See if we can handle the filter. Filtering on objectClass is only done
        * in the DN2ID table scan. If all other filter terms reside in one table,
        * then we scan the OC table instead of the DN2ID table.
        */
       oci = NULL;
       indexed = 0;
       ocfilter = 0;
       rc = ndb_filter_check( ni, op->ors_filter, &oci, &indexed, &ocfilter );
       if ( rc ) {
              Debug( LDAP_DEBUG_TRACE, "ndb_back_search: "
                     "filter attributes from multiple tables, indexing ignored\n",
                     0, 0, 0 );
       } else if ( oci ) {
              rc = ndb_oc_search( op, rs, NA.ndb, txn, &rdns, oci, indexed );
              goto leave;
       }

       scan = txn->getNdbIndexScanOperation( "PRIMARY", DN2ID_TABLE );
       if ( !scan ) {
              rs->sr_err = LDAP_OTHER;
              goto leave;
       }
       scan->readTuples( NdbOperation::LM_CommittedRead );
       rc = ndb_dn2bound( scan, &rdns );

       /* TODO: if ( ocfilter ) set up scanfilter for objectclass matches
        * column COND_LIKE "% <class> %"
        */

       switch( op->ors_scope ) {
       case LDAP_SCOPE_ONELEVEL:
              sf = new NdbScanFilter(scan);
              if ( sf->begin() < 0 ||
                     sf->cmp(NdbScanFilter::COND_NOT_LIKE, rc+3, "_%",
                            STRLENOF("_%")) < 0 ||
                     sf->end() < 0 ) {
                     rs->sr_err = LDAP_OTHER;
                     goto leave;
              }
              /* FALLTHRU */
       case LDAP_SCOPE_CHILDREN:
              /* Note: RDN_COLUMN offset not needed here */
              scan->setBound( rc, NdbIndexScanOperation::BoundLT, "\0" );
              /* FALLTHRU */
       case LDAP_SCOPE_SUBTREE:
              break;
       }
       scanID = scan->getValue( EID_COLUMN, idbuf );
       scanOC = scan->getValue( OCS_COLUMN, ocbuf );
       for ( i=0; i<NDB_MAX_RDNS; i++ ) {
              rdns.nr_buf[i][0] = '\0';
              scanDN[i] = scan->getValue( RDN_COLUMN+i, rdns.nr_buf[i] );
       }
       if ( txn->execute( NdbTransaction::NoCommit, NdbOperation::AbortOnError, 1 )) {
              rs->sr_err = LDAP_OTHER;
              goto leave;
       }

       e.e_name.bv_val = dnBuf;
       while ( scan->nextResult( true, true ) == 0 ) {
              if ( op->o_abandon ) {
                     rs->sr_err = SLAPD_ABANDON;
                     break;
              }
              if ( slapd_shutdown ) {
                     rs->sr_err = LDAP_UNAVAILABLE;
                     break;
              }
              if ( op->ors_tlimit != SLAP_NO_LIMIT &&
                     slap_get_time() > stoptime ) {
                     rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
                     break;
              }
              e.e_id = scanID->u_64_value();
              NA.ocs = ndb_ref2oclist( ocbuf, op->o_tmpmemctx );
              for ( i=0; i<NDB_MAX_RDNS; i++ ) {
                     if ( scanDN[i]->isNULL() || !rdns.nr_buf[i][0] )
                            break;
              }
              ptr = dnBuf;
              rdns.nr_num = i;
              for ( --i; i>=0; i-- ) {
                     char *buf;
                     int len;
                     buf = rdns.nr_buf[i];
                     len = *buf++;
                     ptr = lutil_strncopy( ptr, buf, len );
                     if ( i ) *ptr++ = ',';
              }
              *ptr = '\0';
              e.e_name.bv_len = ptr - dnBuf;
              dnNormalize( 0, NULL, NULL, &e.e_name, &e.e_nname, op->o_tmpmemctx );
              NA.txn = NA.ndb->startTransaction();
              rc = ndb_entry_get_data( op, &NA, 0 );
              NA.txn->close();
              ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
              if ( !manageDSAit && is_entry_referral( &e )) {
                     BerVarray erefs = get_entry_referrals( op, &e );
                     rs->sr_ref = referral_rewrite( erefs, &e.e_name, NULL,
                            op->ors_scope == LDAP_SCOPE_ONELEVEL ?
                                   LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
                     rc = send_search_reference( op, rs );
                     ber_bvarray_free( rs->sr_ref );
                     ber_bvarray_free( erefs );
                     rs->sr_ref = NULL;
              } else if ( manageDSAit || !is_entry_glue( &e )) {
                     rc = test_filter( op, &e, op->ors_filter );
                     if ( rc == LDAP_COMPARE_TRUE ) {
                            rs->sr_entry = &e;
                            rs->sr_attrs = op->ors_attrs;
                            rs->sr_flags = 0;
                            rc = send_search_entry( op, rs );
                            rs->sr_entry = NULL;
                     } else {
                            rc = 0;
                     }
              }
              attrs_free( e.e_attrs );
              e.e_attrs = NULL;
              op->o_tmpfree( e.e_nname.bv_val, op->o_tmpmemctx );
              if ( rc ) break;
       }
leave:
       if ( sf )
              delete sf;
       if ( txn )
              txn->close();
       send_ldap_result( op, rs );
       return rs->sr_err;
}
static int ndb_dn2bound ( NdbIndexScanOperation *  myop,
NdbRdns rdns 
) [static]

Definition at line 32 of file search.cpp.

{
       unsigned int i;

       /* Walk thru RDNs */
       for ( i=0; i<rdns->nr_num; i++ ) {
              /* Note: RDN_COLUMN offset not needed here */
              if ( myop->setBound( i, NdbIndexScanOperation::BoundEQ, rdns->nr_buf[i] ))
                     return LDAP_OTHER;
       }
       return i;
}

Here is the caller graph for this function:

static int ndb_filter_check ( struct ndb_info ni,
Filter f,
NdbOcInfo **  oci,
int indexed,
int ocfilter 
) [static]

Definition at line 56 of file search.cpp.

{
       AttributeDescription *ad = NULL;
       ber_tag_t choice = f->f_choice;
       int rc = 0, undef = 0;

       if ( choice & SLAPD_FILTER_UNDEFINED ) {
              choice &= SLAPD_FILTER_MASK;
              undef = 1;
       }
       switch( choice ) {
       case LDAP_FILTER_AND:
       case LDAP_FILTER_OR:
       case LDAP_FILTER_NOT:
              for ( f = f->f_list; f; f=f->f_next ) {
                     rc = ndb_filter_check( ni, f, oci, indexed, ocfilter );
                     if ( rc ) return rc;
              }
              break;
       case LDAP_FILTER_PRESENT:
              ad = f->f_desc;
              break;
       case LDAP_FILTER_EQUALITY:
       case LDAP_FILTER_SUBSTRINGS:
       case LDAP_FILTER_GE:
       case LDAP_FILTER_LE:
       case LDAP_FILTER_APPROX:
              ad = f->f_av_desc;
              break;
       default:
              break;
       }
       if ( ad && !undef ) {
              NdbAttrInfo *ai;
              /* ObjectClass filtering is in dn2id table */
              if ( ad == slap_schema.si_ad_objectClass ) {
                     if ( choice == LDAP_FILTER_EQUALITY )
                            (*ocfilter)++;
                     return 0;
              }
              ai = ndb_ai_find( ni, ad->ad_type );
              if ( ai ) {
                     if ( ai->na_flag & NDB_INFO_INDEX )
                            (*indexed)++;
                     if ( *oci ) {
                            if ( ai->na_oi != *oci )
                                   rc = -1;
                     } else {
                            *oci = ai->na_oi;
                     }
              }
       }
       return rc;
}

Here is the call graph for this function:

static int ndb_filter_set ( Operation op,
struct ndb_info ni,
Filter f,
int  indexed,
NdbIndexScanOperation *  scan,
NdbScanFilter *  sf,
int bounds 
) [static]

Definition at line 112 of file search.cpp.

{
       AttributeDescription *ad = NULL;
       ber_tag_t choice = f->f_choice;
       int undef = 0;

       if ( choice & SLAPD_FILTER_UNDEFINED ) {
              choice &= SLAPD_FILTER_MASK;
              undef = 1;
       }
       switch( choice ) {
       case LDAP_FILTER_NOT:
              /* no indexing for these */
              break;
       case LDAP_FILTER_OR:
              /* FIXME: these bounds aren't right. */
              if ( indexed ) {
                     scan->end_of_bound( (*bounds)++ );
              }
       case LDAP_FILTER_AND:
              if ( sf ) {
                     sf->begin( choice == LDAP_FILTER_OR ? NdbScanFilter::OR : NdbScanFilter::AND );
              }
              for ( f = f->f_list; f; f=f->f_next ) {
                     if ( ndb_filter_set( op, ni, f, indexed, scan, sf, bounds ))
                            return -1;
              }
              if ( sf ) {
                     sf->end();
              }
              break;
       case LDAP_FILTER_PRESENT:
              ad = f->f_desc;
              break;
       case LDAP_FILTER_EQUALITY:
       case LDAP_FILTER_SUBSTRINGS:
       case LDAP_FILTER_GE:
       case LDAP_FILTER_LE:
       case LDAP_FILTER_APPROX:
              ad = f->f_av_desc;
              break;
       default:
              break;
       }
       if ( ad && !undef ) {
              NdbAttrInfo *ai;
              /* ObjectClass filtering is in dn2id table */
              if ( ad == slap_schema.si_ad_objectClass ) {
                     return 0;
              }
              ai = ndb_ai_find( ni, ad->ad_type );
              if ( ai ) {
                     int rc;
                     if ( ai->na_flag & NDB_INFO_INDEX ) {
                            char *buf, *ptr;
                            NdbIndexScanOperation::BoundType bt;

                            switch(choice) {
                            case LDAP_FILTER_PRESENT:
                                   rc = scan->setBound( ai->na_ixcol - IDX_COLUMN,
                                          NdbIndexScanOperation::BoundGT, NULL );
                                   break;
                            case LDAP_FILTER_EQUALITY:
                            case LDAP_FILTER_APPROX:
                                   bt = NdbIndexScanOperation::BoundEQ;
                                   goto setit;
                            case LDAP_FILTER_GE:
                                   bt = NdbIndexScanOperation::BoundGE;
                                   goto setit;
                            case LDAP_FILTER_LE:
                                   bt = NdbIndexScanOperation::BoundLE;
                            setit:
                                   rc = f->f_av_value.bv_len+1;
                                   if ( ai->na_len > 255 )
                                          rc++;
                                   buf = (char *)op->o_tmpalloc( rc, op->o_tmpmemctx );
                                   rc = f->f_av_value.bv_len;
                                   buf[0] = rc & 0xff;
                                   ptr = buf+1;
                                   if ( ai->na_len > 255 ) {
                                          buf[1] = (rc >> 8);
                                          ptr++;
                                   }
                                   memcpy( ptr, f->f_av_value.bv_val, f->f_av_value.bv_len );
                                   rc = scan->setBound( ai->na_ixcol - IDX_COLUMN, bt, buf );
                                   op->o_tmpfree( buf, op->o_tmpmemctx );
                                   break;
                            default:
                                   break;
                            }
                     } else if ( sf ) {
                            char *buf, *ptr;
                            NdbScanFilter::BinaryCondition bc;

                            switch(choice) {
                            case LDAP_FILTER_PRESENT:
                                   rc = sf->isnotnull( ai->na_column );
                                   break;
                            case LDAP_FILTER_EQUALITY:
                            case LDAP_FILTER_APPROX:
                                   bc = NdbScanFilter::COND_EQ;
                                   goto setf;
                            case LDAP_FILTER_GE:
                                   bc = NdbScanFilter::COND_GE;
                                   goto setf;
                            case LDAP_FILTER_LE:
                                   bc = NdbScanFilter::COND_LE;
                            setf:
                                   rc = sf->cmp( bc, ai->na_column, f->f_av_value.bv_val, f->f_av_value.bv_len );
                                   break;
                            case LDAP_FILTER_SUBSTRINGS:
                                   rc = 0;
                                   if ( f->f_sub_initial.bv_val )
                                          rc += f->f_sub_initial.bv_len + 1;
                                   if ( f->f_sub_any ) {
                                          int i;
                                          if ( !rc ) rc++;
                                          for (i=0; f->f_sub_any[i].bv_val; i++)
                                                 rc += f->f_sub_any[i].bv_len + 1;
                                   }
                                   if ( f->f_sub_final.bv_val ) {
                                          if ( !rc ) rc++;
                                          rc += f->f_sub_final.bv_len;
                                   }
                                   buf = (char *)op->o_tmpalloc( rc+1, op->o_tmpmemctx );
                                   ptr = buf;
                                   if ( f->f_sub_initial.bv_val ) {
                                          memcpy( ptr, f->f_sub_initial.bv_val, f->f_sub_initial.bv_len );
                                          ptr += f->f_sub_initial.bv_len;
                                          *ptr++ = '%';
                                   }
                                   if ( f->f_sub_any ) {
                                          int i;
                                          if ( ptr == buf )
                                                 *ptr++ = '%';
                                          for (i=0; f->f_sub_any[i].bv_val; i++) {
                                                 memcpy( ptr, f->f_sub_any[i].bv_val, f->f_sub_any[i].bv_len );
                                                 ptr += f->f_sub_any[i].bv_len;
                                                 *ptr++ = '%';
                                          }
                                   }
                                   if ( f->f_sub_final.bv_val ) {
                                          if ( ptr == buf )
                                                 *ptr++ = '%';
                                          memcpy( ptr, f->f_sub_final.bv_val, f->f_sub_final.bv_len );
                                          ptr += f->f_sub_final.bv_len;
                                   }
                                   *ptr = '\0';
                                   rc = sf->cmp( NdbScanFilter::COND_LIKE, ai->na_column, buf, ptr - buf );
                                   op->o_tmpfree( buf, op->o_tmpmemctx );
                                   break;
                            }
                     }
              }
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ndb_has_children ( NdbArgs NA,
int hasChildren 
)

Definition at line 754 of file search.cpp.

{
       NdbIndexScanOperation *scan;
       char idbuf[2*sizeof(ID)];
       int rc;

       if ( NA->rdns->nr_num >= NDB_MAX_RDNS ) {
              *hasChildren = LDAP_COMPARE_FALSE;
              return 0;
       }

       scan = NA->txn->getNdbIndexScanOperation( "PRIMARY", DN2ID_TABLE );
       if ( !scan )
              return LDAP_OTHER;
       scan->readTuples( NdbOperation::LM_Read, 0U, 0U, 1U );
       rc = ndb_dn2bound( scan, NA->rdns );
       if ( rc < NDB_MAX_RDNS ) {
              scan->setBound( rc, NdbIndexScanOperation::BoundLT, "\0" );
       }
#if 0
       scan->interpret_exit_last_row();
#else
       scan->setInterpretedCode(ndb_lastrow_code);
#endif
       scan->getValue( EID_COLUMN, idbuf );
       if ( NA->txn->execute( NdbTransaction::NoCommit, NdbOperation::AO_IgnoreError, 1 )) {
              return LDAP_OTHER;
       }
       if (rc < NDB_MAX_RDNS && scan->nextResult( true, true ) == 0 )
              *hasChildren = LDAP_COMPARE_TRUE;
       else
              *hasChildren = LDAP_COMPARE_FALSE;
       scan->close();
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ndb_has_subordinates ( Operation op,
Entry e,
int hasSubordinates 
)

Definition at line 794 of file search.cpp.

{
       NdbArgs NA;
       NdbRdns rdns;
       int rc;

       NA.rdns = &rdns;
       rc = ndb_dn2rdns( &e->e_nname, &rdns );

       if ( rc == 0 ) {
              rc = ndb_thread_handle( op, &NA.ndb );
              NA.txn = NA.ndb->startTransaction();
              if ( NA.txn ) {
                     rc = ndb_has_children( &NA, hasSubordinates );
                     NA.txn->close();
              }
       }

       return rc;
}

Here is the call graph for this function:

static int ndb_oc_search ( Operation op,
SlapReply rs,
Ndb *  ndb,
NdbTransaction *  txn,
NdbRdns rbase,
NdbOcInfo oci,
int  indexed 
) [static]

Definition at line 271 of file search.cpp.

{
       struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
       const NdbDictionary::Dictionary *myDict = ndb->getDictionary();
       const NdbDictionary::Table *myTable;
       const NdbDictionary::Index *myIndex;
       NdbIndexScanOperation *scan;
       NdbIndexOperation *ixop;
       NdbScanFilter *sf = NULL;
       struct berval *ocs;
       NdbRecAttr *scanID, *scanOC, *scanDN[NDB_MAX_RDNS];
       char dnBuf[2048], *ptr;
       NdbRdns rdns;
       NdbArgs NA;
       char idbuf[2*sizeof(ID)];
       char ocbuf[NDB_OC_BUFLEN];
       int i, rc, bounds;
       Entry e = {0};
       Uint64 eid;
       time_t stoptime;
       int manageDSAit;

       stoptime = op->o_time + op->ors_tlimit;
       manageDSAit = get_manageDSAit( op );

       myTable = myDict->getTable( oci->no_table.bv_val );
       if ( indexed ) { 
              scan = txn->getNdbIndexScanOperation( INDEX_NAME, DN2ID_TABLE );
              if ( !scan )
                     return LDAP_OTHER;
              scan->readTuples( NdbOperation::LM_CommittedRead );
       } else {
              myIndex = myDict->getIndex( "eid$unique", DN2ID_TABLE );
              if ( !myIndex ) {
                     Debug( LDAP_DEBUG_ANY, DN2ID_TABLE " eid index is missing!\n", 0, 0, 0 );
                     rs->sr_err = LDAP_OTHER;
                     goto leave;
              }
              scan = (NdbIndexScanOperation *)txn->getNdbScanOperation( myTable );
              if ( !scan )
                     return LDAP_OTHER;
              scan->readTuples( NdbOperation::LM_CommittedRead );
#if 1
              sf = new NdbScanFilter(scan);
              if ( !sf )
                     return LDAP_OTHER;
              switch ( op->ors_filter->f_choice ) {
              case LDAP_FILTER_AND:
              case LDAP_FILTER_OR:
              case LDAP_FILTER_NOT:
                     break;
              default:
                     if ( sf->begin() < 0 ) {
                            rc = LDAP_OTHER;
                            goto leave;
                     }
              }
#endif
       }

       bounds = 0;
       rc = ndb_filter_set( op, ni, op->ors_filter, indexed, scan, sf, &bounds );
       if ( rc )
              goto leave;
       if ( sf ) sf->end();
       
       scanID = scan->getValue( EID_COLUMN, idbuf );
       if ( indexed ) {
              scanOC = scan->getValue( OCS_COLUMN, ocbuf );
              for ( i=0; i<NDB_MAX_RDNS; i++ ) {
                     rdns.nr_buf[i][0] = '\0';
                     scanDN[i] = scan->getValue( RDN_COLUMN+i, rdns.nr_buf[i] );
              }
       }

       if ( txn->execute( NdbTransaction::NoCommit, NdbOperation::AbortOnError, 1 )) {
              rs->sr_err = LDAP_OTHER;
              goto leave;
       }

       e.e_name.bv_val = dnBuf;
       NA.e = &e;
       NA.ndb = ndb;
       while ( scan->nextResult( true, true ) == 0 ) {
              NdbTransaction *tx2;
              if ( op->o_abandon ) {
                     rs->sr_err = SLAPD_ABANDON;
                     break;
              }
              if ( slapd_shutdown ) {
                     rs->sr_err = LDAP_UNAVAILABLE;
                     break;
              }
              if ( op->ors_tlimit != SLAP_NO_LIMIT &&
                     slap_get_time() > stoptime ) {
                     rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
                     break;
              }

              eid = scanID->u_64_value();
              e.e_id = eid;
              if ( !indexed ) {
                     tx2 = ndb->startTransaction( myTable );
                     if ( !tx2 ) {
                            rs->sr_err = LDAP_OTHER;
                            goto leave;
                     }

                     ixop = tx2->getNdbIndexOperation( myIndex );
                     if ( !ixop ) {
                            tx2->close();
                            rs->sr_err = LDAP_OTHER;
                            goto leave;
                     }
                     ixop->readTuple( NdbOperation::LM_CommittedRead );
                     ixop->equal( EID_COLUMN, eid );

                     scanOC = ixop->getValue( OCS_COLUMN, ocbuf );
                     for ( i=0; i<NDB_MAX_RDNS; i++ ) {
                            rdns.nr_buf[i][0] = '\0';
                            scanDN[i] = ixop->getValue( RDN_COLUMN+i, rdns.nr_buf[i] );
                     }
                     rc = tx2->execute( NdbTransaction::Commit, NdbOperation::AbortOnError, 1 );
                     tx2->close();
                     if ( rc ) {
                            rs->sr_err = LDAP_OTHER;
                            goto leave;
                     }
              }

              ocs = ndb_ref2oclist( ocbuf, op->o_tmpmemctx );
              for ( i=0; i<NDB_MAX_RDNS; i++ ) {
                     if ( scanDN[i]->isNULL() || !rdns.nr_buf[i][0] )
                            break;
              }
              rdns.nr_num = i;

              /* entry must be subordinate to the base */
              if ( i < rbase->nr_num ) {
                     continue;
              }

              ptr = dnBuf;
              for ( --i; i>=0; i-- ) {
                     char *buf;
                     int len;
                     buf = rdns.nr_buf[i];
                     len = *buf++;
                     ptr = lutil_strncopy( ptr, buf, len );
                     if ( i ) *ptr++ = ',';
              }
              *ptr = '\0';
              e.e_name.bv_len = ptr - dnBuf;

              /* More scope checks */
              /* If indexed, these can be moved into the ScanFilter */
              switch( op->ors_scope ) {
              case LDAP_SCOPE_ONELEVEL:
                     if ( rdns.nr_num != rbase->nr_num+1 )
                            continue;
              case LDAP_SCOPE_SUBORDINATE:
                     if ( rdns.nr_num == rbase->nr_num )
                            continue;
              case LDAP_SCOPE_SUBTREE:
              default:
                     if ( e.e_name.bv_len <= op->o_req_dn.bv_len ) {
                            if ( op->ors_scope != LDAP_SCOPE_SUBTREE ||
                                   strcasecmp( op->o_req_dn.bv_val, e.e_name.bv_val ))
                                   continue;
                     } else if ( strcasecmp( op->o_req_dn.bv_val, e.e_name.bv_val +
                            e.e_name.bv_len - op->o_req_dn.bv_len ))
                            continue;
              }

              dnNormalize( 0, NULL, NULL, &e.e_name, &e.e_nname, op->o_tmpmemctx );
              {
#if 1  /* NDBapi was broken here but seems to work now */
                     Ndb::Key_part_ptr keys[2];
                     char xbuf[512];
                     keys[0].ptr = &eid;
                     keys[0].len = sizeof(eid);
                     keys[1].ptr = NULL;
                     keys[1].len = 0;
                     tx2 = ndb->startTransaction( myTable, keys, xbuf, sizeof(xbuf));
#else
                     tx2 = ndb->startTransaction( myTable );
#endif
                     if ( !tx2 ) {
                            rs->sr_err = LDAP_OTHER;
                            goto leave;
                     }
                     NA.txn = tx2;
                     NA.ocs = ocs;
                     rc = ndb_entry_get_data( op, &NA, 0 );
                     tx2->close();
              }
              ber_bvarray_free_x( ocs, op->o_tmpmemctx );
              if ( !manageDSAit && is_entry_referral( &e )) {
                     BerVarray erefs = get_entry_referrals( op, &e );
                     rs->sr_ref = referral_rewrite( erefs, &e.e_name, NULL,
                            op->ors_scope == LDAP_SCOPE_ONELEVEL ?
                                   LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
                     rc = send_search_reference( op, rs );
                     ber_bvarray_free( rs->sr_ref );
                     ber_bvarray_free( erefs );
                     rs->sr_ref = NULL;
              } else if ( manageDSAit || !is_entry_glue( &e )) {
                     rc = test_filter( op, &e, op->ors_filter );
                     if ( rc == LDAP_COMPARE_TRUE ) {
                            rs->sr_entry = &e;
                            rs->sr_attrs = op->ors_attrs;
                            rs->sr_flags = 0;
                            rc = send_search_entry( op, rs );
                            rs->sr_entry = NULL;
                            rs->sr_attrs = NULL;
                     } else {
                            rc = 0;
                     }
              }
              attrs_free( e.e_attrs );
              e.e_attrs = NULL;
              op->o_tmpfree( e.e_nname.bv_val, op->o_tmpmemctx );
              if ( rc ) break;
       }
leave:
       if ( sf ) delete sf;
       return rc;
}

Here is the call graph for this function:

int ndb_operational ( Operation op,
SlapReply rs 
)

Definition at line 822 of file search.cpp.

{
       Attribute     **ap;

       assert( rs->sr_entry != NULL );

       for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
              if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
                     break;
              }
       }

       if ( *ap == NULL &&
              attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL &&
              ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
                     ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) )
       {
              int    hasSubordinates, rc;

              rc = ndb_has_subordinates( op, rs->sr_entry, &hasSubordinates );
              if ( rc == LDAP_SUCCESS ) {
                     *ap = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE );
                     assert( *ap != NULL );

                     ap = &(*ap)->a_next;
              }
       }

       return LDAP_SUCCESS;
}

Here is the call graph for this function:


Variable Documentation

NdbInterpretedCode* ndb_lastrow_code

Definition at line 65 of file init.cpp.