Implement reqOld support

This commit is contained in:
Howard Chu 2006-04-27 00:01:20 +00:00
parent 95f90b5759
commit 4f1e154c12

View 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;
}