cscvs to tla changeset 77
[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  * $Id: stats.c,v 1.10 2003/06/04 20:57:13 noodles Exp $
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 #include "getcgi.h"
15 #include "hash.h"
16 #include "keydb.h"
17 #include "ll.h"
18 #include "stats.h"
19
20 /**
21  *      initcolour - Clear the key graph ready for use.
22  *      @parent: Do we want to clear the parent pointers too?
23  *
24  *      Clears the parent and colour information on all elements in the key
25  *      graph.
26  */
27 void initcolour(bool parent)
28 {
29         unsigned long loop;
30         struct ll *curkey;
31
32         /*
33          * Init the colour/parent values. We get each entry list from the hash
34          * table and walk along it, zeroing the values.
35          */
36         for (loop = 0; loop < HASHSIZE; loop++) {
37                 curkey = gethashtableentry(loop);
38                 while (curkey != NULL) {
39                         ((struct stats_key *)curkey->object)->colour = 0;
40                         if (parent) {
41                                 ((struct stats_key *)curkey->object)->parent =
42                                         0;
43                         }
44                         curkey = curkey->next;
45                 }
46         }
47 }
48
49 /**
50  *      findpath - Given 2 keys finds a path between them.
51  *      @have: The key we have.
52  *      @want: The key we want to get to.
53  *
54  *      This does a breadth first search on the key tree, starting with the
55  *      key we have. It returns as soon as a path is found or when we run out
56  *      of keys; whichever comes sooner.
57  */
58 unsigned long findpath(struct stats_key *have, struct stats_key *want)
59 {
60         struct ll *keys = NULL;
61         struct ll *oldkeys = NULL;
62         struct ll *sigs = NULL;
63         struct ll *nextkeys = NULL;
64         long curdegree = 0;
65         long count = 0;
66         
67         curdegree = 1;
68         keys = lladd(NULL, want);
69         oldkeys = keys;
70
71         while (keys != NULL && have->colour == 0) {
72                 sigs = cached_getkeysigs(((struct stats_key *)
73                                         keys->object)->keyid);
74                 while (sigs != NULL && have->colour == 0) {
75                         /*
76                          * Check if we've seen this key before and if not mark
77                          * it and add its sigs to the list we want to look at.
78                          */
79                         if (!((struct stats_key *)sigs->object)->disabled &&
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         cached_getkeysigs(fullhave);
138         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 (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                         printf("Can't find a link from 0x%08llX to 0x%08llX"
166                                 "%s\n",
167                                 have,
168                                 want,
169                                 html ? "<BR>" : "");
170                 } else {
171                         printf("%d steps from 0x%08llX to 0x%08llX%s\n",
172                                 keyinfoa->colour, have & 0xFFFFFFFF,
173                                 want & 0xFFFFFFFF,
174                                 html ? "<BR>" : "");
175                         curkey = keyinfoa;
176                         while (curkey != NULL && curkey->keyid != 0) {
177                                 uid = keyid2uid(curkey->keyid);
178                                 if (html && uid == NULL) {
179                                         printf("<a href=\"lookup?op=get&search="
180                                                 "0x%08llX\">0x%08llX</a> (["
181                                                 "User id not found])%s<BR>\n",
182                                                 curkey->keyid & 0xFFFFFFFF,
183                                                 curkey->keyid & 0xFFFFFFFF,
184                                                 (curkey->keyid == fullwant) ?
185                                                         "" : " signs");
186                                 } else if (html && uid != NULL) {
187                                         printf("<a href=\"lookup?op=get&search="
188                                                 "0x%08llX\">0x%08llX</a>"
189                                                 " (<a href=\"lookup?op=vindex&"
190                                                 "search=0x%08llX\">%s</a>)%s"
191                                                 "<BR>\n",
192                                                 curkey->keyid & 0xFFFFFFFF,
193                                                 curkey->keyid & 0xFFFFFFFF,
194                                                 curkey->keyid & 0xFFFFFFFF,
195                                                 txt2html(uid),
196                                                 (curkey->keyid == fullwant) ?
197                                                 "" : " signs");
198                                 } else {
199                                         printf("0x%08llX (%s)%s\n",
200                                                 curkey->keyid & 0xFFFFFFFF,
201                                                 (uid == NULL) ?
202                                                         "[User id not found]" :
203                                                         uid,
204                                                 (curkey->keyid == fullwant) ?
205                                                 "" : " signs");
206                                 }
207                                 if (uid != NULL) {
208                                         free(uid);
209                                         uid = NULL;
210                                 }
211                                 if (curkey != keyinfoa && curkey != keyinfob) {
212                                         curkey->disabled = true;
213                                 }
214                                 curkey = findinhash(curkey->parent);
215                         }
216                         if (html) {
217                                 puts("<P>List of key ids in path:</P>");
218                         } else {
219                                 puts("List of key ids in path:");
220                         }
221                         curkey = keyinfoa;
222                         while (curkey != NULL && curkey->keyid != 0) {
223                                 printf("0x%08llX ", curkey->keyid & 0xFFFFFFFF);
224                                 curkey = findinhash(curkey->parent);
225                         }
226                         putchar('\n');
227                 }
228                 pathnum++;
229         }
230 }
231
232
233
234 struct stats_key *furthestkey(struct stats_key *have)
235 {
236         unsigned long count = 0;
237         unsigned long curdegree = 0;
238         struct ll *curll, *nextll, *tmp;
239         struct ll *sigs = NULL;
240         struct stats_key *max;
241
242         if (have == NULL) {
243                 return NULL;
244         }
245
246         ++curdegree;
247
248         nextll = NULL;
249         max = have;
250         curll = lladd(NULL, have);
251
252         while (curll != NULL) {
253                 sigs = cached_getkeysigs(((struct stats_key *)
254                                 curll->object)->keyid);
255                 while (sigs != NULL) {
256                         if (((struct stats_key *) sigs->object)->colour == 0) {
257                                 /*
258                                  * We've never seen it. Count it, mark it and
259                                  * explore its subtree.
260                                  */
261                                 count++;
262                                 max = (struct stats_key *)sigs->object;
263                                 ((struct stats_key *)sigs->object)->colour = 
264                                         curdegree;
265                                 ((struct stats_key *)sigs->object)->parent = 
266                                         ((struct stats_key *)
267                                          curll->object)->keyid;
268                                 
269                                 nextll=lladd(nextll, sigs->object);
270                         }
271                         sigs=sigs->next;
272                 }
273                 tmp = curll->next;
274                 free(curll);
275                 curll = tmp;
276                 if (curll == NULL) {
277                         curll = nextll;
278                         nextll = NULL;
279                         ++curdegree;
280                 };
281         }
282
283         return max;
284 }