Back to index

openldap  2.4.31
Classes | Typedefs | Functions
cache.c File Reference
#include "portable.h"
#include <stdio.h>
#include "ac/string.h"
#include "slap.h"
#include "back-monitor.h"

Go to the source code of this file.

Classes

struct  monitor_cache_t

Typedefs

typedef struct monitor_cache_t monitor_cache_t

Functions

int monitor_cache_cmp (const void *c1, const void *c2)
int monitor_cache_dup (void *c1, void *c2)
int monitor_cache_add (monitor_info_t *mi, Entry *e)
int monitor_cache_lock (Entry *e)
int monitor_cache_trylock (Entry *e)
int monitor_cache_get (monitor_info_t *mi, struct berval *ndn, Entry **ep)
int monitor_cache_remove (monitor_info_t *mi, struct berval *ndn, Entry **ep)
int monitor_cache_dn2entry (Operation *op, SlapReply *rs, struct berval *ndn, Entry **ep, Entry **matched)
int monitor_cache_release (monitor_info_t *mi, Entry *e)
static void monitor_entry_destroy (void *v_mc)
int monitor_cache_destroy (monitor_info_t *mi)
int monitor_back_release (Operation *op, Entry *e, int rw)

Class Documentation

struct monitor_cache_t

Definition at line 37 of file cache.c.

Collaboration diagram for monitor_cache_t:
Class Members
Entry * mc_e

Typedef Documentation


Function Documentation

int monitor_back_release ( Operation op,
Entry e,
int  rw 
)

Definition at line 442 of file cache.c.

