From: Art Cancro Date: Wed, 30 Jan 2002 19:03:42 +0000 (+0000) Subject: * Added a new DeleteFunctionHook type of thing. These get called when a X-Git-Tag: v7.86~6565 X-Git-Url: https://code.citadel.org/?a=commitdiff_plain;h=de59f59473d502fcbd4e873260511a8ab2273f47;p=citadel.git * Added a new DeleteFunctionHook type of thing. These get called when a message is being deleted from a room. * When deleting messages from a room, do the AdjRefCount() calls (and now, the PerformDeleteHooks() calls) in a second pass. This keeps that stuff outside of the S_QUICKROOM critical section. --- diff --git a/citadel/ChangeLog b/citadel/ChangeLog index 81f25561e..77d5a415c 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,4 +1,11 @@ $Log$ + Revision 590.95 2002/01/30 19:03:41 ajc + * Added a new DeleteFunctionHook type of thing. These get called when a + message is being deleted from a room. + * When deleting messages from a room, do the AdjRefCount() calls (and now, + the PerformDeleteHooks() calls) in a second pass. This keeps that stuff + outside of the S_QUICKROOM critical section. + Revision 590.94 2002/01/27 06:39:45 error * file_ops.c: fixed bug in cmd_read() which could cause server to report the wrong number of bytes for the client to download @@ -3267,4 +3274,3 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant Fri Jul 10 1998 Art Cancro * Initial CVS import - diff --git a/citadel/dynloader.c b/citadel/dynloader.c index 6647fee2c..5842971d1 100644 --- a/citadel/dynloader.c +++ b/citadel/dynloader.c @@ -47,6 +47,7 @@ struct UserFunctionHook *UserHookTable = NULL; struct XmsgFunctionHook *XmsgHookTable = NULL; struct MessageFunctionHook *MessageHookTable = NULL; struct NetprocFunctionHook *NetprocHookTable = NULL; +struct DeleteFunctionHook *DeleteHookTable = NULL; struct ServiceFunctionHook *ServiceHookTable = NULL; struct ProtoFunctionHook { @@ -398,6 +399,40 @@ void CtdlUnregisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) ) } +void CtdlRegisterDeleteHook(int (*handler)(char *, long) ) +{ + struct DeleteFunctionHook *newfcn; + + newfcn = (struct DeleteFunctionHook *) + mallok(sizeof(struct DeleteFunctionHook)); + newfcn->next = DeleteHookTable; + newfcn->h_function_pointer = handler; + DeleteHookTable = newfcn; + + lprintf(5, "Registered a new netproc function\n"); +} + + +void CtdlUnregisterDeleteHook(int (*handler)(char *, long) ) +{ + struct DeleteFunctionHook *cur, *p; + + for (cur = DeleteHookTable; cur != NULL; cur = cur->next) { + /* This will also remove duplicates if any */ + while (cur != NULL && + handler == cur->h_function_pointer ) { + lprintf(5, "Unregistered netproc function\n"); + p = cur->next; + if (cur == DeleteHookTable) { + DeleteHookTable = p; + } + phree(cur); + cur = p; + } + } +} + + void CtdlRegisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order) { @@ -595,6 +630,16 @@ int PerformNetprocHooks(struct CtdlMessage *msg, char *target_room) } +void PerformDeleteHooks(char *room, long msgnum) +{ + struct DeleteFunctionHook *fcn; + + for (fcn = DeleteHookTable; fcn != NULL; fcn = fcn->next) { + (*fcn->h_function_pointer) (room, msgnum); + } +} + + int PerformXmsgHooks(char *sender, char *recp, char *msg) { diff --git a/citadel/dynloader.h b/citadel/dynloader.h index 23ac0ce80..737384a35 100644 --- a/citadel/dynloader.h +++ b/citadel/dynloader.h @@ -37,6 +37,10 @@ void CtdlRegisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) ); void CtdlUnregisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) ); int PerformNetprocHooks(struct CtdlMessage *, char *); +void CtdlRegisterDeleteHook(int (*handler)(char *, long) ); +void CtdlUnregisterDeleteHook(int (*handler)(char *, long) ); +void PerformDeleteHooks(char *, long); + void CtdlRegisterCleanupHook(void (*fcn_ptr)(void)); void CtdlUnregisterCleanupHook(void (*fcn_ptr)(void)); diff --git a/citadel/msgbase.c b/citadel/msgbase.c index d8e760956..468b70795 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -2472,6 +2472,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ struct quickroom qrbuf; struct cdbdata *cdbfr; long *msglist = NULL; + long *dellist = NULL; int num_msgs = 0; int i; int num_deleted = 0; @@ -2491,6 +2492,7 @@ int CtdlDeleteMessages(char *room_name, /* which room */ if (cdbfr != NULL) { msglist = mallok(cdbfr->len); + dellist = mallok(cdbfr->len); memcpy(msglist, cdbfr->ptr, cdbfr->len); num_msgs = cdbfr->len / sizeof(long); cdb_free(cdbfr); @@ -2516,9 +2518,8 @@ int CtdlDeleteMessages(char *room_name, /* which room */ /* Delete message only if all bits are set */ if (delete_this == 0x03) { - AdjRefCount(msglist[i], -1); + dellist[num_deleted++] = msglist[i]; msglist[i] = 0L; - ++num_deleted; } } @@ -2527,9 +2528,25 @@ int CtdlDeleteMessages(char *room_name, /* which room */ msglist, (num_msgs * sizeof(long))); qrbuf.QRhighest = msglist[num_msgs - 1]; - phree(msglist); } lputroom(&qrbuf); + + /* Go through the messages we pulled out of the index, and decrement + * their reference counts by 1. If this is the only room the message + * was in, the reference count will reach zero and the message will + * automatically be deleted from the database. We do this in a + * separate pass because there might be plug-in hooks getting called, + * and we don't want that happening during an S_QUICKROOM critical + * section. + */ + if (num_deleted) for (i=0; i