* Added a new DeleteFunctionHook type of thing. These get called when a
authorArt Cancro <ajc@citadel.org>
Wed, 30 Jan 2002 19:03:42 +0000 (19:03 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 30 Jan 2002 19:03:42 +0000 (19:03 +0000)
  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.

citadel/ChangeLog
citadel/dynloader.c
citadel/dynloader.h
citadel/msgbase.c
citadel/server.h

index 81f25561e1bf7a65e1c74d7ae378b4933e70cf9b..77d5a415cfdf96ba86701da482478605504f6bab 100644 (file)
@@ -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 <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import 
-
index 6647fee2c479fd3c84191688e3ae26edd4dfa2b1..5842971d154d1ae4eaa38243c1e557b57e5a4a99 100644 (file)
@@ -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)
 {
index 23ac0ce807ecef616b671419a77e5764f61c0fa5..737384a352301efcd6e2710190524229bcbeaeef 100644 (file)
@@ -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));
index d8e7609560518340db9c87df93f66a9c8dc61378..468b7079593f0ed533fc2aff4e4da4dd1378b11e 100644 (file)
@@ -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<num_deleted; ++i) {
+               PerformDeleteHooks(qrbuf.QRname, dellist[i]);
+               AdjRefCount(dellist[i], -1);
+       }
+
+       /* Now free the memory we used, and go away. */
+       if (msglist != NULL) phree(msglist);
+       if (dellist != NULL) phree(dellist);
        lprintf(9, "%d message(s) deleted.\n", num_deleted);
        return (num_deleted);
 }
index ddfd9c3878c5dc2855cf756c99d0fe30615373b5..d1df876828b79f4fad8a8efc8500e11607e74a6f 100644 (file)
@@ -347,6 +347,16 @@ struct NetprocFunctionHook {
 extern DLEXP struct NetprocFunctionHook *NetprocHookTable;
 
 
+/*
+ * DeleteFunctionHook extensions are used for hooks which get called when a
+ * message is about to be deleted.
+ */
+struct DeleteFunctionHook {
+       struct DeleteFunctionHook *next;
+       int (*h_function_pointer) (char *target_room, long msgnum);
+};
+extern DLEXP struct DeleteFunctionHook *DeleteHookTable;
+
 
 /*
  * ExpressMessageFunctionHook extensions are used for hooks which implement