diff options
| author | cvsadm <cvsadm> | 2005-01-21 00:44:34 +0000 |
|---|---|---|
| committer | cvsadm <cvsadm> | 2005-01-21 00:44:34 +0000 |
| commit | b2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch) | |
| tree | cf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/plugins/statechange | |
| download | ds-ldapserver7x.tar.gz ds-ldapserver7x.tar.xz ds-ldapserver7x.zip | |
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/servers/plugins/statechange')
| -rw-r--r-- | ldap/servers/plugins/statechange/Makefile | 78 | ||||
| -rw-r--r-- | ldap/servers/plugins/statechange/dllmain.c | 96 | ||||
| -rw-r--r-- | ldap/servers/plugins/statechange/statechange.c | 450 | ||||
| -rw-r--r-- | ldap/servers/plugins/statechange/statechange.def | 10 |
4 files changed, 634 insertions, 0 deletions
diff --git a/ldap/servers/plugins/statechange/Makefile b/ldap/servers/plugins/statechange/Makefile new file mode 100644 index 00000000..bc04a3f0 --- /dev/null +++ b/ldap/servers/plugins/statechange/Makefile @@ -0,0 +1,78 @@ +# +# BEGIN COPYRIGHT BLOCK +# Copyright 2001 Sun Microsystems, Inc. +# Portions copyright 1999, 2001-2003 Netscape Communications Corporation. +# All rights reserved. +# END COPYRIGHT BLOCK +# +LDAP_SRC = ../../.. +MCOM_ROOT = ../../../../.. + +NOSTDCLEAN=true # don't let nsconfig.mk define target clean +NOSTDSTRIP=true # don't let nsconfig.mk define target strip +NSPR20=true # probably should be defined somewhere else (not sure where) + +OBJDEST = $(OBJDIR)/lib/libstatechange +LIBDIR = $(LIB_RELDIR) + +include $(MCOM_ROOT)/ldapserver/nsdefs.mk +include $(MCOM_ROOT)/ldapserver/nsconfig.mk +include $(LDAP_SRC)/nsldap.mk + +ifeq ($(ARCH), WINNT) +DEF_FILE:=./statechange.def +endif + +STATECHANGE_OBJS = statechange.o +OBJS = $(addprefix $(OBJDEST)/, $(STATECHANGE_OBJS)) + +STATECHANGE_DLL = statechange-plugin + +INCLUDES += -I../../slapd -I../../../include +CFLAGS+=$(SLCFLAGS) -DSLAPD_LOGGING + +ifeq ($(ARCH), WINNT) +EXTRA_LIBS_DEP += $(LIBSLAPD) +EXTRA_LIBS += $(NSPRLINK) $(LIBSLAPD) +STATECHANGE_DLL_OBJ = $(addprefix $(OBJDEST)/, dllmain.o) +endif + +ifeq ($(ARCH), HPUX) +EXTRA_LIBS_DEP += $(LIBSLAPD_DEP) $(LDAPSDK_DEP) $(NSPR_DEP) $(SECURITY_DEP) +EXTRA_LIBS += $(DYN_NSHTTPD) $(ADMINUTIL_LINK) $(LDAPLINK) $(SECURITYLINK) $(NSPRLINK) $(ICULINK) +endif + +ifeq ($(ARCH), AIX) +LD=ld +EXTRA_LIBS += $(LIBSLAPD) +endif + +STATECHANGE= $(addprefix $(LIBDIR)/, $(STATECHANGE_DLL).$(DLL_SUFFIX)) + +clientSDK: + +all: $(OBJDEST) $(LIBDIR) $(STATECHANGE) + +ifeq ($(ARCH), WINNT) +$(STATECHANGE): $(OBJS) $(STATECHANGE_DLL_OBJ) $(DEF_FILE) + $(LINK_DLL) $(STATECHANGE_DLL_OBJ) $(EXTRA_LIBS) /DEF:$(DEF_FILE) +else +$(STATECHANGE): $(OBJS) $(STATECHANGE_DLL_OBJ) + $(LINK_DLL) $(STATECHANGE_DLL_OBJ) $(EXTRA_LIBS) +endif + + +veryclean: clean + +clean: + $(RM) $(OBJS) +ifeq ($(ARCH), WINNT) + $(RM) $(STATECHANGE_DLL_OBJ) +endif + $(RM) $(STATECHANGE) + +$(OBJDEST): + $(MKDIR) $(OBJDEST) + +$(LIBDIR): + $(MKDIR) $(LIBDIR) diff --git a/ldap/servers/plugins/statechange/dllmain.c b/ldap/servers/plugins/statechange/dllmain.c new file mode 100644 index 00000000..fabf8677 --- /dev/null +++ b/ldap/servers/plugins/statechange/dllmain.c @@ -0,0 +1,96 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* + * Microsoft Windows specifics for BACK-LDBM DLL + */ +#include "ldap.h" +#include "lber.h" + + +#ifdef _WIN32 +/* Lifted from Q125688 + * How to Port a 16-bit DLL to a Win32 DLL + * on the MSVC 4.0 CD + */ +BOOL WINAPI DllMain (HANDLE hModule, DWORD fdwReason, LPVOID lpReserved) +{ + WSADATA wsadata; + + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + /* Code from LibMain inserted here. Return TRUE to keep the + DLL loaded or return FALSE to fail loading the DLL. + + You may have to modify the code in your original LibMain to + account for the fact that it may be called more than once. + You will get one DLL_PROCESS_ATTACH for each process that + loads the DLL. This is different from LibMain which gets + called only once when the DLL is loaded. The only time this + is critical is when you are using shared data sections. + If you are using shared data sections for statically + allocated data, you will need to be careful to initialize it + only once. Check your code carefully. + + Certain one-time initializations may now need to be done for + each process that attaches. You may also not need code from + your original LibMain because the operating system may now + be doing it for you. + */ + /* + * 16 bit code calls UnlockData() + * which is mapped to UnlockSegment in windows.h + * in 32 bit world UnlockData is not defined anywhere + * UnlockSegment is mapped to GlobalUnfix in winbase.h + * and the docs for both UnlockSegment and GlobalUnfix say + * ".. function is oboslete. Segments have no meaning + * in the 32-bit environment". So we do nothing here. + */ + + if( errno = WSAStartup(0x0101, &wsadata ) != 0 ) + return FALSE; + + break; + + case DLL_THREAD_ATTACH: + /* Called each time a thread is created in a process that has + already loaded (attached to) this DLL. Does not get called + for each thread that exists in the process before it loaded + the DLL. + + Do thread-specific initialization here. + */ + break; + + case DLL_THREAD_DETACH: + /* Same as above, but called when a thread in the process + exits. + + Do thread-specific cleanup here. + */ + break; + + case DLL_PROCESS_DETACH: + /* Code from _WEP inserted here. This code may (like the + LibMain) not be necessary. Check to make certain that the + operating system is not doing it for you. + */ + WSACleanup(); + + break; + } + /* The return value is only used for DLL_PROCESS_ATTACH; all other + conditions are ignored. */ + return TRUE; // successful DLL_PROCESS_ATTACH +} +#else +int CALLBACK +LibMain( HINSTANCE hinst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine ) +{ + /*UnlockData( 0 );*/ + return( 1 ); +} +#endif diff --git a/ldap/servers/plugins/statechange/statechange.c b/ldap/servers/plugins/statechange/statechange.c new file mode 100644 index 00000000..c0942b41 --- /dev/null +++ b/ldap/servers/plugins/statechange/statechange.c @@ -0,0 +1,450 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +/* plugin which provides a callback mechanism for state changes in the DS */ + +#include <stdio.h> +#include <string.h> +#include "portable.h" +#include "slapi-plugin.h" +#include <dirlite_strings.h> /* PLUGIN_MAGIC_VENDOR_STR */ +#include "dirver.h" +#include "statechange.h" + +/* get file mode flags for unix */ +#ifndef _WIN32 +#include <sys/stat.h> +#endif + +/* the circular list of systems to notify */ +typedef struct _statechange_notify +{ + char *caller_id; + char *dn; + char *filter; + Slapi_Filter *realfilter; + notify_callback func; + void *caller_data; + struct _statechange_notify *next; + struct _statechange_notify *prev; +} SCNotify; + +static SCNotify *head; /* a place to start in the list */ + +#define SCN_PLUGIN_SUBSYSTEM "statechange-plugin" /* used for logging */ + +static void *api[5]; +static Slapi_Mutex *buffer_lock = 0; + +/* other function prototypes */ +int statechange_init( Slapi_PBlock *pb ); +static int statechange_start( Slapi_PBlock *pb ); +static int statechange_close( Slapi_PBlock *pb ); +static int statechange_post_op( Slapi_PBlock *pb, int modtype ); +static int statechange_mod_post_op( Slapi_PBlock *pb ); +static int statechange_modrdn_post_op( Slapi_PBlock *pb ); +static int statechange_add_post_op( Slapi_PBlock *pb ); +static int statechange_delete_post_op( Slapi_PBlock *pb ); +static int _statechange_register(char *caller_id, char *dn, char *filter, void *caller_data, notify_callback func); +static void *_statechange_unregister(char *dn, char *filter, notify_callback func); +static void _statechange_unregister_all(char *caller_id, caller_data_free_callback); +static void _statechange_vattr_cache_invalidator_callback(Slapi_Entry *e, char *dn, int modtype, Slapi_PBlock *pb, void *caller_data); +static SCNotify *statechange_find_notify(char *dn, char *filter, notify_callback func); + + +static Slapi_PluginDesc pdesc = { "statechange", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, + "state change notification service plugin" }; + + +#ifdef _WIN32 +int *module_ldap_debug = 0; + +void plugin_init_debug_level(int *level_ptr) +{ + module_ldap_debug = level_ptr; +} +#endif + + +/* + statechange_init + -------- + adds our callbacks to the list +*/ +int statechange_init( Slapi_PBlock *pb ) +{ + int ret = 0; + + slapi_log_error( SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "--> statechange_init\n"); + + head = 0; + + if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, + SLAPI_PLUGIN_VERSION_01 ) != 0 || + slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, + (void *) statechange_start ) != 0 || + slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, + (void *) statechange_mod_post_op ) != 0 || + slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN, + (void *) statechange_modrdn_post_op ) != 0 || + slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, + (void *) statechange_add_post_op ) != 0 || + slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, + (void *) statechange_delete_post_op ) != 0 || + slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN, + (void *) statechange_close ) != 0 || + slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, + (void *)&pdesc ) != 0 ) + { + slapi_log_error( SLAPI_LOG_FATAL, SCN_PLUGIN_SUBSYSTEM, + "statechange_init: failed to register plugin\n" ); + ret = -1; + } + + slapi_log_error( SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "<-- statechange_init\n"); + return ret; +} + + +/* + statechange_start + --------- + This function publishes the interface for this plugin +*/ +static int statechange_start( Slapi_PBlock *pb ) +{ + int ret = 0; + + slapi_log_error( SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "--> statechange_start\n"); + + api[0] = 0; /* reserved for api broker use, must be zero */ + api[1] = (void *)_statechange_register; + api[2] = (void *)_statechange_unregister; + api[3] = (void *)_statechange_unregister_all; + api[4] = (void *)_statechange_vattr_cache_invalidator_callback; + + if(0 == (buffer_lock = slapi_new_mutex())) /* we never free this mutex */ + { + /* badness */ + slapi_log_error( SLAPI_LOG_FATAL, SCN_PLUGIN_SUBSYSTEM, "statechange: failed to create lock\n"); + ret = -1; + } + else + { + if( slapi_apib_register(StateChange_v1_0_GUID, api) ) + { + slapi_log_error( SLAPI_LOG_FATAL, SCN_PLUGIN_SUBSYSTEM, "statechange: failed to publish state change interface\n"); + ret = -1; + } + } + + head = 0; + + slapi_log_error( SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "<-- statechange_start\n"); + return ret; +} + +/* + statechange_close + --------- + unregisters the interface for this plugin +*/ +static int statechange_close( Slapi_PBlock *pb ) +{ + slapi_log_error( SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "--> statechange_close\n"); + + slapi_apib_unregister(StateChange_v1_0_GUID); + + slapi_log_error( SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "<-- statechange_close\n"); + + return 0; +} + + +static int statechange_mod_post_op( Slapi_PBlock *pb ) +{ + return statechange_post_op(pb, LDAP_CHANGETYPE_MODIFY); +} + +static int statechange_modrdn_post_op( Slapi_PBlock *pb ) +{ + return statechange_post_op(pb, LDAP_CHANGETYPE_MODDN); +} + +static int statechange_add_post_op( Slapi_PBlock *pb ) +{ + return statechange_post_op(pb, LDAP_CHANGETYPE_ADD); +} + +static int statechange_delete_post_op( Slapi_PBlock *pb ) +{ + return statechange_post_op(pb, LDAP_CHANGETYPE_DELETE); +} + + +/* + statechange_post_op + ----------- + Catch all for all post operations that change entries + in some way - evaluate the change against the notification + entries and fire off the relevant callbacks - it is called + from the real postop functions which supply it with the + postop type +*/ +static int statechange_post_op( Slapi_PBlock *pb, int modtype ) +{ + SCNotify *notify = head; + int execute; + char *dn = NULL; + struct slapi_entry *e_before = NULL; + struct slapi_entry *e_after = NULL; + + if(head == 0) + return 0; + + slapi_log_error( SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "--> statechange_post_op\n"); + + /* evaluate this operation against the notification entries */ + + slapi_lock_mutex(buffer_lock); + if(head) + { + if(slapi_pblock_get( pb, SLAPI_TARGET_DN, &dn )) + { + slapi_log_error( SLAPI_LOG_FATAL, SCN_PLUGIN_SUBSYSTEM, "statechange_post_op: failed to get dn of changed entry"); + goto bail; + } + + slapi_dn_normalize( dn ); + + slapi_pblock_get( pb, SLAPI_ENTRY_PRE_OP, &e_before ); + slapi_pblock_get( pb, SLAPI_ENTRY_POST_OP, &e_after ); + + do + { + execute = 0; + + /* first dn */ + if(notify && notify->dn) + { + if(0 != slapi_dn_issuffix(dn, notify->dn)) + execute = 1; + } + else + /* note, if supplied null for everything in the entry *all* ops match */ + if(notify) + execute = 1; + + if(execute && notify->filter) + { + /* next the filter */ + int filter_test = 0; + + /* need to test entry both before and after op */ + if(e_before && !slapi_filter_test_simple( e_before, notify->realfilter)) + filter_test = 1; + + if(!filter_test && e_after && !slapi_filter_test_simple( e_after, notify->realfilter)) + filter_test = 1; + + if(!filter_test) + execute = 0; + } + + if(execute) + { + if(e_after) + (notify->func)(e_after, dn, modtype, pb, notify->caller_data); + else + (notify->func)(e_before, dn, modtype, pb, notify->caller_data); + } + + notify = notify->next; + } + while(notify != head); + } +bail: + slapi_unlock_mutex(buffer_lock); + + slapi_log_error( SLAPI_LOG_TRACE, SCN_PLUGIN_SUBSYSTEM, "<-- statechange_post_op\n"); + return 0; /* always succeed */ +} + + +static int _statechange_register(char *caller_id, char *dn, char *filter, void *caller_data, notify_callback func) +{ + int ret = -1; + SCNotify *item; + + /* simple - we don't check for duplicates */ + + item = (SCNotify*)slapi_ch_malloc(sizeof(SCNotify)); + if(item) + { + char *writable_filter = slapi_ch_strdup(filter); + item->caller_id = slapi_ch_strdup(caller_id); + if(dn) + { + item->dn = slapi_ch_strdup(dn); + slapi_dn_normalize( item->dn ); + } + else + item->dn = 0; + item->filter = slapi_ch_strdup(filter); + item->caller_data = caller_data; + item->realfilter = slapi_str2filter(writable_filter); + item->func = func; + + slapi_lock_mutex(buffer_lock); + if(head == NULL) + { + head = item; + head->next = head; + head->prev = head; + } + else + { + item->next = head; + item->prev = head->prev; + head->prev = item; + item->prev->next = item; + } + slapi_unlock_mutex(buffer_lock); + slapi_ch_free_string(&writable_filter); + + ret = 0; + } + + return ret; +} + +static void *_statechange_unregister(char *dn, char *filter, notify_callback thefunc) +{ + void *ret = NULL; + SCNotify *func = NULL; + + if(buffer_lock == 0) + return ret; + + slapi_lock_mutex(buffer_lock); + + if(func = statechange_find_notify(dn, filter, thefunc)) + { + func->prev->next = func->next; + func->next->prev = func->prev; + + if(func == head) + { + head = func->next; + } + + if(func == head) /* must be the last item, turn off the lights */ + head = 0; + + slapi_ch_free_string(&func->caller_id); + slapi_ch_free_string(&func->dn); + slapi_ch_free_string(&func->filter); + slapi_filter_free( func->realfilter, 1 ); + ret = func->caller_data; + slapi_ch_free((void **)&func); + } + + slapi_unlock_mutex(buffer_lock); + + return ret; +} + +static void _statechange_unregister_all(char *caller_id, caller_data_free_callback callback) +{ + SCNotify *notify = head; + SCNotify *start_notify = head; + + if(buffer_lock == 0) + return; + + slapi_lock_mutex(buffer_lock); + + + if(notify) + { + do + { + SCNotify *notify_next = notify->next; + + if( slapi_utf8casecmp((unsigned char *)caller_id, (unsigned char *)notify->caller_id) ) + { + notify->prev->next = notify->next; + notify->next->prev = notify->prev; + + if(notify == head) + { + head = notify->next; + start_notify = notify->prev; + } + + if(notify == head) /* must be the last item, turn off the lights */ + head = 0; + + if(callback) + callback(notify->caller_data); + slapi_ch_free_string(¬ify->caller_id); + slapi_ch_free_string(¬ify->dn); + slapi_ch_free_string(¬ify->filter); + slapi_filter_free( notify->realfilter, 1 ); + slapi_ch_free((void **)¬ify); + } + + notify = notify_next; + } + while(notify != start_notify && notify != NULL); + } + + slapi_unlock_mutex(buffer_lock); +} + +/* this func needs looking at to make work */ +static SCNotify *statechange_find_notify(char *dn, char *filter, notify_callback func) +{ + SCNotify *notify = head; + SCNotify *start_notify = head; + + if(notify) + { + do + { + if( !slapi_utf8casecmp((unsigned char *)dn, (unsigned char *)notify->dn) && + !slapi_utf8casecmp((unsigned char *)filter, (unsigned char *)notify->filter) && func == notify->func) + { + return notify; + } + + notify = notify->next; + } + while(notify != start_notify); + } + + return 0; +} + +/* intended for use by vattr service providers + * to deal with significant vattr state changes + */ +static void _statechange_vattr_cache_invalidator_callback(Slapi_Entry *e, char *dn, int modtype, Slapi_PBlock *pb, void *caller_data) +{ + /* simply get the significance data and act */ + switch(*(int*)caller_data) + { + case STATECHANGE_VATTR_ENTRY_INVALIDATE: + if(e) + slapi_entry_vattrcache_watermark_invalidate(e); + break; + + case STATECHANGE_VATTR_GLOBAL_INVALIDATE: + default: + slapi_entrycache_vattrcache_watermark_invalidate(); + break; + } +} + diff --git a/ldap/servers/plugins/statechange/statechange.def b/ldap/servers/plugins/statechange/statechange.def new file mode 100644 index 00000000..ed6dca6b --- /dev/null +++ b/ldap/servers/plugins/statechange/statechange.def @@ -0,0 +1,10 @@ +; BEGIN COPYRIGHT BLOCK +; Copyright 2001 Sun Microsystems, Inc. +; Portions copyright 1999, 2001-2003 Netscape Communications Corporation. +; All rights reserved. +; END COPYRIGHT BLOCK +; +DESCRIPTION 'Netscape Directory Server 7.0 State Change Plugin' +EXPORTS + statechange_init @2 + plugin_init_debug_level @3 |
