summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am18
-rw-r--r--[-rwxr-xr-x]Makefile.in105
-rw-r--r--[-rwxr-xr-x]aclocal.m40
-rw-r--r--[-rwxr-xr-x]config.h.in0
-rw-r--r--ldap/admin/src/scripts/template-usn-tombstone-cleanup.pl.in180
-rw-r--r--ldap/ldif/template-dse.ldif.in19
-rw-r--r--ldap/servers/plugins/usn/usn.c570
-rw-r--r--ldap/servers/plugins/usn/usn.h57
-rw-r--r--ldap/servers/plugins/usn/usn_cleanup.c326
-rw-r--r--ldap/servers/slapd/back-ldbm/back-ldbm.h1
-rw-r--r--ldap/servers/slapd/back-ldbm/import.c3
-rw-r--r--ldap/servers/slapd/back-ldbm/init.c4
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_add.c3
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_delete.c228
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_instance_config.c6
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_modify.c1
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_usn.c196
-rw-r--r--ldap/servers/slapd/back-ldbm/misc.c8
-rw-r--r--ldap/servers/slapd/back-ldbm/proto-back-ldbm.h9
-rw-r--r--ldap/servers/slapd/back-ldbm/start.c3
-rw-r--r--ldap/servers/slapd/backend.c2
-rw-r--r--ldap/servers/slapd/main.c2
-rw-r--r--ldap/servers/slapd/pblock.c8
-rw-r--r--ldap/servers/slapd/plugin.c68
-rw-r--r--ldap/servers/slapd/slap.h3
-rw-r--r--ldap/servers/slapd/slapi-plugin.h6
-rw-r--r--ldap/servers/slapd/slapi-private.h3
-rw-r--r--[-rwxr-xr-x]ltmain.sh0
28 files changed, 1748 insertions, 81 deletions
diff --git a/Makefile.am b/Makefile.am
index 05cb3566..5ce6ccbe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -157,9 +157,10 @@ serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \
libhttp-client-plugin.la liblinkedattrs-plugin.la \
libmemberof-plugin.la libpassthru-plugin.la libpwdstorage-plugin.la \
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
- libroles-plugin.la libschemareload-plugin.la libstatechange-plugin.la \
- libsyntax-plugin.la libviews-plugin.la $(LIBPAM_PASSTHRU_PLUGIN) \
- $(LIBDNA_PLUGIN) $(LIBBITWISE_PLUGIN) $(LIBPRESENCE_PLUGIN)
+ libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
+ libviews-plugin.la libschemareload-plugin.la libusn-plugin.la \
+ $(LIBPAM_PASSTHRU_PLUGIN) $(LIBDNA_PLUGIN) \
+ $(LIBBITWISE_PLUGIN) $(LIBPRESENCE_PLUGIN)
nodist_property_DATA = ns-slapd.properties
@@ -314,6 +315,7 @@ task_SCRIPTS = ldap/admin/src/scripts/template-bak2db \
ldap/admin/src/scripts/template-ns-newpwpolicy.pl \
ldap/admin/src/scripts/template-schema-reload.pl \
ldap/admin/src/scripts/template-syntax-validate.pl \
+ ldap/admin/src/scripts/template-usn-tombstone-cleanup.pl \
ldap/admin/src/scripts/template-verify-db.pl \
ldap/admin/src/scripts/template-dbverify
@@ -617,6 +619,7 @@ libback_ldbm_la_SOURCES = ldap/servers/slapd/back-ldbm/ancestorid.c \
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c \
ldap/servers/slapd/back-ldbm/ldbm_search.c \
ldap/servers/slapd/back-ldbm/ldbm_unbind.c \
+ ldap/servers/slapd/back-ldbm/ldbm_usn.c \
ldap/servers/slapd/back-ldbm/ldif2ldbm.c \
ldap/servers/slapd/back-ldbm/dbverify.c \
ldap/servers/slapd/back-ldbm/matchrule.c \
@@ -968,6 +971,15 @@ libsyntax_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
libsyntax_plugin_la_LDFLAGS = -avoid-version
#------------------------
+# libusn-plugin
+#------------------------
+libusn_plugin_la_SOURCES = ldap/servers/plugins/usn/usn.c \
+ ldap/servers/plugins/usn/usn_cleanup.c
+
+libusn_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+libusn_plugin_la_LDFLAGS = -avoid-version
+
+#------------------------
# libviews-plugin
#------------------------
libviews_plugin_la_SOURCES = ldap/servers/plugins/views/views.c
diff --git a/Makefile.in b/Makefile.in
index 9f3208af..865a7dbf 100755..100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -173,6 +173,7 @@ am_libback_ldbm_la_OBJECTS = \
ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_modrdn.lo \
ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_search.lo \
ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_unbind.lo \
+ ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_usn.lo \
ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldif2ldbm.lo \
ldap/servers/slapd/back-ldbm/libback_ldbm_la-dbverify.lo \
ldap/servers/slapd/back-ldbm/libback_ldbm_la-matchrule.lo \
@@ -688,6 +689,14 @@ libsyntax_plugin_la_OBJECTS = $(am_libsyntax_plugin_la_OBJECTS)
libsyntax_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libsyntax_plugin_la_LDFLAGS) $(LDFLAGS) -o $@
+libusn_plugin_la_LIBADD =
+am_libusn_plugin_la_OBJECTS = \
+ ldap/servers/plugins/usn/libusn_plugin_la-usn.lo \
+ ldap/servers/plugins/usn/libusn_plugin_la-usn_cleanup.lo
+libusn_plugin_la_OBJECTS = $(am_libusn_plugin_la_OBJECTS)
+libusn_plugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libusn_plugin_la_LDFLAGS) $(LDFLAGS) -o $@
libviews_plugin_la_LIBADD =
am_libviews_plugin_la_OBJECTS = \
ldap/servers/plugins/views/libviews_plugin_la-views.lo
@@ -899,10 +908,11 @@ SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libretrocl_plugin_la_SOURCES) $(libroles_plugin_la_SOURCES) \
$(libschemareload_plugin_la_SOURCES) $(libslapd_la_SOURCES) \
$(libstatechange_plugin_la_SOURCES) \
- $(libsyntax_plugin_la_SOURCES) $(libviews_plugin_la_SOURCES) \
- $(dbscan_bin_SOURCES) $(dsktune_bin_SOURCES) \
- $(infadd_bin_SOURCES) $(ldap_agent_bin_SOURCES) \
- $(ldclt_bin_SOURCES) $(ldif_bin_SOURCES) $(makstrdb_SOURCES) \
+ $(libsyntax_plugin_la_SOURCES) $(libusn_plugin_la_SOURCES) \
+ $(libviews_plugin_la_SOURCES) $(dbscan_bin_SOURCES) \
+ $(dsktune_bin_SOURCES) $(infadd_bin_SOURCES) \
+ $(ldap_agent_bin_SOURCES) $(ldclt_bin_SOURCES) \
+ $(ldif_bin_SOURCES) $(makstrdb_SOURCES) \
$(migratecred_bin_SOURCES) $(mmldif_bin_SOURCES) \
$(ns_slapd_SOURCES) $(pwdhash_bin_SOURCES) \
$(rsearch_bin_SOURCES)
@@ -927,13 +937,14 @@ DIST_SOURCES = $(libavl_a_SOURCES) $(libldaputil_a_SOURCES) \
$(libschemareload_plugin_la_SOURCES) \
$(am__libslapd_la_SOURCES_DIST) \
$(libstatechange_plugin_la_SOURCES) \
- $(libsyntax_plugin_la_SOURCES) $(libviews_plugin_la_SOURCES) \
- $(dbscan_bin_SOURCES) $(dsktune_bin_SOURCES) \
- $(infadd_bin_SOURCES) $(ldap_agent_bin_SOURCES) \
- $(am__ldclt_bin_SOURCES_DIST) $(ldif_bin_SOURCES) \
- $(makstrdb_SOURCES) $(migratecred_bin_SOURCES) \
- $(mmldif_bin_SOURCES) $(am__ns_slapd_SOURCES_DIST) \
- $(pwdhash_bin_SOURCES) $(rsearch_bin_SOURCES)
+ $(libsyntax_plugin_la_SOURCES) $(libusn_plugin_la_SOURCES) \
+ $(libviews_plugin_la_SOURCES) $(dbscan_bin_SOURCES) \
+ $(dsktune_bin_SOURCES) $(infadd_bin_SOURCES) \
+ $(ldap_agent_bin_SOURCES) $(am__ldclt_bin_SOURCES_DIST) \
+ $(ldif_bin_SOURCES) $(makstrdb_SOURCES) \
+ $(migratecred_bin_SOURCES) $(mmldif_bin_SOURCES) \
+ $(am__ns_slapd_SOURCES_DIST) $(pwdhash_bin_SOURCES) \
+ $(rsearch_bin_SOURCES)
man1dir = $(mandir)/man1
man8dir = $(mandir)/man8
NROFF = nroff
@@ -1252,9 +1263,10 @@ serverplugin_LTLIBRARIES = libacl-plugin.la libattr-unique-plugin.la \
libhttp-client-plugin.la liblinkedattrs-plugin.la \
libmemberof-plugin.la libpassthru-plugin.la libpwdstorage-plugin.la \
libreferint-plugin.la libreplication-plugin.la libretrocl-plugin.la \
- libroles-plugin.la libschemareload-plugin.la libstatechange-plugin.la \
- libsyntax-plugin.la libviews-plugin.la $(LIBPAM_PASSTHRU_PLUGIN) \
- $(LIBDNA_PLUGIN) $(LIBBITWISE_PLUGIN) $(LIBPRESENCE_PLUGIN)
+ libroles-plugin.la libstatechange-plugin.la libsyntax-plugin.la \
+ libviews-plugin.la libschemareload-plugin.la libusn-plugin.la \
+ $(LIBPAM_PASSTHRU_PLUGIN) $(LIBDNA_PLUGIN) \
+ $(LIBBITWISE_PLUGIN) $(LIBPRESENCE_PLUGIN)
nodist_property_DATA = ns-slapd.properties
noinst_LIBRARIES = libavl.a libldaputil.a
@@ -1408,6 +1420,7 @@ task_SCRIPTS = ldap/admin/src/scripts/template-bak2db \
ldap/admin/src/scripts/template-ns-newpwpolicy.pl \
ldap/admin/src/scripts/template-schema-reload.pl \
ldap/admin/src/scripts/template-syntax-validate.pl \
+ ldap/admin/src/scripts/template-usn-tombstone-cleanup.pl \
ldap/admin/src/scripts/template-verify-db.pl \
ldap/admin/src/scripts/template-dbverify
@@ -1657,6 +1670,7 @@ libback_ldbm_la_SOURCES = ldap/servers/slapd/back-ldbm/ancestorid.c \
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c \
ldap/servers/slapd/back-ldbm/ldbm_search.c \
ldap/servers/slapd/back-ldbm/ldbm_unbind.c \
+ ldap/servers/slapd/back-ldbm/ldbm_usn.c \
ldap/servers/slapd/back-ldbm/ldif2ldbm.c \
ldap/servers/slapd/back-ldbm/dbverify.c \
ldap/servers/slapd/back-ldbm/matchrule.c \
@@ -2001,6 +2015,15 @@ libsyntax_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
libsyntax_plugin_la_LDFLAGS = -avoid-version
#------------------------
+# libusn-plugin
+#------------------------
+libusn_plugin_la_SOURCES = ldap/servers/plugins/usn/usn.c \
+ ldap/servers/plugins/usn/usn_cleanup.c
+
+libusn_plugin_la_CPPFLAGS = $(PLUGIN_CPPFLAGS)
+libusn_plugin_la_LDFLAGS = -avoid-version
+
+#------------------------
# libviews-plugin
#------------------------
libviews_plugin_la_SOURCES = ldap/servers/plugins/views/views.c
@@ -2626,6 +2649,9 @@ ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_search.lo: \
ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_unbind.lo: \
ldap/servers/slapd/back-ldbm/$(am__dirstamp) \
ldap/servers/slapd/back-ldbm/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_usn.lo: \
+ ldap/servers/slapd/back-ldbm/$(am__dirstamp) \
+ ldap/servers/slapd/back-ldbm/$(DEPDIR)/$(am__dirstamp)
ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldif2ldbm.lo: \
ldap/servers/slapd/back-ldbm/$(am__dirstamp) \
ldap/servers/slapd/back-ldbm/$(DEPDIR)/$(am__dirstamp)
@@ -3747,6 +3773,20 @@ ldap/servers/plugins/syntaxes/libsyntax_plugin_la-value.lo: \
ldap/servers/plugins/syntaxes/$(DEPDIR)/$(am__dirstamp)
libsyntax-plugin.la: $(libsyntax_plugin_la_OBJECTS) $(libsyntax_plugin_la_DEPENDENCIES)
$(libsyntax_plugin_la_LINK) -rpath $(serverplugindir) $(libsyntax_plugin_la_OBJECTS) $(libsyntax_plugin_la_LIBADD) $(LIBS)
+ldap/servers/plugins/usn/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/usn
+ @: > ldap/servers/plugins/usn/$(am__dirstamp)
+ldap/servers/plugins/usn/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) ldap/servers/plugins/usn/$(DEPDIR)
+ @: > ldap/servers/plugins/usn/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/usn/libusn_plugin_la-usn.lo: \
+ ldap/servers/plugins/usn/$(am__dirstamp) \
+ ldap/servers/plugins/usn/$(DEPDIR)/$(am__dirstamp)
+ldap/servers/plugins/usn/libusn_plugin_la-usn_cleanup.lo: \
+ ldap/servers/plugins/usn/$(am__dirstamp) \
+ ldap/servers/plugins/usn/$(DEPDIR)/$(am__dirstamp)
+libusn-plugin.la: $(libusn_plugin_la_OBJECTS) $(libusn_plugin_la_DEPENDENCIES)
+ $(libusn_plugin_la_LINK) -rpath $(serverplugindir) $(libusn_plugin_la_OBJECTS) $(libusn_plugin_la_LIBADD) $(LIBS)
ldap/servers/plugins/views/$(am__dirstamp):
@$(MKDIR_P) ldap/servers/plugins/views
@: > ldap/servers/plugins/views/$(am__dirstamp)
@@ -4484,6 +4524,10 @@ mostlyclean-compile:
-rm -f ldap/servers/plugins/uiduniq/libattr_unique_plugin_la-7bit.lo
-rm -f ldap/servers/plugins/uiduniq/libattr_unique_plugin_la-uid.$(OBJEXT)
-rm -f ldap/servers/plugins/uiduniq/libattr_unique_plugin_la-uid.lo
+ -rm -f ldap/servers/plugins/usn/libusn_plugin_la-usn.$(OBJEXT)
+ -rm -f ldap/servers/plugins/usn/libusn_plugin_la-usn.lo
+ -rm -f ldap/servers/plugins/usn/libusn_plugin_la-usn_cleanup.$(OBJEXT)
+ -rm -f ldap/servers/plugins/usn/libusn_plugin_la-usn_cleanup.lo
-rm -f ldap/servers/plugins/views/libviews_plugin_la-views.$(OBJEXT)
-rm -f ldap/servers/plugins/views/libviews_plugin_la-views.lo
-rm -f ldap/servers/slapd/back-ldbm/libback_ldbm_la-ancestorid.$(OBJEXT)
@@ -4572,6 +4616,8 @@ mostlyclean-compile:
-rm -f ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_search.lo
-rm -f ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_unbind.$(OBJEXT)
-rm -f ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_unbind.lo
+ -rm -f ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_usn.$(OBJEXT)
+ -rm -f ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_usn.lo
-rm -f ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldif2ldbm.$(OBJEXT)
-rm -f ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldif2ldbm.lo
-rm -f ldap/servers/slapd/back-ldbm/libback_ldbm_la-matchrule.$(OBJEXT)
@@ -5144,6 +5190,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/syntaxes/$(DEPDIR)/libsyntax_plugin_la-value.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/uiduniq/$(DEPDIR)/libattr_unique_plugin_la-7bit.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/uiduniq/$(DEPDIR)/libattr_unique_plugin_la-uid.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/usn/$(DEPDIR)/libusn_plugin_la-usn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/usn/$(DEPDIR)/libusn_plugin_la-usn_cleanup.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/plugins/views/$(DEPDIR)/libviews_plugin_la-views.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/slapd/$(DEPDIR)/ldap_agent_bin-agtmmap.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/slapd/$(DEPDIR)/libslapd_la-add.Plo@am__quote@
@@ -5316,6 +5364,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldbm_modrdn.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldbm_search.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldbm_unbind.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldbm_usn.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldif2ldbm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-matchrule.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-misc.Plo@am__quote@
@@ -5994,6 +6043,13 @@ ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_unbind.lo: ldap/servers/slapd/
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libback_ldbm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_unbind.lo `test -f 'ldap/servers/slapd/back-ldbm/ldbm_unbind.c' || echo '$(srcdir)/'`ldap/servers/slapd/back-ldbm/ldbm_unbind.c
+ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_usn.lo: ldap/servers/slapd/back-ldbm/ldbm_usn.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libback_ldbm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_usn.lo -MD -MP -MF ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldbm_usn.Tpo -c -o ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_usn.lo `test -f 'ldap/servers/slapd/back-ldbm/ldbm_usn.c' || echo '$(srcdir)/'`ldap/servers/slapd/back-ldbm/ldbm_usn.c
+@am__fastdepCC_TRUE@ mv -f ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldbm_usn.Tpo ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldbm_usn.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/slapd/back-ldbm/ldbm_usn.c' object='ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_usn.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libback_ldbm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldbm_usn.lo `test -f 'ldap/servers/slapd/back-ldbm/ldbm_usn.c' || echo '$(srcdir)/'`ldap/servers/slapd/back-ldbm/ldbm_usn.c
+
ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldif2ldbm.lo: ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libback_ldbm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldif2ldbm.lo -MD -MP -MF ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldif2ldbm.Tpo -c -o ldap/servers/slapd/back-ldbm/libback_ldbm_la-ldif2ldbm.lo `test -f 'ldap/servers/slapd/back-ldbm/ldif2ldbm.c' || echo '$(srcdir)/'`ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@am__fastdepCC_TRUE@ mv -f ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldif2ldbm.Tpo ldap/servers/slapd/back-ldbm/$(DEPDIR)/libback_ldbm_la-ldif2ldbm.Plo
@@ -7912,6 +7968,20 @@ ldap/servers/plugins/syntaxes/libsyntax_plugin_la-value.lo: ldap/servers/plugins
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsyntax_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/syntaxes/libsyntax_plugin_la-value.lo `test -f 'ldap/servers/plugins/syntaxes/value.c' || echo '$(srcdir)/'`ldap/servers/plugins/syntaxes/value.c
+ldap/servers/plugins/usn/libusn_plugin_la-usn.lo: ldap/servers/plugins/usn/usn.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libusn_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/usn/libusn_plugin_la-usn.lo -MD -MP -MF ldap/servers/plugins/usn/$(DEPDIR)/libusn_plugin_la-usn.Tpo -c -o ldap/servers/plugins/usn/libusn_plugin_la-usn.lo `test -f 'ldap/servers/plugins/usn/usn.c' || echo '$(srcdir)/'`ldap/servers/plugins/usn/usn.c
+@am__fastdepCC_TRUE@ mv -f ldap/servers/plugins/usn/$(DEPDIR)/libusn_plugin_la-usn.Tpo ldap/servers/plugins/usn/$(DEPDIR)/libusn_plugin_la-usn.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/plugins/usn/usn.c' object='ldap/servers/plugins/usn/libusn_plugin_la-usn.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libusn_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/usn/libusn_plugin_la-usn.lo `test -f 'ldap/servers/plugins/usn/usn.c' || echo '$(srcdir)/'`ldap/servers/plugins/usn/usn.c
+
+ldap/servers/plugins/usn/libusn_plugin_la-usn_cleanup.lo: ldap/servers/plugins/usn/usn_cleanup.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libusn_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/usn/libusn_plugin_la-usn_cleanup.lo -MD -MP -MF ldap/servers/plugins/usn/$(DEPDIR)/libusn_plugin_la-usn_cleanup.Tpo -c -o ldap/servers/plugins/usn/libusn_plugin_la-usn_cleanup.lo `test -f 'ldap/servers/plugins/usn/usn_cleanup.c' || echo '$(srcdir)/'`ldap/servers/plugins/usn/usn_cleanup.c
+@am__fastdepCC_TRUE@ mv -f ldap/servers/plugins/usn/$(DEPDIR)/libusn_plugin_la-usn_cleanup.Tpo ldap/servers/plugins/usn/$(DEPDIR)/libusn_plugin_la-usn_cleanup.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ldap/servers/plugins/usn/usn_cleanup.c' object='ldap/servers/plugins/usn/libusn_plugin_la-usn_cleanup.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libusn_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ldap/servers/plugins/usn/libusn_plugin_la-usn_cleanup.lo `test -f 'ldap/servers/plugins/usn/usn_cleanup.c' || echo '$(srcdir)/'`ldap/servers/plugins/usn/usn_cleanup.c
+
ldap/servers/plugins/views/libviews_plugin_la-views.lo: ldap/servers/plugins/views/views.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libviews_plugin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ldap/servers/plugins/views/libviews_plugin_la-views.lo -MD -MP -MF ldap/servers/plugins/views/$(DEPDIR)/libviews_plugin_la-views.Tpo -c -o ldap/servers/plugins/views/libviews_plugin_la-views.lo `test -f 'ldap/servers/plugins/views/views.c' || echo '$(srcdir)/'`ldap/servers/plugins/views/views.c
@am__fastdepCC_TRUE@ mv -f ldap/servers/plugins/views/$(DEPDIR)/libviews_plugin_la-views.Tpo ldap/servers/plugins/views/$(DEPDIR)/libviews_plugin_la-views.Plo
@@ -9128,6 +9198,7 @@ clean-libtool:
-rm -rf ldap/servers/plugins/statechange/.libs ldap/servers/plugins/statechange/_libs
-rm -rf ldap/servers/plugins/syntaxes/.libs ldap/servers/plugins/syntaxes/_libs
-rm -rf ldap/servers/plugins/uiduniq/.libs ldap/servers/plugins/uiduniq/_libs
+ -rm -rf ldap/servers/plugins/usn/.libs ldap/servers/plugins/usn/_libs
-rm -rf ldap/servers/plugins/views/.libs ldap/servers/plugins/views/_libs
-rm -rf ldap/servers/slapd/.libs ldap/servers/slapd/_libs
-rm -rf ldap/servers/slapd/back-ldbm/.libs ldap/servers/slapd/back-ldbm/_libs
@@ -9642,6 +9713,8 @@ distclean-generic:
-rm -f ldap/servers/plugins/syntaxes/$(am__dirstamp)
-rm -f ldap/servers/plugins/uiduniq/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/uiduniq/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/usn/$(DEPDIR)/$(am__dirstamp)
+ -rm -f ldap/servers/plugins/usn/$(am__dirstamp)
-rm -f ldap/servers/plugins/views/$(DEPDIR)/$(am__dirstamp)
-rm -f ldap/servers/plugins/views/$(am__dirstamp)
-rm -f ldap/servers/slapd/$(DEPDIR)/$(am__dirstamp)
@@ -9682,7 +9755,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libtool \
distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/shared/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/shared/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
@@ -9724,7 +9797,7 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
- -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/shared/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
+ -rm -rf ldap/libraries/libavl/$(DEPDIR) ldap/servers/plugins/acl/$(DEPDIR) ldap/servers/plugins/bitwise/$(DEPDIR) ldap/servers/plugins/chainingdb/$(DEPDIR) ldap/servers/plugins/collation/$(DEPDIR) ldap/servers/plugins/cos/$(DEPDIR) ldap/servers/plugins/distrib/$(DEPDIR) ldap/servers/plugins/dna/$(DEPDIR) ldap/servers/plugins/http/$(DEPDIR) ldap/servers/plugins/linkedattrs/$(DEPDIR) ldap/servers/plugins/memberof/$(DEPDIR) ldap/servers/plugins/pam_passthru/$(DEPDIR) ldap/servers/plugins/passthru/$(DEPDIR) ldap/servers/plugins/presence/$(DEPDIR) ldap/servers/plugins/pwdstorage/$(DEPDIR) ldap/servers/plugins/referint/$(DEPDIR) ldap/servers/plugins/replication/$(DEPDIR) ldap/servers/plugins/retrocl/$(DEPDIR) ldap/servers/plugins/rever/$(DEPDIR) ldap/servers/plugins/roles/$(DEPDIR) ldap/servers/plugins/schema_reload/$(DEPDIR) ldap/servers/plugins/shared/$(DEPDIR) ldap/servers/plugins/statechange/$(DEPDIR) ldap/servers/plugins/syntaxes/$(DEPDIR) ldap/servers/plugins/uiduniq/$(DEPDIR) ldap/servers/plugins/usn/$(DEPDIR) ldap/servers/plugins/views/$(DEPDIR) ldap/servers/slapd/$(DEPDIR) ldap/servers/slapd/back-ldbm/$(DEPDIR) ldap/servers/slapd/tools/$(DEPDIR) ldap/servers/slapd/tools/ldclt/$(DEPDIR) ldap/servers/slapd/tools/rsearch/$(DEPDIR) ldap/servers/snmp/$(DEPDIR) ldap/systools/$(DEPDIR) lib/base/$(DEPDIR) lib/ldaputil/$(DEPDIR) lib/libaccess/$(DEPDIR) lib/libadmin/$(DEPDIR) lib/libsi18n/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/aclocal.m4 b/aclocal.m4
index 95c2c89f..95c2c89f 100755..100644
--- a/aclocal.m4
+++ b/aclocal.m4
diff --git a/config.h.in b/config.h.in
index 1a266da0..1a266da0 100755..100644
--- a/config.h.in
+++ b/config.h.in
diff --git a/ldap/admin/src/scripts/template-usn-tombstone-cleanup.pl.in b/ldap/admin/src/scripts/template-usn-tombstone-cleanup.pl.in
new file mode 100644
index 00000000..bd8c2575
--- /dev/null
+++ b/ldap/admin/src/scripts/template-usn-tombstone-cleanup.pl.in
@@ -0,0 +1,180 @@
+#{{PERL-EXEC}}
+#
+# BEGIN COPYRIGHT BLOCK
+# This Program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 2 of the License.
+#
+# This Program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA.
+#
+# In addition, as a special exception, Red Hat, Inc. gives You the additional
+# right to link the code of this Program with code not covered under the GNU
+# General Public License ("Non-GPL Code") and to distribute linked combinations
+# including the two, subject to the limitations in this paragraph. Non-GPL Code
+# permitted under this exception must only link to the code of this Program
+# through those well defined interfaces identified in the file named EXCEPTION
+# found in the source code files (the "Approved Interfaces"). The files of
+# Non-GPL Code may instantiate templates or use macros or inline functions from
+# the Approved Interfaces without causing the resulting work to be covered by
+# the GNU General Public License. Only Red Hat, Inc. may make changes or
+# additions to the list of Approved Interfaces. You must obey the GNU General
+# Public License in all respects for all of the Program code and other code used
+# in conjunction with the Program except the Non-GPL Code covered by this
+# exception. If you modify this file, you may extend this exception to your
+# version of the file, but you are not obligated to do so. If you do not wish to
+# provide this exception without modification, you must delete this exception
+# statement from your version and license this file solely under the GPL without
+# exception.
+#
+#
+# Copyright (C) 2009 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+
+sub usage {
+ print(STDERR "Usage: $0 [-v] -D rootdn { -w password | -w - | -j filename } -s suffix | -n backend [ -m maxusn_to_delete ]\n");
+ print(STDERR " Opts: -D rootdn - Directory Manager\n");
+ print(STDERR " : -w password - Directory Manager's password\n");
+ print(STDERR " : -w - - Prompt for Directory Manager's password\n");
+ print(STDERR " : -j filename - Read Directory Manager's password from file\n");
+ print(STDERR " : -s suffix - Suffix where USN tombstone entries are cleaned up\n");
+ print(STDERR " : -n backend - Backend instance in which USN tombstone entries \n");
+ print(STDERR " are cleaned up (alternative to suffix)\n");
+ print(STDERR " : -m maxusn_to_delete - USN tombstone entries are deleted up to \n");
+ print(STDERR " the entry with maxusn_to_delete\n");
+ print(STDERR " : -v - verbose\n");
+}
+
+$rootdn = "";
+$passwd = "";
+$passwdfile = "";
+$args = "";
+$suffix_arg = "";
+$backend_arg = "";
+$maxusn_arg = "";
+$verbose = 0;
+
+$prefix = "{{DS-ROOT}}";
+
+$ENV{'PATH'} = "$prefix@ldapsdk_bindir@:$prefix/usr/bin:@ldapsdk_bindir@:/usr/bin";
+$ENV{'LD_LIBRARY_PATH'} = "$prefix@nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib";
+$ENV{'SHLIB_PATH'} = "$prefix@nss_libdir@:$prefix/usr/lib:@nss_libdir@:/usr/lib";
+
+$i = 0;
+while ($i <= $#ARGV)
+{
+ if ("$ARGV[$i]" eq "-s")
+ {
+ # suffix
+ $i++; $suffix_arg = $ARGV[$i];
+ }
+ elsif ("$ARGV[$i]" eq "-n")
+ {
+ # backend
+ $i++; $backend_arg = $ARGV[$i];
+ }
+ elsif ("$ARGV[$i]" eq "-m")
+ {
+ # max usn
+ $i++; $maxusn_arg = $ARGV[$i];
+ }
+ elsif ("$ARGV[$i]" eq "-D")
+ {
+ # Directory Manager
+ $i++; $rootdn = $ARGV[$i];
+ }
+ elsif ("$ARGV[$i]" eq "-w")
+ {
+ # Directory Manager's password
+ $i++; $passwd = $ARGV[$i];
+ }
+ elsif ("$ARGV[$i]" eq "-j")
+ {
+ # Read Directory Manager's password from a file
+ $i++; $passwdfile = $ARGV[$i];
+ }
+ elsif ("$ARGV[$i]" eq "-v")
+ {
+ # verbose
+ $verbose = 1;
+ }
+ else
+ {
+ &usage; exit(1);
+ }
+ $i++;
+}
+
+if ($passwdfile ne ""){
+# Open file and get the password
+ unless (open (RPASS, $passwdfile)) {
+ die "Error, cannot open password file $passwdfile\n";
+ }
+ $passwd = <RPASS>;
+ chomp($passwd);
+ close(RPASS);
+} elsif ($passwd eq "-"){
+# Read the password from terminal
+ print "Bind Password: ";
+ # Disable console echo
+ system("stty -echo");
+ # read the answer
+ $passwd = <STDIN>;
+ # Enable console echo
+ system("stty echo");
+ print "\n";
+ chop($passwd); # trim trailing newline
+}
+
+if ( $rootdn eq "" || $passwd eq "" )
+{
+ &usage;
+ exit(1);
+}
+
+$vstr = "";
+if ($verbose != 0)
+{
+ $vstr = "-v";
+}
+
+# Use a timestamp as part of the task entry name
+($s, $m, $h, $dy, $mn, $yr, $wdy, $ydy, $r) = localtime(time);
+$mn++; $yr += 1900;
+$taskname = "usn_cleanup_${yr}_${mn}_${dy}_${h}_${m}_${s}";
+
+# Build the task entry to add
+$dn = "dn: cn=$taskname, cn=USN tombstone cleanup task, cn=tasks, cn=config\n";
+$misc = "changetype: add\nobjectclass: top\nobjectclass: extensibleObject\n";
+$cn = "cn: $taskname\n";
+
+if ( $suffix_arg eq "" && $backend_arg eq "" )
+{
+ &usage;
+ exit(1);
+}
+elsif ( $suffix_arg ne "" )
+{
+ $args = "suffix: $suffix_arg\n";
+}
+else
+{
+ $args = "backend: $backend_arg\n";
+}
+
+if ( $maxusn_arg ne "" )
+{
+ $args = $args . "maxusn_to_delete: $maxusn_arg\n";
+}
+
+$entry = "${dn}${misc}${cn}${basedn}${args}";
+open(FOO, "| ldapmodify $vstr -h {{SERVER-NAME}} -p {{SERVER-PORT}} -D \"$rootdn\" -w \"$passwd\" -a" );
+print(FOO "$entry");
+close(FOO);
diff --git a/ldap/ldif/template-dse.ldif.in b/ldap/ldif/template-dse.ldif.in
index d0e29278..c2ac588f 100644
--- a/ldap/ldif/template-dse.ldif.in
+++ b/ldap/ldif/template-dse.ldif.in
@@ -677,6 +677,17 @@ nsslapd-plugintype: preoperation
nsslapd-pluginenabled: off
nsslapd-plugin-depends-on-type: database
+dn: cn=USN,cn=plugins,cn=config
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: USN
+nsslapd-pluginpath: libusn-plugin
+nsslapd-plugininitfunc: usn_init
+nsslapd-plugintype: object
+nsslapd-pluginenabled: off
+nsslapd-plugin-depends-on-type: database
+
dn: cn=ldbm database,cn=plugins,cn=config
objectclass: top
objectclass: nsSlapdPlugin
@@ -724,6 +735,14 @@ cn: entrydn
nssystemindex: true
nsindextype: eq
+dn: cn=entryusn,cn=default indexes, cn=config,cn=ldbm database,cn=plugins,cn=config
+objectclass: top
+objectclass: nsIndex
+cn: entryusn
+nssystemindex: true
+nsindextype: eq
+nsmatchingrule: integerOrderingMatch
+
dn: cn=givenName,cn=default indexes, cn=config,cn=ldbm database,cn=plugins,cn=config
objectclass: top
objectclass: nsIndex
diff --git a/ldap/servers/plugins/usn/usn.c b/ldap/servers/plugins/usn/usn.c
new file mode 100644
index 00000000..2bb389a2
--- /dev/null
+++ b/ldap/servers/plugins/usn/usn.c
@@ -0,0 +1,570 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "usn.h"
+
+static Slapi_PluginDesc pdesc = {
+ "USN", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT,
+ "USN (Update Sequence Number) plugin" };
+
+static CSNGen *_usn_csngen = NULL;
+
+static void *_usn_identity = NULL;
+
+static int usn_preop_init(Slapi_PBlock *pb);
+static int usn_bepreop_init(Slapi_PBlock *pb);
+static int usn_bepostop_init(Slapi_PBlock *pb);
+static int usn_rootdse_init();
+
+static int usn_preop_delete(Slapi_PBlock *pb);
+static int usn_bepreop_add(Slapi_PBlock *pb);
+static int usn_bepreop_delete(Slapi_PBlock *pb);
+static int usn_bepreop_modify(Slapi_PBlock *pb);
+static int usn_bepostop(Slapi_PBlock *pb);
+static int usn_start(Slapi_PBlock *pb);
+static int usn_close(Slapi_PBlock *pb);
+static int usn_get_attr(Slapi_PBlock *pb, const char* type, void *value);
+
+static int usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e,
+ Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
+
+/*
+ * Register USN plugin
+ * Note: USN counter initialization is done in the backend (ldbm_usn_init).
+ */
+int
+usn_init(Slapi_PBlock *pb)
+{
+ int rc = 0;
+ void *identity = NULL;
+ int enabled = 0;
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> usn_init\n");
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_ENABLED, &enabled);
+
+ if (!enabled) {
+ /* not enabled */
+ goto bail;
+ }
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &identity);
+
+ /* slapi_register_plugin always returns SUCCESS (0) */
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
+ SLAPI_PLUGIN_VERSION_01) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
+ (void *)&pdesc) != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "usn_init: failed to register version & description\n");
+ rc = -1;
+ goto bail;
+ }
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
+ (void *)usn_start) != 0 ) {
+ slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
+ (void *)usn_close) != 0 ||
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "usn_init: failed to register close callback & task\n");
+ rc = -1;
+ goto bail;
+ }
+
+ rc = slapi_register_plugin("preoperation", 1 /* Enabled */,
+ "usn_preop_init", usn_preop_init,
+ "USN preoperation plugin", NULL, identity);
+ rc = slapi_register_plugin("bepreoperation", 1 /* Enabled */,
+ "usn_bepreop_init", usn_bepreop_init,
+ "USN bepreoperation plugin", NULL, identity);
+ rc = slapi_register_plugin("bepostoperation", 1 /* Enabled */,
+ "usn_bepostop_init", usn_bepostop_init,
+ "USN bepostoperation plugin", NULL, identity);
+ usn_set_identity(identity);
+bail:
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- usn_init\n");
+ return rc;
+}
+
+static int
+usn_preop_init(Slapi_PBlock *pb)
+{
+ int rc = 0;
+
+ /* set up csn generator for tombstone */
+ _usn_csngen = csngen_new(USN_CSNGEN_ID, NULL);
+ if (NULL == _usn_csngen) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "usn_preop_init: csngen_new failed\n");
+ rc = -1;
+ }
+
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_DELETE_FN,
+ (void *)usn_preop_delete) != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "usn_preop_init: failed to register preop plugin\n");
+ rc = -1;
+ }
+
+ return rc;
+}
+
+static int
+usn_bepreop_init(Slapi_PBlock *pb)
+{
+ int rc = 0;
+
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN,
+ (void *)usn_bepreop_add) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN,
+ (void *)usn_bepreop_delete) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN,
+ (void *)usn_bepreop_modify) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODRDN_FN,
+ (void *)usn_bepreop_modify) != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "usn_bepreop_init: failed to register bepreop plugin\n");
+ rc = -1;
+ }
+
+ return rc;
+}
+
+static int
+usn_bepostop_init(Slapi_PBlock *pb)
+{
+ int rc = 0;
+
+ if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_ADD_FN,
+ (void *)usn_bepostop) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_DELETE_FN,
+ (void *)usn_bepostop) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN,
+ (void *)usn_bepostop) != 0 ||
+ slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN,
+ (void *)usn_bepostop) != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "usn_bepostop_init: failed to register bepostop plugin\n");
+ rc = -1;
+ }
+
+ return rc;
+}
+
+static int
+usn_rootdse_init()
+{
+ int rc = -1;
+
+ if (slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
+ "", LDAP_SCOPE_BASE, "(objectclass=*)",
+ usn_rootdse_search, NULL)) {
+ rc = 0;
+ }
+
+ return rc;
+}
+
+/*
+ * usn_start: usn_rootdse_init -- set rootdse callback to aggregate in rootDSE
+ * usn_cleanup_start -- initialize USN tombstone cleanup task
+ */
+static int
+usn_start(Slapi_PBlock *pb)
+{
+ int rc = 0;
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_start\n");
+
+ rc = usn_rootdse_init();
+ rc |= usn_cleanup_start(pb);
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- usn_start\n");
+
+ return rc;
+}
+
+/*
+ * usn_close: release the csn generator used to convert an entry to tombstone
+ */
+static int
+usn_close(Slapi_PBlock *pb)
+{
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_close\n");
+
+ csngen_free(&_usn_csngen);
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- usn_close\n");
+}
+
+/*
+ * usn_preop_delete -- set params to turn the entry to tombstone
+ */
+static int
+usn_preop_delete(Slapi_PBlock *pb)
+{
+ int rc = 0;
+ CSN *csn = NULL;
+ CSN *orig_csn = NULL;
+ Slapi_Operation *op = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> usn_preop_delete\n");
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ orig_csn = operation_get_csn(op);
+
+ if (NULL == orig_csn) {
+ /*
+ * No other plugins hasn't set csn yet, so let's set USN's csn.
+ * If other plugin overrides csn and replica_attr_handler, that's fine.
+ */
+ rc = csngen_new_csn(_usn_csngen, &csn, PR_FALSE /* notify */);
+ if (CSN_SUCCESS != rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "usn_preop_delete: csngen_new failed (%d)\n", rc);
+ goto bail;
+ }
+ operation_set_csn(op, csn);
+ slapi_operation_set_replica_attr_handler(op, (void *)usn_get_attr);
+ }
+bail:
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- usn_preop_delete\n");
+
+ return rc;
+}
+
+#define KEEP_PREV_USN 1
+
+static void
+_usn_add_next_usn(Slapi_Entry *e, Slapi_Backend *be, int flags)
+{
+ struct berval usn_berval = {0};
+ Slapi_Attr* attr = NULL;
+
+ if (NULL == be->be_usn_counter) {
+ /* USN plugin is not enabled */
+ return;
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> _usn_add_next_usn\n");
+
+ /* add next USN to the entry; "be" contains the usn counter */
+ usn_berval.bv_val = slapi_ch_smprintf("%" NSPRIu64,
+ slapi_counter_get_value(be->be_usn_counter));
+ usn_berval.bv_len = strlen(usn_berval.bv_val);
+ slapi_entry_attr_find(e, SLAPI_ATTR_ENTRYUSN, &attr);
+ if (NULL == attr) { /* ENTRYUSN does not exist; add it */
+ Slapi_Value *usn_value = slapi_value_new_berval(&usn_berval);
+ slapi_entry_add_value(e, SLAPI_ATTR_ENTRYUSN, usn_value);
+ slapi_value_free(&usn_value);
+ } else { /* ENTRYUSN exists; replace it */
+ struct berval *new_bvals[2];
+ struct berval **prev_values = NULL;
+ if (KEEP_PREV_USN == flags) {
+ if (0 == slapi_attr_get_bervals_copy(attr, &prev_values)) {
+ slapi_entry_add_values(e,
+ SLAPI_ATTR_ENTRYUSN_PREV, prev_values);
+ ber_bvecfree(prev_values);
+ }
+ }
+ new_bvals[0] = &usn_berval;
+ new_bvals[1] = NULL;
+ slapi_entry_attr_replace(e, SLAPI_ATTR_ENTRYUSN, new_bvals);
+ }
+ slapi_ch_free_string(&usn_berval.bv_val);
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- _usn_add_next_usn\n");
+
+ return;
+}
+
+static int
+_usn_mod_next_usn(LDAPMod ***mods, Slapi_Backend *be)
+{
+ Slapi_Mods smods = {0};
+ struct berval *bvals[2];
+ struct berval usn_berval = {0};
+ char counter_buf[USN_COUNTER_BUF_LEN];
+
+ if (NULL == be->be_usn_counter) {
+ /* USN plugin is not enabled */
+ return LDAP_UNWILLING_TO_PERFORM;
+ }
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> _usn_mod_next_usn\n");
+
+ /* add next USN to the mods; "be" contains the usn counter */
+ usn_berval.bv_val = counter_buf;
+ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64,
+ slapi_counter_get_value(be->be_usn_counter));
+ usn_berval.bv_len = strlen(usn_berval.bv_val);
+ bvals[0] = &usn_berval;
+ bvals[1] = NULL;
+
+ slapi_mods_init_byref(&smods, *mods);
+ /* bvals is duplicated by ber_bvdup in slapi_mods_add_modbvps */
+ slapi_mods_add_modbvps(&smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
+ SLAPI_ATTR_ENTRYUSN, bvals);
+
+ *mods = slapi_mods_get_ldapmods_byref(&smods);
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- _usn_mod_next_usn\n");
+ return LDAP_SUCCESS;
+}
+
+/*
+ * usn_bepreop_add - add next USN to the entry to be added
+ */
+static int
+usn_bepreop_add(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e = NULL;
+ Slapi_Backend *be = NULL;
+ int rc = LDAP_SUCCESS;
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> usn_bepreop_add\n");
+
+ /* add next USN to the entry; "be" contains the usn counter */
+ slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
+ if (NULL == e) {
+ rc = LDAP_NO_SUCH_OBJECT;
+ goto bail;
+ }
+ slapi_pblock_get(pb, SLAPI_BACKEND, &be);
+ if (NULL == be) {
+ rc = LDAP_PARAM_ERROR;
+ goto bail;
+ }
+ _usn_add_next_usn(e, be, 0);
+bail:
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- usn_bepreop_add\n");
+ return rc;
+}
+
+/*
+ * usn_bepreop_delete -- add/replace next USN to the entry
+ * bepreop_delete is not called if the entry is tombstone
+ */
+static int
+usn_bepreop_delete(Slapi_PBlock *pb)
+{
+ Slapi_Entry *e = NULL;
+ Slapi_Backend *be = NULL;
+ int rc = LDAP_SUCCESS;
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> usn_bepreop_delete\n");
+
+ /* add next USN to the entry; "be" contains the usn counter */
+ slapi_pblock_get(pb, SLAPI_DELETE_BEPREOP_ENTRY, &e);
+ if (NULL == e) {
+ rc = LDAP_NO_SUCH_OBJECT;
+ goto bail;
+ }
+ slapi_pblock_get(pb, SLAPI_BACKEND, &be);
+ if (NULL == be) {
+ rc = LDAP_PARAM_ERROR;
+ goto bail;
+ }
+ if (e->e_flags & SLAPI_ENTRY_FLAG_TOMBSTONE) {
+ Slapi_Operation *op = NULL;
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ slapi_operation_set_flag(op, OP_FLAG_TOMBSTONE_ENTRY);
+ } else {
+ _usn_add_next_usn(e, be, KEEP_PREV_USN);
+ }
+bail:
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- usn_bepreop_delete\n");
+ return rc;
+}
+
+/*
+ * usn_bepreop_modify - add/replace next USN to the mods;
+ * shared by modify and modrdn
+ */
+static int
+usn_bepreop_modify (Slapi_PBlock *pb)
+{
+ LDAPMod **mods = NULL;
+ Slapi_Backend *be = NULL;
+ int rc = LDAP_SUCCESS;
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> usn_bepreop_modify\n");
+
+ /* add/replace next USN to the mods; "be" contains the usn counter */
+ slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
+ slapi_pblock_get(pb, SLAPI_BACKEND, &be);
+ if (NULL == be) {
+ rc = LDAP_PARAM_ERROR;
+ goto bail;
+ }
+ if (LDAP_SUCCESS == _usn_mod_next_usn(&mods, be)) {
+ slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
+ }
+bail:
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- usn_bepreop_modify\n");
+ return rc;
+}
+
+/* count up the counter */
+static int
+usn_bepostop (Slapi_PBlock *pb)
+{
+ int rc = -1;
+ Slapi_Backend *be = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> usn_bepostop\n");
+
+ /* if op is not successful, don't increment the counter */
+ slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
+ if (LDAP_SUCCESS != rc) {
+ goto bail;
+ }
+
+ slapi_pblock_get(pb, SLAPI_BACKEND, &be);
+ if (NULL == be) {
+ rc = LDAP_PARAM_ERROR;
+ goto bail;
+ }
+
+ if (be->be_usn_counter) {
+ slapi_counter_increment(be->be_usn_counter);
+ }
+bail:
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- usn_bepostop\n");
+ return rc;
+}
+
+/* mimic replication to turn on create_tombstone_entry */
+static int
+usn_get_attr(Slapi_PBlock *pb, const char* type, void *value)
+{
+ if (0 == strcasecmp(type, "nsds5ReplicaTombstonePurgeInterval")) {
+ *(int *)value = 1;
+ } else {
+ *(int *)value = 0;
+ }
+}
+
+void
+usn_set_identity(void *identity)
+{
+ _usn_identity = identity;
+}
+
+void *
+usn_get_identity()
+{
+ return _usn_identity;
+}
+
+/*
+ * usn_rootdse_search -- callback for the search on root DSN
+ * add lastusn value per backend
+ *
+ * example:
+ * ldapsearch -b "" -s base "(objectclass=*)" lastusn
+ * dn:
+ * lastusn;userroot: 72
+ * lastusn;testbackend: 15
+ */
+static int
+usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
+ int *returncode, char *returntext, void *arg)
+{
+ char *cookie = NULL;
+ Slapi_Backend *be;
+ struct berval *vals[2];
+ struct berval usn_berval;
+ vals[0] = &usn_berval;
+ vals[1] = NULL;
+ char counter_buf[USN_COUNTER_BUF_LEN];
+ int attr_len = 64; /* length of lastusn;<backend_name> */
+ char *attr = (char *)slapi_ch_malloc(attr_len);
+ char *attr_subp = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> usn_rootdse_search\n");
+
+ usn_berval.bv_val = counter_buf;
+ PR_snprintf(attr, USN_LAST_USN_ATTR_CORE_LEN+1, "%s;", USN_LAST_USN);
+ attr_subp = attr + USN_LAST_USN_ATTR_CORE_LEN;
+ for (be = slapi_get_first_backend(&cookie); be;
+ be = slapi_get_next_backend(cookie)) {
+ if (NULL == be->be_usn_counter) { /* no counter == not a db backend */
+ continue;
+ }
+ /* get a next USN counter from be_usn_counter; then minus 1 from it */
+ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64,
+ slapi_counter_get_value(be->be_usn_counter)-1);
+ usn_berval.bv_len = strlen(usn_berval.bv_val);
+
+ if (USN_LAST_USN_ATTR_CORE_LEN + strlen(be->be_name) + 1 > attr_len) {
+ attr_len *= 2;
+ attr = (char *)slapi_ch_realloc(attr, attr_len);
+ attr_subp = attr + USN_LAST_USN_ATTR_CORE_LEN;
+ }
+ PR_snprintf(attr_subp, attr_len - USN_LAST_USN_ATTR_CORE_LEN,
+ "%s", be->be_name);
+ slapi_entry_attr_replace(e, attr, vals);
+ }
+
+ slapi_ch_free_string(&cookie);
+ slapi_ch_free_string(&attr);
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- usn_rootdse_search\n");
+ return SLAPI_DSE_CALLBACK_OK;
+}
diff --git a/ldap/servers/plugins/usn/usn.h b/ldap/servers/plugins/usn/usn.h
new file mode 100644
index 00000000..cf0cd184
--- /dev/null
+++ b/ldap/servers/plugins/usn/usn.h
@@ -0,0 +1,57 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include <string.h>
+#include "slap.h"
+#include "slapi-plugin.h"
+
+#define USN_PLUGIN_SUBSYSTEM "usn-plugin"
+
+#define USN_CSNGEN_ID 65535
+
+#define USN_LAST_USN "lastusn"
+#define USN_LAST_USN_ATTR_CORE_LEN 8 /* lastusn; */
+
+#define USN_COUNTER_BUF_LEN 32 /* enough size for 64 bit inteters */
+
+/* usn.c */
+void usn_set_identity(void *identity);
+void *usn_get_identity();
+
+/* usn_cleanup.c */
+int usn_cleanup_start(Slapi_PBlock *pb);
+
diff --git a/ldap/servers/plugins/usn/usn_cleanup.c b/ldap/servers/plugins/usn/usn_cleanup.c
new file mode 100644
index 00000000..bf13073a
--- /dev/null
+++ b/ldap/servers/plugins/usn/usn_cleanup.c
@@ -0,0 +1,326 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "usn.h"
+
+struct usn_cleanup_data {
+ char *suffix;
+ char *maxusn_to_delete;
+};
+
+
+static int usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e,
+ Slapi_Entry *eAfter, int *returncode, char *returntext, void *arg);
+
+int
+usn_cleanup_start(Slapi_PBlock *pb)
+{
+ int rc = slapi_task_register_handler("USN tombstone cleanup task",
+ usn_cleanup_add);
+ return rc;
+}
+
+/*
+ * Task thread
+ */
+static void
+usn_cleanup_thread(void *arg)
+{
+ Slapi_Task *task = (Slapi_Task *)arg;
+ int rv = 0;
+ int total_work = 2;
+ /* fetch our argument from the task */
+ struct usn_cleanup_data *cleanup_data =
+ (struct usn_cleanup_data*)slapi_task_get_data(task);
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries = NULL, **ep = NULL;
+ Slapi_PBlock *delete_pb = NULL;
+ char *filter = "objectclass=nsTombstone";
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> usn_cleanup_thread\n");
+
+ if (NULL == usn_get_identity()) { /* plugin is not initialized */
+ slapi_task_log_notice(task, "USN plugin is not initialized\n");
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup: USN plugin is not initialized\n");
+ rv = -1;
+ goto bail;
+ }
+
+ /* update task state to show it's running */
+ slapi_task_begin(task, total_work);
+ if (cleanup_data->maxusn_to_delete) {
+ /* (&(objectclass=nsTombstone)(entryusn<=maxusn_to_delete)) */
+ int filter_len =
+ strlen(filter) + strlen(cleanup_data->maxusn_to_delete) + 32;
+ filter = (char *)slapi_ch_malloc(filter_len);
+ PR_snprintf(filter, filter_len,
+ "(&(objectclass=nsTombstone)(entryusn<=%s))",
+ cleanup_data->maxusn_to_delete);
+ }
+
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(search_pb, cleanup_data->suffix,
+ LDAP_SCOPE_SUBTREE, filter,
+ NULL, 0, NULL, NULL, usn_get_identity(), 0);
+ slapi_search_internal_pb(search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rv);
+ if (LDAP_NO_SUCH_OBJECT == rv) {
+ slapi_task_log_notice(task,
+ "USN tombstone cleanup: no such suffix %s.\n",
+ cleanup_data->suffix);
+ slapi_task_log_status(task,
+ "USN tombstone cleanup: no such suffix %s.\n",
+ cleanup_data->suffix);
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup: no such suffix %s.\n",
+ cleanup_data->suffix);
+ goto bail;
+ } else if (LDAP_SUCCESS != rv) {
+ slapi_task_log_notice(task,
+ "USN tombstone cleanup: searching tombstone entries "
+ "in %s failed; (%d).\n", cleanup_data->suffix, rv);
+ slapi_task_log_status(task,
+ "USN tombstone cleanup: searching tombstone entries in "
+ "%s failed; (%d).\n", cleanup_data->suffix, rv);
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup: searching tombstone entries in "
+ "%s failed; (%d).\n", cleanup_data->suffix, rv);
+ goto bail;
+ }
+
+ slapi_task_log_notice(task,
+ "USN tombstone cleanup task starts (suffix: %s) ...\n",
+ cleanup_data->suffix);
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup task starts (suffix: %s) ...\n",
+ cleanup_data->suffix);
+
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+
+ delete_pb = slapi_pblock_new();
+ for (ep = entries; ep && *ep; ep++) {
+ int delrv = 0;
+ const Slapi_DN *sdn = slapi_entry_get_sdn_const(*ep);
+
+ slapi_delete_internal_set_pb(delete_pb, slapi_sdn_get_dn(sdn),
+ NULL, NULL, usn_get_identity(), 0);
+ slapi_delete_internal_pb(delete_pb);
+ slapi_pblock_get(delete_pb, SLAPI_PLUGIN_INTOP_RESULT, &delrv);
+ if (LDAP_SUCCESS != delrv) {
+ slapi_task_log_notice(task,
+ "USN tombstone cleanup: deleting %s failed; (%d).\n",
+ slapi_sdn_get_dn(sdn), delrv);
+ slapi_task_log_status(task,
+ "USN tombstone cleanup: deleting %s failed; (%d).\n",
+ slapi_sdn_get_dn(sdn), delrv);
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup: deleting %s failed; (%d).\n",
+ slapi_sdn_get_dn(sdn), delrv);
+ rv = delrv;
+ }
+
+ slapi_pblock_init(delete_pb);
+ slapi_task_inc_progress(task);
+ }
+ slapi_task_log_notice(task, "USN tombstone cleanup task finished.");
+ slapi_task_log_status(task, "USN tombstone cleanup task finished.");
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup task finished.\n");
+bail:
+ slapi_free_search_results_internal(search_pb);
+ slapi_pblock_destroy(search_pb);
+ slapi_pblock_destroy(delete_pb);
+ if (cleanup_data->maxusn_to_delete) {
+ slapi_ch_free_string(&filter);
+ }
+ slapi_ch_free_string(&cleanup_data->maxusn_to_delete);
+ slapi_ch_free_string(&cleanup_data->suffix);
+ slapi_ch_free((void **)&cleanup_data);
+
+ /* this will queue the destruction of the task */
+ slapi_task_finish(task, rv);
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- usn_cleanup_thread\n");
+}
+
+#define MAPPING_TREE_BASE_DN "cn=mapping tree,cn=config"
+
+static int
+_usn_cleanup_is_mmr_enabled(const char *suffix)
+{
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries = NULL;
+ char *base_dn = NULL;
+ int rc = 0; /* disabled, by default */
+
+ base_dn = slapi_ch_smprintf("cn=replica,cn=\"%s\",%s",
+ suffix, MAPPING_TREE_BASE_DN);
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_ONELEVEL,
+ "objectclass=nsDS5ReplicationAgreement",
+ NULL, 0, NULL, NULL, usn_get_identity(), 0);
+ slapi_search_internal_pb(search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+ if (LDAP_SUCCESS != rc) { /* agreement is not available */
+ goto bail;
+ }
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if (entries && *entries) {
+ rc = 1; /* At least one agreement on the suffix is found */
+ }
+bail:
+ slapi_free_search_results_internal(search_pb);
+ slapi_pblock_destroy(search_pb);
+ slapi_ch_free_string(&base_dn);
+
+ return rc;
+}
+
+static int
+usn_cleanup_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter,
+ int *returncode, char *returntext, void *arg)
+{
+ PRThread *thread = NULL;
+ char *cn = NULL;
+ char *suffix = NULL;
+ char *backend = NULL;
+ char *maxusn = NULL;
+ struct usn_cleanup_data *cleanup_data = NULL;
+ int rv = SLAPI_DSE_CALLBACK_OK;
+ Slapi_Task *task = NULL;
+ Slapi_Backend *be = NULL;
+ const Slapi_DN *be_suffix = NULL;
+
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "--> usn_cleanup_add\n");
+
+ *returncode = LDAP_SUCCESS;
+ cn = slapi_entry_attr_get_charptr(e, "cn");
+ if (NULL == cn) {
+ *returncode = LDAP_OBJECT_CLASS_VIOLATION;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto bail;
+ }
+
+ /* get args */
+ suffix = slapi_entry_attr_get_charptr(e, "suffix");
+ backend = slapi_entry_attr_get_charptr(e, "backend");
+ maxusn = slapi_entry_attr_get_charptr(e, "maxusn_to_delete");
+
+ if (NULL == suffix && NULL == backend) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup: Both suffix and backend are missing.\n");
+ *returncode = LDAP_PARAM_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto bail;
+ }
+
+ /* suffix is not given, but backend is; get the suffix */
+ if (NULL == suffix && NULL != backend) {
+ be = slapi_be_select_by_instance_name(backend);
+ be_suffix = slapi_be_getsuffix(be, 0);
+ if (be_suffix) {
+ suffix = slapi_ch_strdup(slapi_sdn_get_ndn(be_suffix));
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup: Backend %s is invalid.\n", backend);
+ *returncode = LDAP_PARAM_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto bail;
+ }
+ }
+
+ /* The suffix is the target of replication,
+ * we don't want to clean up tombstones used by MMR */
+ if (_usn_cleanup_is_mmr_enabled(suffix)) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup: Suffix %s is replicated. Unwilling to "
+ "perform cleaning up tombstones.\n", suffix);
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto bail;
+ }
+
+ cleanup_data =
+ (struct usn_cleanup_data *)slapi_ch_malloc(sizeof(struct usn_cleanup_data));
+ cleanup_data->suffix = slapi_ch_strdup(suffix);
+ cleanup_data->maxusn_to_delete = slapi_ch_strdup(maxusn);
+
+ /* allocate new task now */
+ task = slapi_new_task(slapi_entry_get_ndn(e));
+ if (task == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup: unable to allocate new task.\n");
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ goto bail;
+ }
+
+ /* Stash our argument in the task for use by the task thread */
+ slapi_task_set_data(task, cleanup_data);
+
+ /* start the USN tombstone cleanup task as a separate thread */
+ thread = PR_CreateThread(PR_USER_THREAD, usn_cleanup_thread,
+ (void *)task, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, SLAPD_DEFAULT_THREAD_STACKSIZE);
+ if (thread == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+ "USN tombstone cleanup: unable to create task thread.\n");
+ *returncode = LDAP_OPERATIONS_ERROR;
+ rv = SLAPI_DSE_CALLBACK_ERROR;
+ slapi_task_finish(task, *returncode);
+ } else {
+ /* thread successful */
+ rv = SLAPI_DSE_CALLBACK_OK;
+ }
+bail:
+ slapi_ch_free_string(&cn);
+ slapi_ch_free_string(&suffix);
+ slapi_ch_free_string(&backend);
+ slapi_ch_free_string(&maxusn);
+ slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
+ "<-- usn_cleanup_add\n");
+ return rv;
+}
+
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index 1b6dda54..3036bf7c 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -739,6 +739,7 @@ typedef struct _back_search_result_set
#define LDBM_DNCOMP_OID "2.16.840.1.113730.3.1.603"
#define LDBM_PARENTID_OID "2.16.840.1.113730.3.1.604"
#define LDBM_ENTRYID_OID "2.16.840.1.113730.3.1.605"
+#define LDBM_ENTRYUSN_OID "2.16.840.1.113730.3.1.606"
/* Name of psuedo attribute used to track default indexes */
#define LDBM_PSEUDO_ATTR_DEFAULT ".default"
diff --git a/ldap/servers/slapd/back-ldbm/import.c b/ldap/servers/slapd/back-ldbm/import.c
index 57c208a8..48e19c81 100644
--- a/ldap/servers/slapd/back-ldbm/import.c
+++ b/ldap/servers/slapd/back-ldbm/import.c
@@ -1052,6 +1052,9 @@ static int import_all_done(ImportJob *job, int ret)
if (ret != 0)
return ret;
+ /* Reset USN slapi_counter with the last key of the entryUSN index */
+ ldbm_set_last_usn(inst->inst_be);
+
/* bring backend online again */
slapi_mtn_be_enable(inst->inst_be);
}
diff --git a/ldap/servers/slapd/back-ldbm/init.c b/ldap/servers/slapd/back-ldbm/init.c
index c32f9825..be9c114d 100644
--- a/ldap/servers/slapd/back-ldbm/init.c
+++ b/ldap/servers/slapd/back-ldbm/init.c
@@ -84,6 +84,10 @@ ldbm_back_add_schema( Slapi_PBlock *pb )
LDBM_ENTRYID_OID, DIRSTRING_SYNTAX_OID, CASEIGNOREMATCH_NAME,
SLAPI_ATTR_FLAG_SINGLE );
+ rc |= add_ldbm_internal_attr_syntax( "entryusn",
+ LDBM_ENTRYUSN_OID, INTEGER_SYNTAX_OID, INTFIRSTCOMPMATCH_NAME,
+ SLAPI_ATTR_FLAG_SINGLE|SLAPI_ATTR_FLAG_NOUSERMOD );
+
return rc;
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index b9f573a7..fa53e05f 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -159,6 +159,7 @@ ldbm_back_add( Slapi_PBlock *pb )
operation->o_status = SLAPI_OP_STATUS_WILL_COMPLETE;
}
if ( slapi_op_abandoned( pb ) ) {
+ ldap_result_code = -1; /* needs to distinguish from "success" */
goto error_return;
}
@@ -847,6 +848,8 @@ common_return:
{
cache_return( &inst->inst_cache, &addingentry );
}
+ /* bepost op needs to know this result */
+ slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
/* JCMREPL - The bepostop is called even if the operation fails. */
plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_ADD_FN);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index fe02b207..74d8de8e 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -82,6 +82,9 @@ ldbm_back_delete( Slapi_PBlock *pb )
int tombstone_in_cache = 0;
entry_address *addr;
int addordel_flags = 0; /* passed to index_addordel */
+ char *entryusn_str = NULL;
+ char *prev_entryusn_str = NULL;
+ Slapi_Entry *orig_entry = NULL;
slapi_pblock_get( pb, SLAPI_BACKEND, &be);
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
@@ -133,6 +136,23 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
+ /* find and lock the entry we are about to modify */
+ if ( (e = find_entry2modify( pb, be, addr, NULL )) == NULL )
+ {
+ ldap_result_code= -1;
+ goto error_return; /* error result sent by find_entry2modify() */
+ }
+
+ if ( slapi_entry_has_children( e->ep_entry ) )
+ {
+ ldap_result_code= LDAP_NOT_ALLOWED_ON_NONLEAF;
+ goto error_return;
+ }
+
+ /* set entry in case be-preop plugins need to work on it (e.g., USN) */
+ slapi_pblock_get( pb, SLAPI_DELETE_BEPREOP_ENTRY, &orig_entry );
+ slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, e->ep_entry );
+
/* Don't call pre-op for Tombstone entries */
if (!delete_tombstone_entry)
{
@@ -141,7 +161,8 @@ ldbm_back_delete( Slapi_PBlock *pb )
* backend pre-op plugin. To ensure a consistent snapshot of this state
* we wrap the reading of the entry with the dblock.
*/
- ldap_result_code= get_copy_of_entry(pb, addr, &txn, SLAPI_DELETE_EXISTING_ENTRY, !is_replicated_operation);
+ ldap_result_code= get_copy_of_entry(pb, addr, &txn,
+ SLAPI_DELETE_EXISTING_ENTRY, !is_replicated_operation);
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
if(plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN)==-1)
{
@@ -152,21 +173,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
goto error_return;
}
- }
-
-
- /* find and lock the entry we are about to modify */
- if ( (e = find_entry2modify( pb, be, addr, NULL )) == NULL )
- {
- ldap_result_code= -1;
- goto error_return; /* error result sent by find_entry2modify() */
+ /* the flag could be set in a preop plugin (e.g., USN) */
+ delete_tombstone_entry = operation_is_flag_set(operation,
+ OP_FLAG_TOMBSTONE_ENTRY);
}
- if ( slapi_entry_has_children( e->ep_entry ) )
- {
- ldap_result_code= LDAP_NOT_ALLOWED_ON_NONLEAF;
- goto error_return;
- }
+ slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
/*
* Sanity check to avoid to delete a non-tombstone or to tombstone again
@@ -196,8 +208,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
opcsn = operation_get_csn (operation);
if (!delete_tombstone_entry)
{
- if (opcsn == NULL && !is_fixup_operation && operation->o_csngen_handler)
+ /* If both USN and replication is enabled, csn set by replication
+ * should be honored. */
+ if ((opcsn == NULL || ldbm_usn_enabled(be)) &&
+ !is_fixup_operation && operation->o_csngen_handler)
{
+ csn_free(&opcsn); /* free opcsn set by USN plugin, if any */
/*
* Current op is a user request. Opcsn will be assigned
* by entry_assign_operation_csn() if the dn is in an
@@ -338,6 +354,20 @@ ldbm_back_delete( Slapi_PBlock *pb )
slapi_entry_add_value(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, tomb_value);
slapi_value_free(&tomb_value);
+ /* retrieve previous entry usn value, if any */
+ prev_entryusn_str = slapi_entry_attr_get_charptr(tombstone->ep_entry,
+ SLAPI_ATTR_ENTRYUSN_PREV);
+ if (prev_entryusn_str) {
+ /* discard the previous value from the tombstone entry */
+ retval = slapi_entry_delete_string(tombstone->ep_entry,
+ SLAPI_ATTR_ENTRYUSN_PREV, prev_entryusn_str);
+ if (0 != retval) {
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (deleting %s) failed, err=%d\n",
+ SLAPI_ATTR_ENTRYUSN, retval, 0) ;
+ }
+ }
+
/* XXXggood above used to be: slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE); */
/* JCMREPL - Add a description of what's going on? */
}
@@ -432,45 +462,110 @@ ldbm_back_delete( Slapi_PBlock *pb )
* above, but we want it to remain in the nsUniqueID and nscpEntryDN indexes
* and for objectclass=tombstone.
*/
- retval = index_addordel_string(be,SLAPI_ATTR_OBJECTCLASS,SLAPI_ATTR_VALUE_TOMBSTONE,tombstone->ep_id,BE_INDEX_ADD,&txn);
+ retval = index_addordel_string(be, SLAPI_ATTR_OBJECTCLASS,
+ SLAPI_ATTR_VALUE_TOMBSTONE,
+ tombstone->ep_id,BE_INDEX_ADD, &txn);
if (DB_LOCK_DEADLOCK == retval) {
- LDAPDebug( LDAP_DEBUG_ARGS, "delete 4 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_ARGS,
+ "delete (adding %s) DB_LOCK_DEADLOCK\n",
+ SLAPI_ATTR_VALUE_TOMBSTONE, 0, 0 );
/* Retry txn */
continue;
}
if (0 != retval) {
- LDAPDebug( LDAP_DEBUG_TRACE, "delete 1 BAD, err=%d %s\n",
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (adding %s) failed, err=%d %s\n",
+ SLAPI_ATTR_VALUE_TOMBSTONE, retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- retval = index_addordel_string(be,SLAPI_ATTR_UNIQUEID,slapi_entry_get_uniqueid(tombstone->ep_entry),tombstone->ep_id,BE_INDEX_ADD,&txn);
+ retval = index_addordel_string(be, SLAPI_ATTR_UNIQUEID,
+ slapi_entry_get_uniqueid(tombstone->ep_entry),
+ tombstone->ep_id,BE_INDEX_ADD,&txn);
if (DB_LOCK_DEADLOCK == retval) {
- LDAPDebug( LDAP_DEBUG_ARGS, "delete 5 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_ARGS,
+ "delete (adding %s) DB_LOCK_DEADLOCK\n",
+ SLAPI_ATTR_UNIQUEID, 0, 0 );
/* Retry txn */
continue;
}
if (0 != retval) {
- LDAPDebug( LDAP_DEBUG_TRACE, "delete 2 BAD, err=%d %s\n",
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (adding %s) failed, err=%d %s\n",
+ SLAPI_ATTR_UNIQUEID, retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- retval = index_addordel_string(be,SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(nscpEntrySDN),tombstone->ep_id,BE_INDEX_ADD,&txn);
+ retval = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN,
+ slapi_sdn_get_ndn(nscpEntrySDN),
+ tombstone->ep_id, BE_INDEX_ADD, &txn);
if (DB_LOCK_DEADLOCK == retval) {
- LDAPDebug( LDAP_DEBUG_ARGS, "delete 6 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_ARGS,
+ "delete (adding %s) DB_LOCK_DEADLOCK\n",
+ SLAPI_ATTR_NSCP_ENTRYDN, 0, 0 );
/* Retry txn */
continue;
}
if (0 != retval) {
- LDAPDebug( LDAP_DEBUG_TRACE, "delete 3 BAD, err=%d %s\n",
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (adding %s) failed, err=%d %s\n",
+ SLAPI_ATTR_NSCP_ENTRYDN, retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
+ /* add a new usn to the entryusn index */
+ entryusn_str = slapi_entry_attr_get_charptr(tombstone->ep_entry,
+ SLAPI_ATTR_ENTRYUSN);
+ if (entryusn_str) {
+ retval = index_addordel_string(be, SLAPI_ATTR_ENTRYUSN,
+ entryusn_str, tombstone->ep_id, BE_INDEX_ADD, &txn);
+ slapi_ch_free_string(&entryusn_str);
+ if (DB_LOCK_DEADLOCK == retval) {
+ LDAPDebug( LDAP_DEBUG_ARGS,
+ "delete (adding %s) DB_LOCK_DEADLOCK\n",
+ SLAPI_ATTR_ENTRYUSN, 0, 0 );
+ /* Retry txn */
+ continue;
+ }
+ if (0 != retval) {
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (adding %s) failed, err=%d %s\n",
+ SLAPI_ATTR_ENTRYUSN, retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
+ if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ }
+ /* delete a previous value (if it exists) from the entryusn index */
+ if (prev_entryusn_str) {
+ retval = index_addordel_string(be, SLAPI_ATTR_ENTRYUSN,
+ prev_entryusn_str, tombstone->ep_id,
+ BE_INDEX_DEL|BE_INDEX_EQUALITY, &txn);
+ slapi_ch_free_string(&prev_entryusn_str);
+ if (DB_LOCK_DEADLOCK == retval) {
+ LDAPDebug( LDAP_DEBUG_ARGS,
+ "delete (deleting %s) DB_LOCK_DEADLOCK\n",
+ SLAPI_ATTR_ENTRYUSN, 0, 0 );
+ /* Retry txn */
+ continue;
+ }
+ if (0 != retval) {
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (deleting %s) failed, err=%d %s\n",
+ SLAPI_ATTR_ENTRYUSN, retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
+ if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ }
} /* create_tombstone_entry */
else if (delete_tombstone_entry)
{
@@ -480,45 +575,88 @@ ldbm_back_delete( Slapi_PBlock *pb )
*/
char *nscpedn = NULL;
- retval = index_addordel_string(be,SLAPI_ATTR_OBJECTCLASS,SLAPI_ATTR_VALUE_TOMBSTONE,e->ep_id,BE_INDEX_DEL,&txn);
+ retval = index_addordel_string(be, SLAPI_ATTR_OBJECTCLASS,
+ SLAPI_ATTR_VALUE_TOMBSTONE, e->ep_id,
+ BE_INDEX_DEL, &txn);
if (DB_LOCK_DEADLOCK == retval) {
- LDAPDebug( LDAP_DEBUG_ARGS, "delete 4 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_ARGS,
+ "delete (deleting %s) DB_LOCK_DEADLOCK\n",
+ SLAPI_ATTR_VALUE_TOMBSTONE, 0, 0 );
/* Retry txn */
continue;
}
if (0 != retval) {
- LDAPDebug( LDAP_DEBUG_TRACE, "delete 1 BAD, err=%d %s\n",
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (deleting %s) failed, err=%d %s\n",
+ SLAPI_ATTR_VALUE_TOMBSTONE, retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- retval = index_addordel_string(be,SLAPI_ATTR_UNIQUEID,slapi_entry_get_uniqueid(e->ep_entry),e->ep_id,BE_INDEX_DEL,&txn);
+ retval = index_addordel_string(be, SLAPI_ATTR_UNIQUEID,
+ slapi_entry_get_uniqueid(e->ep_entry),
+ e->ep_id, BE_INDEX_DEL, &txn);
if (DB_LOCK_DEADLOCK == retval) {
- LDAPDebug( LDAP_DEBUG_ARGS, "delete 5 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_ARGS,
+ "delete (deleting %s) DB_LOCK_DEADLOCK\n",
+ SLAPI_ATTR_UNIQUEID, 0, 0 );
/* Retry txn */
continue;
}
if (0 != retval) {
- LDAPDebug( LDAP_DEBUG_TRACE, "delete 2 BAD, err=%d %s\n",
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (deleting %s) failed, err=%d %s\n",
+ SLAPI_ATTR_UNIQUEID, retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- nscpedn = slapi_entry_attr_get_charptr(e->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN);
+ nscpedn = slapi_entry_attr_get_charptr(e->ep_entry,
+ SLAPI_ATTR_NSCP_ENTRYDN);
if (nscpedn) {
- retval = index_addordel_string(be,SLAPI_ATTR_NSCP_ENTRYDN, nscpedn, e->ep_id,BE_INDEX_DEL,&txn);
+ retval = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN,
+ nscpedn, e->ep_id, BE_INDEX_DEL, &txn);
slapi_ch_free((void **)&nscpedn);
if (DB_LOCK_DEADLOCK == retval) {
- LDAPDebug( LDAP_DEBUG_ARGS, "delete 6 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_ARGS,
+ "delete (deleting %s) DB_LOCK_DEADLOCK\n",
+ SLAPI_ATTR_NSCP_ENTRYDN, 0, 0 );
+ /* Retry txn */
+ continue;
+ }
+ if (0 != retval) {
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (deleting %s) failed, err=%d %s\n",
+ SLAPI_ATTR_NSCP_ENTRYDN, retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
+ if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ }
+ /* delete usn from the entryusn index */
+ entryusn_str = slapi_entry_attr_get_charptr(e->ep_entry,
+ SLAPI_ATTR_ENTRYUSN);
+ if (entryusn_str) {
+ retval = index_addordel_string(be, SLAPI_ATTR_ENTRYUSN,
+ entryusn_str, e->ep_id,
+ BE_INDEX_DEL|BE_INDEX_EQUALITY, &txn);
+ slapi_ch_free_string(&entryusn_str);
+ if (DB_LOCK_DEADLOCK == retval) {
+ LDAPDebug( LDAP_DEBUG_ARGS,
+ "delete (deleting %s) DB_LOCK_DEADLOCK\n",
+ SLAPI_ATTR_ENTRYUSN, 0, 0 );
/* Retry txn */
continue;
}
if (0 != retval) {
- LDAPDebug( LDAP_DEBUG_TRACE, "delete 3 BAD, err=%d %s\n",
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE,
+ "delete (deleting %s) failed, err=%d %s\n",
+ SLAPI_ATTR_ENTRYUSN, retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
index e8fc3d73..b4e44732 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
@@ -752,6 +752,12 @@ static int ldbm_instance_generate(struct ldbminfo *li, char *instance_name,
ldbm_instance_config_load_dse_info(new_be->be_instance_info);
rc = ldbm_instance_create_default_indexes(new_be);
+ /* if USN plugin is enabled, set slapi_counter */
+ if (plugin_enabled("USN", li->li_identity)) {
+ /* slapi_counter_new sets the initial value to 0 */
+ new_be->be_usn_counter = slapi_counter_new();
+ }
+
if (ret_be != NULL) {
*ret_be = new_be;
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index e85443d7..6ae95448 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -303,6 +303,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
}
if ( !change_entry || ldap_result_code != 0 ) {
/* change_entry == 0 is not an error, but we need to free lock etc */
+ slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
goto error_return;
}
}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_usn.c b/ldap/servers/slapd/back-ldbm/ldbm_usn.c
new file mode 100644
index 00000000..e8dd7237
--- /dev/null
+++ b/ldap/servers/slapd/back-ldbm/ldbm_usn.c
@@ -0,0 +1,196 @@
+/** BEGIN COPYRIGHT BLOCK
+ * This Program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; version 2 of the License.
+ *
+ * This Program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "back-ldbm.h"
+
+static int usn_get_last_usn(Slapi_Backend *be, PRUint64 *last_usn);
+
+/*
+ * USN counter part in the backend
+ * - If usn is enabled,
+ * - For each backend,
+ * - Get the last USN index key
+ * - Initialize the slapi counter with the next USN (last USN + 1)
+ *
+ * dn: cn=entryusn,cn=default indexes,cn=config,cn=ldbm database,cn=plugins,cn=
+ * config
+ * objectClass: top
+ * objectClass: nsIndex
+ * cn: entryusn
+ * nsSystemIndex: true
+ * nsIndexType: eq
+ */
+
+void
+ldbm_usn_init(struct ldbminfo *li)
+{
+ Slapi_DN *sdn = NULL;
+ void *node = NULL;
+ const char *base = NULL;
+ int rc = 0;
+ Slapi_Backend *be = NULL;
+ PRUint64 last_usn = 0;
+
+ /* if USN is not enabled, return immediately */
+ if (!plugin_enabled("USN", li->li_identity)) {
+ goto bail;
+ }
+
+ /* Search each namingContext in turn */
+ for ( sdn = slapi_get_first_suffix( &node, 0 ); sdn != NULL;
+ sdn = slapi_get_next_suffix( &node, 0 )) {
+ base = slapi_sdn_get_dn( sdn );
+ be = slapi_mapping_tree_find_backend_for_sdn(sdn);
+ slapi_log_error(SLAPI_LOG_TRACE, "ldbm_usn_init",
+ "backend: %s\n", be->be_name);
+ rc = usn_get_last_usn(be, &last_usn);
+ if (0 == rc) { /* only when the last usn is available */
+ be->be_usn_counter = slapi_counter_new();
+ slapi_counter_set_value(be->be_usn_counter, last_usn);
+ slapi_counter_increment(be->be_usn_counter); /* stores next usn */
+ }
+ }
+bail:
+ return;
+}
+
+/*
+ * usn_ge_last_usn: get the last USN from the entryusn equality index
+ */
+static int
+usn_get_last_usn(Slapi_Backend *be, PRUint64 *last_usn)
+{
+ struct attrinfo *ai = NULL;
+ struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
+ int rc = -1;
+ DB *db = NULL;
+ DBC *dbc = NULL;
+ DBT key; /* For the last usn */
+ DBT value;
+
+ if (NULL == last_usn) {
+ return rc;
+ }
+
+ memset(&key, 0, sizeof(key));
+ memset(&value, 0, sizeof(key));
+
+ *last_usn = -1; /* to start from 0 */
+
+ /* Open the entryusn index */
+ ainfo_get(be, "entryusn", &ai);
+
+ /* Open the entryusn index file */
+ rc = dblayer_get_index_file(be, ai, &db, DBOPEN_CREATE);
+ if (0 != rc) {
+ /* entryusn.db# is missing; it would be the first time. */
+ slapi_log_error(SLAPI_LOG_FATAL, "usn_get_last_usn",
+ "failed to open the entryusn index: %d", rc);
+ goto bail;
+ }
+
+ /* Get a cursor */
+ rc = db->cursor(db, NULL, &dbc, 0);
+ if (0 != rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, "usn_get_last_usn",
+ "failed to create a cursor: %d", rc);
+ goto bail;
+ }
+
+ key.flags = DB_DBT_MALLOC;
+ value.flags = DB_DBT_MALLOC;
+ rc = dbc->c_get(dbc, &key, &value, DB_LAST);
+ if ((0 == rc) && key.data) {
+ char *p = (char *)key.data;
+ while ((0 == rc) && ('=' != *p)) { /* get the last elem of equality */
+ slapi_ch_free(&(key.data));
+ slapi_ch_free(&(value.data));
+ rc = dbc->c_get(dbc, &key, &value, DB_PREV);
+ p = (char *)key.data;
+ }
+ if (0 == rc) {
+ *last_usn = strtoll(++p, (char **)NULL, 0); /* key.data: =num */
+ }
+ } else if (DB_NOTFOUND == rc) {
+ /* if empty, it's okay. This is just a beginning. */
+ rc = 0;
+ }
+ slapi_ch_free(&(key.data));
+ slapi_ch_free(&(value.data));
+
+bail:
+ if (dbc) {
+ dbc->c_close(dbc);
+ }
+ if (db) {
+ dblayer_release_index_file(be, ai, db);
+ }
+ return rc;
+}
+
+/*
+ * Whether USN is enabled or not is checked with be_usn_counter.
+ */
+int
+ldbm_usn_enabled(Slapi_Backend *be)
+{
+ return (NULL != be->be_usn_counter);
+}
+
+/*
+ * set last usn to the USN slapi_counter in backend
+ */
+int
+ldbm_set_last_usn(Slapi_Backend *be)
+{
+ PRUint64 last_usn = 0;
+ int rc = usn_get_last_usn(be, &last_usn);
+
+ if (0 == rc) { /* only when the last usn is available */
+ /* destroy old counter, if any */
+ slapi_counter_destroy(&(be->be_usn_counter));
+ be->be_usn_counter = slapi_counter_new();
+ slapi_counter_set_value(be->be_usn_counter, last_usn);
+ slapi_counter_increment(be->be_usn_counter); /* stores next usn */
+ }
+
+ return rc;
+}
diff --git a/ldap/servers/slapd/back-ldbm/misc.c b/ldap/servers/slapd/back-ldbm/misc.c
index b4c7942f..8fcb81f8 100644
--- a/ldap/servers/slapd/back-ldbm/misc.c
+++ b/ldap/servers/slapd/back-ldbm/misc.c
@@ -94,17 +94,19 @@ int return_on_disk_full(struct ldbminfo *li)
/* System Indexes */
static const char *systemIndexes[] = {
- "entrydn",
- "parentid",
- "objectclass",
"aci",
+ "entrydn",
"numsubordinates",
+ "parentid",
+ SLAPI_ATTR_OBJECTCLASS,
SLAPI_ATTR_UNIQUEID,
SLAPI_ATTR_NSCP_ENTRYDN,
ATTR_NSDS5_REPLCONFLICT,
+ SLAPI_ATTR_ENTRYUSN,
NULL
};
+
int
ldbm_attribute_always_indexed(const char *attrtype)
{
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
index 30d607ee..3fc58328 100644
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -632,3 +632,12 @@ int attrcrypt_encrypt_entry_inplace(backend *be, const struct backentry *inout);
int attrcrypt_encrypt_entry(backend *be, const struct backentry *in, struct backentry **out);
int attrcrypt_encrypt_index_key(backend *be, struct attrinfo *ai, const struct berval *in, struct berval **out);
int attrcrypt_init(ldbm_instance *li);
+
+/*
+ * ldbm_usn.c
+ */
+void ldbm_usn_init(struct ldbminfo *li);
+int ldbm_usn_enabled(backend *be);
+int ldbm_set_last_usn(Slapi_Backend *be);
+
+
diff --git a/ldap/servers/slapd/back-ldbm/start.c b/ldap/servers/slapd/back-ldbm/start.c
index 9b517eb1..6d833571 100644
--- a/ldap/servers/slapd/back-ldbm/start.c
+++ b/ldap/servers/slapd/back-ldbm/start.c
@@ -222,6 +222,9 @@ ldbm_back_start( Slapi_PBlock *pb )
initialized = 1;
}
+ /* initialize the USN counter */
+ ldbm_usn_init(li);
+
LDAPDebug( LDAP_DEBUG_TRACE, "ldbm backend done starting\n", 0, 0, 0 );
return( 0 );
diff --git a/ldap/servers/slapd/backend.c b/ldap/servers/slapd/backend.c
index c4c399f9..740de29d 100644
--- a/ldap/servers/slapd/backend.c
+++ b/ldap/servers/slapd/backend.c
@@ -64,7 +64,7 @@ be_init( Slapi_Backend *be, const char *type, const char *name, int isprivate, i
/* maximum group nesting level before giving up */
be->be_maxnestlevel = SLAPD_DEFAULT_GROUPNESTLEVEL;
be->be_noacl= 0;
- be->be_flags=0;
+ be->be_flags=0;
if (( fecfg = getFrontendConfig()) != NULL )
{
if ( fecfg->backendconfig != NULL && fecfg->backendconfig[ 0 ] != NULL )
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index 7e595111..ed51825e 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -2372,6 +2372,8 @@ slapd_exemode_db2ldif(int argc, char** argv)
}
slapi_ch_free( (void**)&myname );
if (db2ldif_dump_replica) {
+ eq_stop(); /* event queue should be shutdown before closing
+ all plugins (especailly, replication plugin) */
plugin_closeall( 1 /* Close Backends */, 1 /* Close Globals */);
}
return( return_value );
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index 98984ada..e5751a92 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -1592,6 +1592,10 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
(*(IFP *)value) = pblock->pb_plugin->plg_entrystorefunc;
break;
+ case SLAPI_PLUGIN_ENABLED:
+ *((int *)value) = pblock->pb_plugin_enabled;
+ break;
+
/* DSE add parameters */
case SLAPI_DSE_DONT_WRITE_WHEN_ADDING:
(*(int *)value) = pblock->pb_dse_dont_add_write;
@@ -2857,6 +2861,10 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
pblock->pb_plugin->plg_entrystorefunc = (IFP) value;
break;
+ case SLAPI_PLUGIN_ENABLED:
+ pblock->pb_plugin_enabled = *((int *)value);
+ break;
+
/* DSE add parameters */
case SLAPI_DSE_DONT_WRITE_WHEN_ADDING:
pblock->pb_dse_dont_add_write = *((int *)value);
diff --git a/ldap/servers/slapd/plugin.c b/ldap/servers/slapd/plugin.c
index 5ae63564..17730d59 100644
--- a/ldap/servers/slapd/plugin.c
+++ b/ldap/servers/slapd/plugin.c
@@ -2166,6 +2166,20 @@ plugin_setup(Slapi_Entry *plugin_entry, struct slapi_componentid *group,
configdir = config_get_configdir();
slapi_pblock_set(&pb, SLAPI_CONFIG_DIRECTORY, configdir);
+ /* see if the plugin is enabled or not */
+ if ((value = slapi_entry_attr_get_charptr(plugin_entry,
+ ATTR_PLUGIN_ENABLED)) &&
+ !strcasecmp(value, "off"))
+ {
+ enabled = 0;
+ }
+ else
+ {
+ enabled = 1;
+ }
+
+ slapi_pblock_set(&pb, SLAPI_PLUGIN_ENABLED, &enabled);
+
if ((*initfunc)(&pb) != 0)
{
LDAPDebug(LDAP_DEBUG_ANY, "Init function \"%s\" for \"%s\" plugin"
@@ -2193,18 +2207,6 @@ plugin_setup(Slapi_Entry *plugin_entry, struct slapi_componentid *group,
}
}
- /* see if the plugin is enabled or not */
- if ((value = slapi_entry_attr_get_charptr(plugin_entry,
- ATTR_PLUGIN_ENABLED)) &&
- !strcasecmp(value, "off"))
- {
- enabled = 0;
- }
- else
- {
- enabled = 1;
- }
-
if (value)
slapi_ch_free((void**)&value);
@@ -2859,3 +2861,45 @@ void plugin_print_versions(void)
}
}
+
+/*
+ * check the spedified plugin entry and its nssladp-pluginEnabled value
+ * Return Value: 1 if the plugin is on.
+ * : 0 otherwise.
+ */
+int
+plugin_enabled(const char *plugin_name, void *identity)
+{
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries = NULL, **ep = NULL;
+ char *on_off = NULL;
+ char *filter = NULL;
+ int rc = 0; /* disabled, by default */
+
+ filter = slapi_ch_smprintf("cn=%s", plugin_name);
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(search_pb, PLUGIN_BASE_DN, LDAP_SCOPE_ONELEVEL,
+ filter, NULL, 0, NULL, NULL, identity, 0);
+ slapi_search_internal_pb(search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+ if (LDAP_SUCCESS != rc) { /* plugin is not available */
+ goto bail;
+ }
+
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ for (ep = entries; ep && *ep; ep++) {
+ on_off = slapi_entry_attr_get_charptr(*ep, "nsslapd-pluginEnabled");
+ if (on_off && (0 == strcasecmp(on_off, "on"))) {
+ rc = 1; /* plugin is on */
+ goto bail;
+ }
+ }
+
+bail:
+ slapi_ch_free_string(&on_off);
+ slapi_free_search_results_internal(search_pb);
+ slapi_pblock_destroy(search_pb);
+ slapi_ch_free_string(&filter);
+
+ return rc;
+}
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index b4eb0c03..6eecd013 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1115,6 +1115,7 @@ typedef struct backend {
PRRWLock *be_lock;
PRRWLock *vlvSearchList_lock;
void *vlvSearchList;
+ Slapi_Counter *be_usn_counter; /* USN counter; one counter per backend */
} backend;
enum
@@ -1488,6 +1489,8 @@ typedef struct slapi_pblock {
int *pb_substrlens; /* user specified minimum substr search key lengths:
* nsSubStrBegin, nsSubStrMiddle, nsSubStrEnd
*/
+ int pb_plugin_enabled; /* nsslapd-pluginEnabled: on|off */
+ /* used in plugin init; pb_plugin is not ready, then */
} slapi_pblock;
/* index if substrlens */
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index e04fad9b..d5efe4d5 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -296,7 +296,9 @@ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...)
#define SLAPI_ATTR_OBJECTCLASS "objectclass"
#define SLAPI_ATTR_VALUE_TOMBSTONE "nsTombstone"
#define SLAPI_ATTR_VALUE_PARENT_UNIQUEID "nsParentUniqueID"
-#define SLAPI_ATTR_NSCP_ENTRYDN "nscpEntryDN"
+#define SLAPI_ATTR_NSCP_ENTRYDN "nscpEntryDN"
+#define SLAPI_ATTR_ENTRYUSN "entryusn"
+#define SLAPI_ATTR_ENTRYUSN_PREV "preventryusn"
/* opaque structures */
@@ -3272,6 +3274,7 @@ typedef struct slapi_plugindesc {
/* entry fetch and entry store values */
#define SLAPI_PLUGIN_ENTRY_FETCH_FUNC 813
#define SLAPI_PLUGIN_ENTRY_STORE_FUNC 814
+#define SLAPI_PLUGIN_ENABLED 815
/*
* Defined values of SLAPI_PLUGIN_SYNTAX_FLAGS:
@@ -3332,6 +3335,7 @@ typedef struct slapi_plugindesc {
#define SLAPI_DELETE_TARGET SLAPI_TARGET_DN
#define SLAPI_DELETE_EXISTING_ENTRY SLAPI_ADD_EXISTING_DN_ENTRY
#define SLAPI_DELETE_GLUE_PARENT_ENTRY SLAPI_ADD_PARENT_ENTRY
+#define SLAPI_DELETE_BEPREOP_ENTRY SLAPI_ENTRY_PRE_OP
/* modify arguments */
#define SLAPI_MODIFY_TARGET SLAPI_TARGET_DN
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 85c45896..21b8dc4f 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -1200,6 +1200,9 @@ void DS_Sleep(PRIntervalTime ticks);
#define PRLDAP_SET_PORT(myaddr,myport) \
((myaddr)->raw.family == PR_AF_INET6 ? ((myaddr)->ipv6.port = PR_htons(myport)) : ((myaddr)->inet.port = PR_htons(myport)))
+/* plugin.c */
+int plugin_enabled(const char *plugin_name, void *identity);
+
#ifdef __cplusplus
}
#endif
diff --git a/ltmain.sh b/ltmain.sh
index 8e5a9304..8e5a9304 100755..100644
--- a/ltmain.sh
+++ b/ltmain.sh