]> git.sur5r.net Git - openldap/commitdiff
Here is slapo-nops, used to remove idempotent operations (i.e.: replacing
authorEmmanuel Dreyfus <manu@openldap.org>
Mon, 19 May 2008 22:44:08 +0000 (22:44 +0000)
committerEmmanuel Dreyfus <manu@openldap.org>
Mon, 19 May 2008 22:44:08 +0000 (22:44 +0000)
an attribute values by the exact same values)

contrib/slapd-modules/nops/Makefile [new file with mode: 0644]
contrib/slapd-modules/nops/nops.c [new file with mode: 0644]
contrib/slapd-modules/nops/slapo-nops.5 [new file with mode: 0644]

diff --git a/contrib/slapd-modules/nops/Makefile b/contrib/slapd-modules/nops/Makefile
new file mode 100644 (file)
index 0000000..827a5ba
--- /dev/null
@@ -0,0 +1,9 @@
+CPPFLAGS+=-I../../../include -I../../../servers/slapd
+
+all: nops.so
+
+nops.so: nops.c
+       $(CC) -shared $(CPPFLAGS) -Wall -o $@ $?
+
+clean:
+       rm nops.so
diff --git a/contrib/slapd-modules/nops/nops.c b/contrib/slapd-modules/nops/nops.c
new file mode 100644 (file)
index 0000000..0914cf4
--- /dev/null
@@ -0,0 +1,168 @@
+/* $OpenLDAP$ */
+/* nops.c - Overlay to filter idempotent operations */
+/* 
+ * Copyright 2008 Emmanuel Dreyfus
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+#include "portable.h"
+
+#ifdef SLAPD_OVER_NOPS
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "lutil.h"
+#include "slap.h"
+#include "config.h"
+
+static ConfigDriver nops_cf_gen;
+
+static int nops_cf_gen( ConfigArgs *c ) { return 0; }
+
+static void
+nops_rm_mod( Modifications **mods, Modifications *mod ) {
+       Modifications *next, *m;
+
+       next = mod->sml_next;
+       if (*mods == mod) {
+               *mods = next;
+       } else {
+               Modifications *m;
+
+               for (m = *mods; m; m = m->sml_next) {
+                       if (m->sml_next == mod) {
+                               m->sml_next = next;
+                               break;
+                       }
+               }
+       }
+
+       for (m = *mods; m; m = m->sml_next)
+       mod->sml_next = NULL;
+       slap_mods_free(mod, 1);
+
+       return;
+}
+
+static int
+nops_modify( Operation *op, SlapReply *rs )
+{
+       slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+       Backend *be = op->o_bd;
+       Entry *target_entry = NULL;
+       Modifications *m;
+       int rc;
+       
+       if ((m = op->orm_modlist) == NULL) {
+               op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+               send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
+                               "nops() got null orm_modlist");
+               return(rs->sr_err);
+       }
+
+       op->o_bd = on->on_info->oi_origdb;
+       rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0,  &target_entry);
+       op->o_bd = be;
+
+       if (rc != 0 || target_entry == NULL)
+               return 0;
+        
+       /* 
+        * For each attribute modification, check if the 
+        * modification and the old entry are the same.
+        */
+       while (m) {
+               int i, j;
+               int found;
+               Attribute *a;
+               BerVarray bm;
+               BerVarray bt;
+               Modifications *mc;
+
+               mc = m;
+               m = m->sml_next;
+
+               /* Check only replace sub-operations */
+               if ((mc->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE)
+                       continue;
+
+               /* If there is no values, skip */
+               if (((bm = mc->sml_values ) == NULL ) || (bm[0].bv_val == NULL))
+                       continue;
+
+               /* If the attribute does not exist in old entry, skip */
+               if ((a = attr_find(target_entry->e_attrs, mc->sml_desc)) == NULL)
+                       continue;
+               if ((bt = a->a_vals) == NULL)
+                       continue;
+
+               /* For each value replaced, do we find it in old entry? */
+               found = 0;
+               for (i = 0; bm[i].bv_val; i++) {
+                       for (j = 0; bt[j].bv_val; j++) {
+                               if (bm[i].bv_len != bt[j].bv_len)
+                                       continue;
+                               if (memcmp(bm[i].bv_val, bt[j].bv_val, bt[j].bv_len) != 0)
+                                       continue;
+
+                               found++;
+                               break;
+                       }
+               }
+
+               /* Did we find as many values as we had in old entry? */
+               if (i != a->a_numvals || found != a->a_numvals)
+                       continue;
+
+               /* This is a nop, remove it */
+               Debug(LDAP_DEBUG_TRACE, "removing nop on %s%s%s",
+                       a->a_desc->ad_cname.bv_val, "", "");
+
+               nops_rm_mod(&op->orm_modlist, mc);
+       }
+       if (target_entry) {
+               op->o_bd = on->on_info->oi_origdb;
+               be_entry_release_r(op, target_entry);
+               op->o_bd = be;
+       }
+
+       if ((m = op->orm_modlist) == NULL) {
+               op->o_bd->bd_info = (BackendInfo *)(on->on_info);
+               send_ldap_error(op, rs, LDAP_SUCCESS, "");
+               return(rs->sr_err);
+               return (rs->sr_err);
+       }
+
+       return SLAP_CB_CONTINUE;
+}
+
+static slap_overinst nops_ovl;
+
+#if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC
+static
+#endif
+int
+nops_initialize( void ) {
+       nops_ovl.on_bi.bi_type = "nops";
+       nops_ovl.on_bi.bi_op_modify = nops_modify;
+       return overlay_register( &nops_ovl );
+}
+
+#if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC
+int init_module(int argc, char *argv[]) {
+       return nops_initialize();
+}
+#endif
+
+#endif /* defined(SLAPD_OVER_NOPS) */
+
diff --git a/contrib/slapd-modules/nops/slapo-nops.5 b/contrib/slapd-modules/nops/slapo-nops.5
new file mode 100644 (file)
index 0000000..ac8f19d
--- /dev/null
@@ -0,0 +1,32 @@
+.TH SLAPO-NOPS 5 "RELEASEDATE" "OpenLDAP LDVERSION"
+.\" Copyright 2008 Emmanuel Dreyfus
+.\" Copying restrictions apply.  See COPYRIGHT/LICENSE.
+.\" $OpenLDAP$
+.SH NAME
+slapo-nops \- Remove Null Operations Overlay to slapd
+.SH SYNOPSIS
+ETCDIR/slapd.conf
+.SH DESCRIPTION
+Some broken client tend to implement modifications as replace operations
+where all attributes are replaced, most of the time by the same values
+they had before. This can cause undesirable load on logs, ACL evaluation, 
+or replication trafic.
+
+This overlay detects idempotent replace operations and filter them out.
+.SH CONFIGURATION
+This overlay had no specific configuration.
+.SH EXAMPLES
+.LP
+.RS
+.nf
+overlay nops
+.RE
+.SH FILES
+.TP
+ETCDIR/slapd.conf
+default slapd configuration file
+.SH SEE ALSO
+.BR slapd.conf (5).
+.SH ACKNOWLEDGEMENTS
+This module was written in 2008 by Emmanuel Dreyfus.
+.so ../Project