]> git.sur5r.net Git - openldap/commitdiff
Implement reqOld support
authorHoward Chu <hyc@openldap.org>
Thu, 27 Apr 2006 00:01:20 +0000 (00:01 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 27 Apr 2006 00:01:20 +0000 (00:01 +0000)
servers/slapd/overlays/accesslog.c

index 3600b3591d82de1aa482da0733d7b2616a7e440f..f134ed1d1f3a4013d166ecab43e8275209ae7642 100644 (file)
@@ -57,6 +57,8 @@ typedef struct log_info {
        int li_age;
        int li_cycle;
        struct re_s *li_task;
+       Filter *li_filter;
+       Entry *li_old;
        int li_success;
        ldap_pvt_thread_mutex_t li_op_mutex;
        ldap_pvt_thread_mutex_t li_log_mutex;
@@ -68,7 +70,8 @@ enum {
        LOG_DB = 1,
        LOG_OPS,
        LOG_PURGE,
-       LOG_SUCCESS
+       LOG_SUCCESS,
+       LOG_FILTER
 };
 
 static ConfigTable log_cfats[] = {
@@ -90,6 +93,10 @@ static ConfigTable log_cfats[] = {
                log_cf_gen, "( OLcfgOvAt:4.4 NAME 'olcAccessLogSuccess' "
                        "DESC 'Log successful ops only' "
                        "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
+       { "logoldfilter", NULL, 2, 2, 0, ARG_MAGIC|LOG_FILTER,
+               log_cf_gen, "( OLcfgOvAt:4.5 NAME 'olcAccessLogOldFilter' "
+                       "DESC 'Log old values when modifying entries matching the filter' "
+                       "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
        { NULL }
 };
 
@@ -99,7 +106,8 @@ static ConfigOCs log_cfocs[] = {
                "DESC 'Access log configuration' "
                "SUP olcOverlayConfig "
                "MUST olcAccessLogDB "
-               "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess ) )",
+               "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess $ "
+                       "olcAccessLogOldFilter ) )",
                        Cft_Overlay, log_cfats },
        { NULL }
 };
@@ -605,6 +613,14 @@ log_cf_gen(ConfigArgs *c)
                        else
                                rc = 1;
                        break;
+               case LOG_FILTER:
+                       if ( li->li_filter ) {
+                               filter2bv( li->li_filter, &agebv );
+                               value_add_one( &c->rvalue_vals, &agebv );
+                       }
+                       else
+                               rc = 1;
+                       break;
                }
                break;
        case LDAP_MOD_DELETE:
@@ -635,6 +651,12 @@ log_cf_gen(ConfigArgs *c)
                case LOG_SUCCESS:
                        li->li_success = 0;
                        break;
+               case LOG_FILTER:
+                       if ( li->li_filter ) {
+                               filter_free( li->li_filter );
+                               li->li_filter = NULL;
+                       }
+                       break;
                }
                break;
        default:
@@ -680,6 +702,12 @@ log_cf_gen(ConfigArgs *c)
                case LOG_SUCCESS:
                        li->li_success = c->value_int;
                        break;
+               case LOG_FILTER:
+                       li->li_filter = str2filter( c->argv[1] );
+                       if ( !li->li_filter ) {
+                               sprintf( c->msg, "bad filter!" );
+                               rc = 1;
+                       }
                }
                break;
        }
