Bug 222827

Summary: SLAPI_PLUGIN_PRE_ENTRY_FN cached entry problem?
Product: [Retired] 389 Reporter: Martin <m.d.t.evans>
Component: Directory ServerAssignee: Rich Megginson <rmeggins>
Status: CLOSED NOTABUG QA Contact: Orla Hegarty <ohegarty>
Severity: medium Docs Contact:
Priority: medium    
Version: 1.0.4   
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2007-01-25 16:58:20 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Martin 2007-01-16 13:29:36 UTC
Description of problem:

I'm writing a ns/slapi directory plugin and am seeing some strange behaviour.
The plugin registers a function that is run when the server is passing entries
back to the client (i.e. registered as SLAPI_PLUGIN_PRE_ENTRY_FN in the plugin
init script).

The plugin is fairly simple (can supply if needed), currently, it simply adds a
list of telephone numbers (held in a special attribute called
qmulInternalTelephoneNumber) to the standard telephoneNumber attribute.

The attributes are retrieved and set from the entry with the slapi api
(slapi_attr_first_value/slapi_entry_add_value). But it seems that the modified
entry is cached somewhere and is used in place of the original in subsequent
searches.

Version-Release number of selected component (if applicable):

1.0.4

How reproducible:

Always.

Steps to Reproduce:
1. Load plugin.
2. Restart slapd
3. Run 2 identical searches.
  
Actual results:

The first search fails to return an entry that has added the list of
qmulinternalTelephoneNumbers to telephoneNumber. This code currently (its in
development) looks like this (just a 2 dumb loops):

  /* get the search entry */
  if (slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e)!=0) {
    LOG("[%i] failed to get original_results\n",conn_id);
    goto end;
  }

  /* get the internal number if there is one if there isnt one
     then we have nothing to do. */  
  if (slapi_entry_attr_find(e,"qmulInternalTelephoneNumber",&ai)) {
    DEBUG("[%i] no qmulInternalTelephoneNumber - skipping to end\n",conn_id);
    goto end;
  }
  
  /* get the external number if there is one - dont care
     if it is there or not. */
  slapi_entry_attr_find(e,"telephoneNumber",&ae);
  
  /* loop over the external number to see if we already have
     the internal numbers listed */
  {   
    Slapi_Value *ve=NULL;
    Slapi_Value *vi=NULL;
    char *se;
    char *si;
    int he,hi;
    for (hi=slapi_attr_first_value(ai,&vi); hi!=-1;
         hi=slapi_attr_next_value(ai,hi,&vi)) {
      si=(char*)slapi_value_get_string(vi);
      int notgotit=1;
      for (he=slapi_attr_first_value(ae,&ve); he!=-1;
           he=slapi_attr_next_value(ae,he,&ve )) {
        se=(char*)slapi_value_get_string(ve);
        DEBUG("[%i]cmp si=%s se=%s\n",conn_id,si,se);
        if(!strcmp(si,se)){
          notgotit=0;
          DEBUG("[%i] found.\n",conn_id);
	}
      }
      if(notgotit){
        LOG("[%i] adding int tel: %s\n",conn_id,si);
        slapi_entry_add_value(e,"telephoneNumber",slapi_value_dup(vi));
      }
    }
    
    return (LDAP_SUCCESS)

But the first search fails to return the combined list:

The bash-3.1$ ldapsearch -h xxx.qmul.ac.uk -x -s sub  -b"o=queen mary and
westfield college,c=gb" -LLL "(mail=xxxx.uk)"
dn: cn=M D T Evans, ou=Information Services, o=Queen Mary and Westfield Colleg
 e, c=GB
<snip>
telephoneNumber: +44 20 7822 XXXX
telephoneNumber: +44 20 7822 YYYY
qmulInternalTelephoneNumber: 13 XXXX
qmulInternalTelephoneNumber: 13 YYYY

But the error log suggests that the code is working:

[16/Jan/2007:13:15:05 +0000] dirfilter (debug) - [2] processing results of
search under: o=queen mary and westfield college,c=gb
[16/Jan/2007:13:15:05 +0000] dirfilter (debug) - [2]cmp si=13 3739 se=+44 20
7822 3739
[16/Jan/2007:13:15:05 +0000] dirfilter (debug) - [2]cmp si=13 3739 se=+44 20
7822 5555
[16/Jan/2007:13:15:05 +0000] dirfilter - [2] adding int tel: 13 3739
[16/Jan/2007:13:15:05 +0000] dirfilter (debug) - [2]cmp si=13 5555 se=+44 20
7822 3739
[16/Jan/2007:13:15:05 +0000] dirfilter (debug) - [2]cmp si=13 5555 se=+44 20
7822 5555
[16/Jan/2007:13:15:05 +0000] dirfilter (debug) - [2]cmp si=13 5555 se=13 3739
[16/Jan/2007:13:15:05 +0000] dirfilter - [2] adding int tel: 13 5555
[16/Jan/2007:13:15:05 +0000] dirfilter (debug) - [2] finish

A subsequent search gives the combined list of telephone attributes, but the log
suggests that the values are already in the entry recovered with
SLAPI_SEARCH_RESULT_ENTRY. i.e.

==> /opt/fedora-ds/slapd-mdte3/logs/errors <==
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3] processing results of
search under: o=queen mary and westfield college,c=gb
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3]cmp si=13 3739 se=+44 20
7822 3739
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3]cmp si=13 3739 se=+44 20
7822 5555
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3]cmp si=13 3739 se=13 3739
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3] found.
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3]cmp si=13 3739 se=13 5555
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3]cmp si=13 5555 se=+44 20
7822 3739
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3]cmp si=13 5555 se=+44 20
7822 5555
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3]cmp si=13 5555 se=13 3739
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3]cmp si=13 5555 se=13 5555
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3] found.
[16/Jan/2007:13:15:16 +0000] dirfilter (debug) - [3] finish

Expected results:

I'd expect entries recovered by the parameter block call to
SLAPI_SEARCH_RESULT_ENTRY to be the same and not to include the combined
attribute list.


Additional info:

My suspicion is that the plugin function I have called is using a modified
cached value of the entry.

Comment 1 Rich Megginson 2007-01-23 23:53:56 UTC
Yes, that's what's happening.  When you modify the SLAPI_SEARCH_RESULT_ENTRY,
you are modifying the entry directly inside the entry cache.  The entry provided
by SLAPI_SEARCH_RESULT_ENTRY in a SLAPI_PLUGIN_PRE_ENTRY_FN should be considered
read only - there is no way to modify the entry to be returned.  At the point in
the code where SLAPI_PLUGIN_PRE_ENTRY_FN is called (flush_ber() - result.c:1488)
the BER has already been formed.  I'm not sure what the purpose of the
SLAPI_PLUGIN_PRE_ENTRY_FN is except possibly to allow you to look at the entry
to be returned or possibly abort the return, but not to modify it.

If you want to change the results as they are returned to the client, you should
probably look at the virtual attribute interface.  I _think_ this will allow you
to add "virtual" values to telephoneNumber.

Comment 2 Martin 2007-01-25 16:58:20 UTC
OK. Fair enough. I've had a look at the vattr interface and it seems that I can
do everything that I want to with that. Thanks for the tip.