{
       monitor_info_t       *mi = ( monitor_info_t * )op->o_bd->be_private;
       return monitor_cache_release( mi, e );
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 80 of file cache.c.

{
       monitor_cache_t      *mc;
       monitor_entry_t      *mp;
       int           rc;

       assert( mi != NULL );
       assert( e != NULL );

       mp = ( monitor_entry_t *)e->e_private;

       mc = ( monitor_cache_t * )ch_malloc( sizeof( monitor_cache_t ) );
       mc->mc_ndn = e->e_nname;
       mc->mc_e = e;
       ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
       rc = avl_insert( &mi->mi_cache, ( caddr_t )mc,
                     monitor_cache_cmp, monitor_cache_dup );
       ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int monitor_cache_cmp ( const void c1,
const void c2 
)

Definition at line 46 of file cache.c.

{
       monitor_cache_t      *cc1 = ( monitor_cache_t * )c1;
       monitor_cache_t      *cc2 = ( monitor_cache_t * )c2;

       /*
        * case sensitive, because the dn MUST be normalized
        */
       return ber_bvcmp( &cc1->mc_ndn, &cc2->mc_ndn );
}

Here is the caller graph for this function:

Definition at line 432 of file cache.c.

{
       if ( mi->mi_cache ) {
              avl_free( mi->mi_cache, monitor_entry_destroy );
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int monitor_cache_dn2entry ( Operation op,
SlapReply rs,
struct berval ndn,
Entry **  ep,
Entry **  matched 
)

Definition at line 290 of file cache.c.

{
       monitor_info_t *mi = (monitor_info_t *)op->o_bd->be_private;
       int                  rc;
       struct berval        p_ndn = BER_BVNULL;
       Entry                *e_parent;
       monitor_entry_t      *mp;
              
       assert( mi != NULL );
       assert( ndn != NULL );
       assert( ep != NULL );
       assert( matched != NULL );

       *matched = NULL;

       if ( !dnIsSuffix( ndn, &op->o_bd->be_nsuffix[ 0 ] ) ) {
              return( -1 );
       }

       rc = monitor_cache_get( mi, ndn, ep );
              if ( !rc && *ep != NULL ) {
              return( 0 );
       }

       /* try with parent/ancestors */
       if ( BER_BVISNULL( ndn ) ) {
              BER_BVSTR( &p_ndn, "" );

       } else {
              dnParent( ndn, &p_ndn );
       }

       rc = monitor_cache_dn2entry( op, rs, &p_ndn, &e_parent, matched );
       if ( rc || e_parent == NULL ) {
              return( -1 );
       }

       mp = ( monitor_entry_t * )e_parent->e_private;
       rc = -1;
       if ( mp->mp_flags & MONITOR_F_VOLATILE_CH ) {
              /* parent entry generates volatile children */
              rc = monitor_entry_create( op, rs, ndn, e_parent, ep );
       }

       if ( !rc ) {
              monitor_cache_lock( *ep );
              monitor_cache_release( mi, e_parent );

       } else {
              *matched = e_parent;
       }
       
       return( rc );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int monitor_cache_dup ( void c1,
void c2 
)

Definition at line 63 of file cache.c.

{
       monitor_cache_t *cc1 = ( monitor_cache_t * )c1;
       monitor_cache_t *cc2 = ( monitor_cache_t * )c2;

       /*
        * case sensitive, because the dn MUST be normalized
        */
       return ber_bvcmp( &cc1->mc_ndn, &cc2->mc_ndn ) == 0 ? -1 : 0;
}

Here is the caller graph for this function:

int monitor_cache_get ( monitor_info_t mi,
struct berval ndn,
Entry **  ep 
)

Definition at line 143 of file cache.c.

{
       monitor_cache_t tmp_mc, *mc;

       assert( mi != NULL );
       assert( ndn != NULL );
       assert( ep != NULL );

       *ep = NULL;

       tmp_mc.mc_ndn = *ndn;
retry:;
       ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
       mc = ( monitor_cache_t * )avl_find( mi->mi_cache,
                     ( caddr_t )&tmp_mc, monitor_cache_cmp );

       if ( mc != NULL ) {
              /* entry is returned with mutex locked */
              if ( monitor_cache_trylock( mc->mc_e ) ) {
                     ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
                     ldap_pvt_thread_yield();
                     goto retry;
              }
              *ep = mc->mc_e;
       }

       ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );

       return ( *ep == NULL ? -1 : 0 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 108 of file cache.c.

{
       monitor_entry_t *mp;

       assert( e != NULL );
       assert( e->e_private != NULL );

       mp = ( monitor_entry_t * )e->e_private;
       ldap_pvt_thread_mutex_lock( &mp->mp_mutex );

       return( 0 );
}

Here is the caller graph for this function:

Definition at line 355 of file cache.c.

{
       monitor_entry_t *mp;

       assert( mi != NULL );
       assert( e != NULL );
       assert( e->e_private != NULL );
       
       mp = ( monitor_entry_t * )e->e_private;

       if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
              monitor_cache_t      *mc, tmp_mc;

              /* volatile entries do not return to cache */
              ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
              tmp_mc.mc_ndn = e->e_nname;
              mc = avl_delete( &mi->mi_cache,
                            ( caddr_t )&tmp_mc, monitor_cache_cmp );
              ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
              if ( mc != NULL ) {
                     ch_free( mc );
              }
              
              ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
              ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
              ch_free( mp );
              e->e_private = NULL;
              entry_free( e );

              return( 0 );
       }
       
       ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );

       return( 0 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int monitor_cache_remove ( monitor_info_t mi,
struct berval ndn,
Entry **  ep 
)

Definition at line 182 of file cache.c.

{
       monitor_cache_t tmp_mc, *mc;
       struct berval pndn;

       assert( mi != NULL );
       assert( ndn != NULL );
       assert( ep != NULL );

       *ep = NULL;

       dnParent( ndn, &pndn );

retry:;
       ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );

       tmp_mc.mc_ndn = *ndn;
       mc = ( monitor_cache_t * )avl_find( mi->mi_cache,
                     ( caddr_t )&tmp_mc, monitor_cache_cmp );

       if ( mc != NULL ) {
              monitor_cache_t *pmc;

              if ( monitor_cache_trylock( mc->mc_e ) ) {
                     ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
                     goto retry;
              }

              tmp_mc.mc_ndn = pndn;
              pmc = ( monitor_cache_t * )avl_find( mi->mi_cache,
                     ( caddr_t )&tmp_mc, monitor_cache_cmp );
              if ( pmc != NULL ) {
                     monitor_entry_t      *mp = (monitor_entry_t *)mc->mc_e->e_private,
                                   *pmp = (monitor_entry_t *)pmc->mc_e->e_private;
                     Entry         **entryp;

                     if ( monitor_cache_trylock( pmc->mc_e ) ) {
                            monitor_cache_release( mi, mc->mc_e );
                            ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
                            goto retry;
                     }

                     for ( entryp = &pmp->mp_children; *entryp != NULL;  ) {
                            monitor_entry_t      *next = (monitor_entry_t *)(*entryp)->e_private;
                            if ( next == mp ) {
                                   *entryp = next->mp_next;
                                   entryp = NULL;
                                   break;
                            }

                            entryp = &next->mp_next;
                     }

                     if ( entryp != NULL ) {
                            Debug( LDAP_DEBUG_ANY,
                                   "monitor_cache_remove(\"%s\"): "
                                   "not in parent's list\n",
                                   ndn->bv_val, 0, 0 );
                     }

                     /* either succeeded, and the entry is no longer
                      * in its parent's list, or failed, and the
                      * entry is neither mucked with nor returned */
                     monitor_cache_release( mi, pmc->mc_e );

                     if ( entryp == NULL ) {
                            monitor_cache_t *tmpmc;

                            tmp_mc.mc_ndn = *ndn;
                            tmpmc = avl_delete( &mi->mi_cache,
                                   ( caddr_t )&tmp_mc, monitor_cache_cmp );
                            assert( tmpmc == mc );

                            *ep = mc->mc_e;
                            ch_free( mc );
                            mc = NULL;

                            /* NOTE: we destroy the mutex, but otherwise
                             * leave the private data around; specifically,
                             * callbacks need be freed by someone else */

                            ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
                            mp->mp_next = NULL;
                            mp->mp_children = NULL;
                     }

              }

              if ( mc ) {
                     monitor_cache_release( mi, mc->mc_e );
              }
       }

       ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );

       return ( *ep == NULL ? -1 : 0 );
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 126 of file cache.c.

{
       monitor_entry_t *mp;

       assert( e != NULL );
       assert( e->e_private != NULL );

       mp = ( monitor_entry_t * )e->e_private;
       return ldap_pvt_thread_mutex_trylock( &mp->mp_mutex );
}

Here is the caller graph for this function:

static void monitor_entry_destroy ( void v_mc) [static]

Definition at line 395 of file cache.c.

{
       monitor_cache_t             *mc = (monitor_cache_t *)v_mc;

       if ( mc->mc_e != NULL ) {
              monitor_entry_t *mp;

              assert( mc->mc_e->e_private != NULL );
       
              mp = ( monitor_entry_t * )mc->mc_e->e_private;

              if ( mp->mp_cb ) {
                     monitor_callback_t   *cb;

                     for ( cb = mp->mp_cb; cb != NULL; ) {
                            monitor_callback_t   *next = cb->mc_next;

                            if ( cb->mc_free ) {
                                   (void)cb->mc_free( mc->mc_e, &cb->mc_private );
                            }
                            ch_free( mp->mp_cb );

                            cb = next;
                     }
              }

              ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );

              ch_free( mp );
              mc->mc_e->e_private = NULL;
              entry_free( mc->mc_e );
       }

       ch_free( mc );
}

Here is the call graph for this function:

Here is the caller graph for this function: