1 /* $Id: wip.c 6124 2003-01-14 06:03:29Z rra $
3 ** Routines for keeping track of incoming articles, articles that haven't
4 ** acked from a duplex channel feed, and history caching.
6 ** WIP stands for work-in-progress
12 #include "inn/innconf.h"
15 #define WIPTABLESIZE 1024
16 #define WIP_ARTMAX 300 /* innfeed default max send time */
18 static WIP *WIPtable[WIPTABLESIZE]; /* Top level of the WIP hash table */
23 memset(WIPtable, '\0', sizeof(WIPtable));
26 /* Add a new entry into the table. It is the appilications responsiblity to
27 to call WIPinprogress or WIPbyid first. */
29 WIPnew(const char *messageid, CHANNEL *cp)
35 hash = Hash(messageid, strlen(messageid));
36 memcpy(&bucket, &hash,
37 sizeof(bucket) < sizeof(hash) ? sizeof(bucket) : sizeof(hash));
38 bucket = bucket % WIPTABLESIZE;
40 new = xmalloc(sizeof(WIP));
41 new->MessageID = hash;
42 new->Timestamp = Now.time;
44 /* Link the new entry into the list */
45 new->Next = WIPtable[bucket];
46 WIPtable[bucket] = new;
51 WIPprecomfree(CHANNEL *cp)
58 for (i = 0 ; i < PRECOMMITCACHESIZE ; i++) {
59 cur = cp->PrecommitWIP[i];
60 if (cur != (WIP *)NULL) {
73 /* This is good error checking, but also allows us to
74 WIPfree(WIPbymessageid(id))
75 without having to check if id exists first */
79 memcpy(&bucket, &wp->MessageID,
80 sizeof(bucket) < sizeof(HASH) ? sizeof(bucket) : sizeof(HASH));
81 bucket = bucket % WIPTABLESIZE;
83 for (i = 0 ; i < PRECOMMITCACHESIZE ; i++) {
84 if (wp->Chan->PrecommitWIP[i] == wp) {
85 wp->Chan->PrecommitWIP[i] = (WIP *)NULL;
89 for (cur = WIPtable[bucket]; (cur != NULL) && (cur != wp); prev = cur, cur = cur->Next);
95 WIPtable[bucket] = cur->Next;
97 prev->Next = cur->Next;
99 /* unlink the entry and free the memory */
103 /* Check if the given messageid is being transfered on another channel. If
104 Add is true then add the given message-id to the current channel */
106 WIPinprogress(const char *msgid, CHANNEL *cp, bool Precommit)
111 if ((wp = WIPbyid(msgid)) != NULL) {
112 if(wp->Chan->ArtBeg == 0)
115 i = wp->Chan->ArtMax;
120 if ((Now.time - wp->Timestamp) < (i + innconf->wipcheck))
122 if ((Now.time - wp->Timestamp) > (i + innconf->wipexpire)) {
123 for (i = 0 ; i < PRECOMMITCACHESIZE ; i++) {
124 if (wp->Chan->PrecommitWIP[i] == wp) {
125 wp->Chan->PrecommitWIP[i] = (WIP *)NULL;
130 WIPinprogress(msgid, cp, Precommit);
137 wp = WIPnew(msgid, cp);
139 if (cp->PrecommitiCachenext == PRECOMMITCACHESIZE)
140 cp->PrecommitiCachenext = 0;
141 if (cp->PrecommitWIP[cp->PrecommitiCachenext])
142 WIPfree(cp->PrecommitWIP[cp->PrecommitiCachenext]);
143 cp->PrecommitWIP[cp->PrecommitiCachenext++] = wp;
145 WIPfree(WIPbyhash(cp->CurrentMessageIDHash));
146 cp->CurrentMessageIDHash = wp->MessageID;
152 WIPbyid(const char *messageid)
155 unsigned long bucket;
158 hash = Hash(messageid, strlen(messageid));
159 memcpy(&bucket, &hash,
160 sizeof(bucket) < sizeof(hash) ? sizeof(bucket) : sizeof(hash));
161 bucket = bucket % WIPTABLESIZE;
163 /* Traverse the list until we find a match or find the head again */
164 for (wp = WIPtable[bucket]; wp != NULL; wp = wp->Next)
165 if (!memcmp(&hash, &wp->MessageID, sizeof(HASH)))
172 WIPbyhash(const HASH hash)
174 unsigned long bucket;
177 memcpy(&bucket, &hash,
178 sizeof(bucket) < sizeof(hash) ? sizeof(bucket) : sizeof(hash));
179 bucket = bucket % WIPTABLESIZE;
181 /* Traverse the list until we find a match or find the head again */
182 for (wp = WIPtable[bucket]; wp != NULL; wp = wp->Next)
183 if (!memcmp(&hash, &wp->MessageID, sizeof(HASH)))