@@ -782,6 +810,24 @@ static struct berval derefs[] = {
 
 static struct berval simple = BER_BVC("SIMPLE");
 
+static void accesslog_val2val(AttributeDescription *ad, struct berval *val,
+       char c_op, struct berval *dst) {
+       char *ptr;
+
+       dst->bv_len = ad->ad_cname.bv_len + val->bv_len + 2;
+       if ( c_op ) dst->bv_len++;
+
+       dst->bv_val = ch_malloc( dst->bv_len+1 );
+
+       ptr = lutil_strcopy( dst->bv_val, ad->ad_cname.bv_val );
+       *ptr++ = ':';
+       if ( c_op )
+               *ptr++ = c_op;
+       *ptr++ = ' ';
+       AC_MEMCPY( ptr, val->bv_val, val->bv_len );
+       dst->bv_val[dst->bv_len] = '\0';
+}
+
 static int accesslog_response(Operation *op, SlapReply *rs) {
        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
        log_info *li = on->on_bi.bi_private;
@@ -791,7 +837,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
        int i;
        int logop;
        slap_verbmasks *lo;
-       Entry *e;
+       Entry *e, *old = NULL;
        char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE+8];
        struct berval bv;
        char *ptr;
@@ -821,6 +867,8 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
 
        if ( lo->mask & LOG_OP_WRITES ) {
                ldap_pvt_thread_mutex_lock( &li->li_log_mutex );
+               old = li->li_old;
+               li->li_old = NULL;
                ldap_pvt_thread_mutex_unlock( &li->li_op_mutex );
        }
 
@@ -844,9 +892,22 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
 
        switch( logop ) {
        case LOG_EN_ADD:
+       case LOG_EN_DELETE: {
+               char c_op;
+               Entry *e2;
+
+               if ( logop == LOG_EN_ADD ) {
+                       e2 = op->ora_e;
+                       c_op = '+';
+               } else {
+                       if ( !old )
+                               break;
+                       e2 = old;
+                       c_op = 0;
+               }
                /* count all the vals */
                i = 0;
-               for ( a=op->ora_e->e_attrs; a; a=a->a_next ) {
+               for ( a=e2->e_attrs; a; a=a->a_next ) {
                        if ( a->a_vals ) {
                                for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
                                        i++;
@@ -855,32 +916,21 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                }
                vals = ch_malloc( (i+1) * sizeof( struct berval ));
                i = 0;
-               for ( a=op->ora_e->e_attrs; a; a=a->a_next ) {
+               for ( a=e2->e_attrs; a; a=a->a_next ) {
                        if ( a->a_vals ) {
                                for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
-                                       vals[i].bv_len = a->a_desc->ad_cname.bv_len + b->bv_len +3;
-                                       vals[i].bv_val = ch_malloc( vals[i].bv_len+1 );
-                                       ptr = lutil_strcopy( vals[i].bv_val,
-                                               a->a_desc->ad_cname.bv_val );
-                                       *ptr++ = ':';
-                                       *ptr++ = '+';
-                                       *ptr++ = ' ';
-                                       AC_MEMCPY( ptr, b->bv_val, b->bv_len );
-                                       vals[i].bv_val[vals[i].bv_len] = '\0';
+                                       accesslog_val2val( a->a_desc, b, c_op, &vals[i] );
                                }
                        }
                }
                vals[i].bv_val = NULL;
                vals[i].bv_len = 0;
-               a = attr_alloc( ad_reqMod );
+               a = attr_alloc( logop == LOG_EN_ADD ? ad_reqMod : ad_reqOld );
                a->a_vals = vals;
                a->a_nvals = vals;
                last_attr->a_next = a;
                break;
-
-       case LOG_EN_DELETE:
-               /* needs nothing else */
-               break;
+       }
 
        case LOG_EN_MODIFY:
                /* count all the mods */
@@ -896,15 +946,24 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                }
                vals = ch_malloc( (i+1) * sizeof( struct berval ));
                i = 0;
+
+               /* Zero flags on old entry */
+               if ( old ) {
+                       for ( a=old->e_attrs; a; a=a->a_next )
+                               a->a_flags = 0;
+               }
+
                for ( m=op->orm_modlist; m; m=m->sml_next ) {
+                       /* Mark this attribute as modified */
+                       if ( old ) {
+                               a = attr_find( old->e_attrs, m->sml_desc );
+                               if ( a )
+                                       a->a_flags = 1;
+                       }
                        if ( m->sml_values ) {
                                for (b=m->sml_values; !BER_BVISNULL( b ); b++,i++) {
                                        char c_op;
-                                       vals[i].bv_len = m->sml_desc->ad_cname.bv_len + b->bv_len +3;
-                                       vals[i].bv_val = ch_malloc( vals[i].bv_len+1 );
-                                       ptr = lutil_strcopy( vals[i].bv_val,
-                                               m->sml_desc->ad_cname.bv_val );
-                                       *ptr++ = ':';
+
                                        switch( m->sml_op ) {
                                        case LDAP_MOD_ADD: c_op = '+'; break;
                                        case LDAP_MOD_DELETE:   c_op = '-'; break;
@@ -917,10 +976,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                                         */
                                        default: c_op = '?'; break;
                                        }
-                                       *ptr++ = c_op;
-                                       *ptr++ = ' ';
-                                       AC_MEMCPY( ptr, b->bv_val, b->bv_len );
-                                       vals[i].bv_val[vals[i].bv_len] = '\0';
+                                       accesslog_val2val( m->sml_desc, b, c_op, &vals[i] );
                                }
                        } else if ( m->sml_op == LDAP_MOD_DELETE ) {
                                vals[i].bv_len = m->sml_desc->ad_cname.bv_len + 2;
@@ -939,6 +995,34 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                a->a_vals = vals;
                a->a_nvals = vals;
                last_attr->a_next = a;
+
+               if ( old ) {
+                       last_attr = a;
+                       /* count all the vals */
+                       i = 0;
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               if ( a->a_vals && a->a_flags ) {
+                                       for (b=a->a_vals; !BER_BVISNULL( b ); b++) {
+                                       i++;
+                                       }
+                               }
+                       }
+                       vals = ch_malloc( (i+1) * sizeof( struct berval ));
+                       i = 0;
+                       for ( a=old->e_attrs; a; a=a->a_next ) {
+                               if ( a->a_vals && a->a_flags ) {
+                                       for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) {
+                                               accesslog_val2val( a->a_desc, b, 0, &vals[i] );
+                                       }
+                               }
+                       }
+                       vals[i].bv_val = NULL;
+                       vals[i].bv_len = 0;
+                       a = attr_alloc( ad_reqOld );
+                       a->a_vals = vals;
+                       a->a_nvals = vals;
+                       last_attr->a_next = a;
+               }
                break;
 
        case LOG_EN_MODRDN:
@@ -1043,6 +1127,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
        entry_free( e );
 
 done:
+       if ( old ) entry_free( old );
        ldap_pvt_thread_mutex_unlock( &li->li_log_mutex );
        return SLAP_CB_CONTINUE;
 }
@@ -1099,6 +1184,20 @@ accesslog_op_mod( Operation *op, SlapReply *rs )
                 * overlays like refint to keep working.
                 */
                ldap_pvt_thread_mutex_lock( &li->li_op_mutex );
+               if ( li->li_filter && ( op->o_tag == LDAP_REQ_DELETE ||
+                       op->o_tag == LDAP_REQ_MODIFY )) {
+                       int rc;
+                       Entry *e;
+
+                       op->o_bd->bd_info = on->on_info->oi_orig;
+                       rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e );
+                       if ( e ) {
+                               if ( test_filter( op, e, li->li_filter ) == LDAP_COMPARE_TRUE )
+                                       li->li_old = entry_dup( e );
+                               be_entry_release_rw( op, e, 0 );
+                       }
+                       op->o_bd->bd_info = (BackendInfo *)on;
+               }
        }
        return SLAP_CB_CONTINUE;
 }