32bb3fb9d7f3e1d382aafa9425600d9c0bdfb5d2
[ircu2.10.12-pk.git] / ircd / destruct_event.c
1 /*
2  * IRC - Internet Relay Chat, ircd/destruct_event.c
3  * Copyright (C) 2002 Carlo Wood <carlo@alinoe.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 1, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /** @file
20  * @brief Implementation of timed channel destruction events.
21  * @version $Id$
22  */
23 #include "config.h"
24
25 #include "channel.h"    /* destruct_channel */
26 #include "s_debug.h"
27 #include "ircd_alloc.h"
28 #include "ircd.h"
29 #include "ircd_events.h"
30 #include "send.h"
31 #include "msg.h"
32
33 #include <assert.h>
34 #include <stdlib.h>
35
36 /** Structure describing a destruction event. */
37 struct DestructEvent {
38   struct DestructEvent* next_event; /**< Next event in the queue. */
39   struct DestructEvent* prev_event; /**< Previous event in the queue. */
40   time_t expires;                   /**< When the destruction should happen. */
41   struct Channel* chptr;            /**< Channel to destroy. */
42 };
43
44 /** Head of short-delay destruction events.  */
45 static struct DestructEvent* minute_list_top;
46 /** Tail of short-delay destruction events. */
47 static struct DestructEvent* minute_list_bottom;
48 /** Head of long-delay destruction events. */
49 static struct DestructEvent* days_list_top;
50 /** Tail of long-delay destruction events. */
51 static struct DestructEvent* days_list_bottom;
52
53 /** Schedule a short-delay destruction event for \a chptr.
54  * @param[in] chptr Channel to destroy.
55  */
56 void schedule_destruct_event_1m(struct Channel* chptr)
57 {
58   struct DestructEvent* new_event;
59
60   /* Ignore request when we already have a destruct request */
61   if (chptr->destruct_event)
62     return;
63
64   /* Create a new destruct event and add it at the top of the list. */
65   new_event = (struct DestructEvent*)MyMalloc(sizeof(struct DestructEvent));
66   new_event->expires = TStime() + 60;   /* 1 minute from now */
67   new_event->next_event = NULL;
68   new_event->prev_event = minute_list_top;
69   new_event->chptr = chptr;
70
71   if (minute_list_top)
72     minute_list_top->next_event = new_event;
73   minute_list_top = new_event;
74   if (!minute_list_bottom)
75     minute_list_bottom = new_event;
76
77   chptr->destruct_event = new_event;
78 }
79
80 /** Schedule a long-delay destruction event for \a chptr.
81  * @param[in] chptr Channel to destroy.
82  */
83 void schedule_destruct_event_48h(struct Channel* chptr)
84 {
85   struct DestructEvent* new_event;
86
87   /* Ignore request when we already have a destruct request */
88   if (chptr->destruct_event)
89     return;
90
91   /* Create a new destruct event and add it at the top of the list. */
92   new_event = (struct DestructEvent*)MyMalloc(sizeof(struct DestructEvent));
93   new_event->expires = TStime() + 172800;       /* 48 hours from now */
94   new_event->next_event = NULL;
95   new_event->prev_event = days_list_top;
96   new_event->chptr = chptr;
97
98   if (days_list_top)
99     days_list_top->next_event = new_event;
100   days_list_top = new_event;
101   if (!days_list_bottom)
102     days_list_bottom = new_event;
103
104   chptr->destruct_event = new_event;
105 }
106
107 /** Unlink a destruction event for a channel.
108  * @param[in] chptr Channel that is being destroyed early.
109  */
110 void remove_destruct_event(struct Channel* chptr)
111 {
112   struct DestructEvent* event = chptr->destruct_event;
113
114   assert(event != NULL);
115
116   /* unlink event */
117   if (event->prev_event)
118     event->prev_event->next_event = event->next_event;
119   if (event->next_event)
120     event->next_event->prev_event = event->prev_event;
121
122   /* correct top and bottom pointers */
123   if (days_list_top == event)
124     days_list_top = event->prev_event;
125   if (minute_list_top == event)
126     minute_list_top = event->prev_event;
127   if (days_list_bottom == event)
128     days_list_bottom = event->next_event;
129   if (minute_list_bottom == event)
130     minute_list_bottom = event->next_event;
131
132   /* Free memory */
133   MyFree(event);
134
135   chptr->destruct_event = NULL;
136 }
137
138 /** Execute expired channel destruction events.
139  * @param[in] ev Expired timer event (ignored).
140  */
141 void exec_expired_destruct_events(struct Event* ev)
142 {
143   int i = 0;
144   struct DestructEvent** list_bottom;
145   for(list_bottom = &minute_list_bottom; i < 2; ++i, list_bottom = &days_list_bottom)
146   {
147     while (*list_bottom && TStime() >= (*list_bottom)->expires)
148     {
149       struct Channel* chptr = (*list_bottom)->chptr;
150       /* Send DESTRUCT message */
151       sendcmdto_serv_butone(&me, CMD_DESTRUCT, 0, "%s %Tu", chptr->chname, chptr->creationtime);
152       remove_destruct_event(chptr);
153       destruct_channel(chptr);
154     }
155   }
156 }
157