First cut at cleanup infrastructure.
[onak.git] / stats.c
1 /*
2  * stats.c - various routines to do stats on the key graph
3  *
4  * Jonathan McDowell <noodles@earth.li>
5  *
6  * Copyright 2000-2002 Project Purple
7  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 #include "cleanup.h"
13 #include "getcgi.h"
14 #include "hash.h"
15 #include "keydb.h"
16 #include "ll.h"
17 #include "stats.h"
18
19 /**
20  *      initcolour - Clear the key graph ready for use.
21  *      @parent: Do we want to clear the parent pointers too?
22  *
23  *      Clears the parent and colour information on all elements in the key
24  *      graph.
25  */
26 void initcolour(bool parent)
27 {
28         unsigned int loop;
29         struct ll *curkey;
30
31         /*
32          * Init the colour/parent values. We get each entry list from the hash
33          * table and walk along it, zeroing the values.
34          */
35         for (loop = 0; loop < HASHSIZE; loop++) {
36                 curkey = gethashtableentry(loop);
37                 while (curkey != NULL) {
38                         ((struct stats_key *)curkey->object)->colour = 0;
39                         if (parent) {
40                                 ((struct stats_key *)curkey->object)->parent =
41                                         0;
42                         }
43                         curkey = curkey->next;
44                 }
45         }
46 }
47
48 /**
49  *      findpath - Given 2 keys finds a path between them.
50  *      @have: The key we have.
51  *      @want: The key we want to get to.
52  *
53  *      This does a breadth first search on the key tree, starting with the
54  *      key we have. It returns as soon as a path is found or when we run out
55  *      of keys; whichever comes sooner.
56  */
57 unsigned long findpath(struct stats_key *have, struct stats_key *want)
58 {
59         struct ll *keys = NULL;
60         struct ll *oldkeys = NULL;
61         struct ll *sigs = NULL;
62         struct ll *nextkeys = NULL;
63         long curdegree = 0;
64         unsigned long count = 0;
65         
66         curdegree = 1;
67         keys = lladd(NULL, want);
68         oldkeys = keys;
69
70         while ((!cleanup()) && keys != NULL && have->colour == 0) {
71                 sigs = cached_getkeysigs(((struct stats_key *)
72                                         keys->object)->keyid);
73                 while ((!cleanup()) && sigs != NULL && have->colour == 0) {
74                         /*
75                          * Check if we've seen this key before and if not mark
76                          * it and add its sigs to the list we want to look at.
77                          */
78                         if (!((struct stats_key *)sigs->object)->disabled &&
79                             !((struct stats_key *)sigs->object)->revoked &&
80                             ((struct stats_key *)sigs->object)->colour == 0) {
81                                 count++;
82                                 ((struct stats_key *)sigs->object)->colour =
83                                         curdegree;
84                                 ((struct stats_key *)sigs->object)->parent =
85                                         ((struct stats_key *)
86                                          keys->object)->keyid;
87                                 nextkeys = lladd(nextkeys, sigs->object);
88                         }
89                         sigs = sigs->next;
90                 }
91                 keys = keys->next;
92                 if (keys == NULL) {
93                         keys = nextkeys;
94                         llfree(oldkeys, NULL);
95                         oldkeys = keys;
96                         nextkeys = NULL;
97                         curdegree++;
98                 }
99         }
100         if (oldkeys != NULL) {
101                 llfree(oldkeys, NULL);
102                 oldkeys = NULL;
103         }
104         if (nextkeys != NULL) {
105                 llfree(nextkeys, NULL);
106                 nextkeys = NULL;
107         }
108
109         return count;
110 }
111
112 /**
113  *      dofindpath - Given 2 keys displays a path between them.
114  *      @have: The key we have.
115  *      @want: The key we want to get to.
116  *      @html: Should we output in html.
117  *      @count: How many paths we should look for.
118  *
119  *      This does a breadth first search on the key tree, starting with the
120  *      key we have. It returns as soon as a path is found or when we run out
121  *      of keys; whichever comes sooner.
122  */
123 void dofindpath(uint64_t have, uint64_t want, bool html, int count)
124 {
125         struct stats_key *keyinfoa, *keyinfob, *curkey;
126         uint64_t fullhave, fullwant;
127         int rec;
128         int pathnum;
129         char *uid;
130
131         fullhave = getfullkeyid(have);
132         fullwant = getfullkeyid(want);
133
134         /*
135          * Make sure the keys we have and want are in the cache.
136          */
137         (void) cached_getkeysigs(fullhave);
138         (void) cached_getkeysigs(fullwant);
139
140         if ((keyinfoa = findinhash(fullhave)) == NULL) {
141                 printf("Couldn't find key 0x%llX.\n", have);
142                 return;
143         }
144         if ((keyinfob = findinhash(fullwant)) == NULL) {
145                 printf("Couldn't find key 0x%llX.\n", want);
146                 return;
147         }
148
149         pathnum = 0;
150         
151         while ((!cleanup()) && (pathnum < count)) {
152                 /*
153                  * Fill the tree info up.
154                  */
155                 initcolour(true);
156                 rec = findpath(keyinfoa, keyinfob);
157                 keyinfob->parent = 0;
158
159                 printf("%s%d nodes examined. %ld elements in the hash%s\n",
160                         html ? "<HR>" : "",
161                         rec,
162                         hashelements(),
163                         html ? "<BR>" : "");
164                 if (keyinfoa->colour == 0) {
165                         if (pathnum == 0) {
166                                 printf("Can't find a link from 0x%08llX to "
167                                 "0x%08llX%s\n",
168                                 have,
169                                 want,
170                                 html ? "<BR>" : "");
171                         } else {
172                                 printf("Can't find any further paths%s\n",
173                                         html ? "<BR>" : "");
174                         }
175                         pathnum = count;
176                 } else {
177                         printf("%d steps from 0x%08llX to 0x%08llX%s\n",
178                                 keyinfoa->colour, have & 0xFFFFFFFF,
179                                 want & 0xFFFFFFFF,
180                                 html ? "<BR>" : "");
181                         curkey = keyinfoa;
182                         while (curkey != NULL && curkey->keyid != 0) {
183                                 uid = keyid2uid(curkey->keyid);
184                                 if (html && uid == NULL) {
185                                         printf("<a href=\"lookup?op=get&search="
186                                                 "0x%08llX\">0x%08llX</a> (["
187                                                 "User id not found])%s<BR>\n",
188                                                 curkey->keyid & 0xFFFFFFFF,
189                                                 curkey->keyid & 0xFFFFFFFF,
190                                                 (curkey->keyid == fullwant) ?
191                                                         "" : " signs");
192                                 } else if (html && uid != NULL) {
193                                         printf("<a href=\"lookup?op=get&search="
194                                                 "0x%08llX\">0x%08llX</a>"
195                                                 " (<a href=\"lookup?op=vindex&"
196                                                 "search=0x%08llX\">%s</a>)%s"
197                                                 "<BR>\n",
198                                                 curkey->keyid & 0xFFFFFFFF,
199                                                 curkey->keyid & 0xFFFFFFFF,
200                                                 curkey->keyid & 0xFFFFFFFF,
201                                                 txt2html(uid),
202                                                 (curkey->keyid == fullwant) ?
203                                                 "" : " signs");
204                                 } else {
205                                         printf("0x%08llX (%s)%s\n",
206                                                 curkey->keyid & 0xFFFFFFFF,
207                                                 (uid == NULL) ?
208                                                         "[User id not found]" :
209                                                         uid,
210                                                 (curkey->keyid == fullwant) ?
211                                                 "" : " signs");
212                                 }
213                                 if (uid != NULL) {
214                                         free(uid);
215                                         uid = NULL;
216                                 }
217                                 if (curkey != keyinfoa && curkey != keyinfob) {
218                                         curkey->disabled = true;
219                                 }
220                                 curkey = findinhash(curkey->parent);
221                         }
222                         if (html) {
223                                 puts("<P>List of key ids in path:</P>");
224                         } else {
225                                 puts("List of key ids in path:");
226                         }
227                         curkey = keyinfoa;
228                         while (curkey != NULL && curkey->keyid != 0) {
229                                 printf("0x%08llX ", curkey->keyid & 0xFFFFFFFF);
230                                 curkey = findinhash(curkey->parent);
231                         }
232                         putchar('\n');
233                 }
234                 pathnum++;
235         }
236 }
237
238
239
240 struct stats_key *furthestkey(struct stats_key *have)
241 {
242         unsigned long count = 0;
243         unsigned long curdegree = 0;
244         struct ll *curll, *nextll, *tmp;
245         struct ll *sigs = NULL;
246         struct stats_key *max;
247
248         if (have == NULL) {
249                 return NULL;
250         }
251
252         ++curdegree;
253
254         nextll = NULL;
255         max = have;
256         curll = lladd(NULL, have);
257
258         while (curll != NULL) {
259                 sigs = cached_getkeysigs(((struct stats_key *)
260                                 curll->object)->keyid);
261                 while (sigs != NULL) {
262                         if (((struct stats_key *) sigs->object)->colour == 0) {
263                                 /*
264                                  * We've never seen it. Count it, mark it and
265                                  * explore its subtree.
266                                  */
267                                 count++;
268                                 max = (struct stats_key *)sigs->object;
269                                 ((struct stats_key *)sigs->object)->colour = 
270                                         curdegree;
271                                 ((struct stats_key *)sigs->object)->parent = 
272                                         ((struct stats_key *)
273                                          curll->object)->keyid;
274                                 
275                                 nextll=lladd(nextll, sigs->object);
276                         }
277                         sigs=sigs->next;
278                 }
279                 tmp = curll->next;
280                 free(curll);
281                 curll = tmp;
282                 if (curll == NULL) {
283                         curll = nextll;
284                         nextll = NULL;
285                         ++curdegree;
286                 };
287         }
288
289         return max;
290 }