Omit CVS Id. Update copyright year.
[idzebra-moved-to-github.git] / index / invstat.c
1 /* This file is part of the Zebra server.
2    Copyright (C) 1995-2008 Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 */
19
20
21 #include <stdio.h>
22 #include <assert.h>
23 #include <string.h>
24
25 #include "index.h"
26
27 struct inv_stat_info {
28     ZebraHandle zh;
29     zint no_isam_entries[9];
30     int no_dict_entries;
31     int no_dict_bytes;
32     int isam_bounds[20];
33     int isam_occurrences[20];
34     char tmp[128];
35     int isamb_levels[10][5];
36     zint isamb_sizes[10];
37     zint isamb_blocks[10];
38     unsigned long cksum;
39     int dumpwords;
40 };
41
42 #define SINGLETON_TYPE 8 /* the type to use for singletons that */ 
43                          /* have no block and no block type */
44
45 static void print_dict_item (ZebraHandle zh, const char *s, zint count,
46             int firstsys, int firstseq, int lastsys, int lastseq )
47 {
48     char dst[IT_MAX_WORD+1];
49     int ord;
50     int len = key_SU_decode(&ord, (const unsigned char *) s);
51     const char *index_type;
52     const char *db = 0;
53
54     if (!zh)
55         *dst = '\0';
56     else
57     {
58         zebraExplain_lookup_ord (zh->reg->zei, ord, &index_type, &db, 0);
59
60         zebra_term_untrans(zh, index_type, dst, s + len);
61     }
62     printf("%02d:%10" ZINT_FORMAT0 " %s %d.%d - %d.%d\n", ord, count, dst,
63            firstsys, firstseq, lastsys, lastseq);
64 }
65
66 static int inv_stat_handle (char *name, const char *info, int pos,
67                             void *client)
68 {
69     zint occur = 0;
70     int i = 0;
71     struct inv_stat_info *stat_info = (struct inv_stat_info*) client;
72     ISAM_P isam_p;
73     int firstsys=-1;
74     int firstseq=-1;
75     int lastsys=-1;
76     int lastseq=-1;
77
78     stat_info->no_dict_entries++;
79     stat_info->no_dict_bytes += strlen(name);
80
81     assert (*info == sizeof(ISAM_P));
82     memcpy (&isam_p, info+1, sizeof(ISAM_P));
83
84     if (stat_info->zh->reg->isams)
85     {
86         ISAMS_PP pp;
87         int occurx = 0;
88         struct it_key key;
89
90         pp = isams_pp_open (stat_info->zh->reg->isams, isam_p);
91         occur = isams_pp_num (pp);
92         while (isams_pp_read(pp, &key))
93         {
94             occurx++;
95         }
96         assert (occurx == occur);
97         stat_info->no_isam_entries[0] += occur;
98         isams_pp_close (pp);
99     }
100     if (stat_info->zh->reg->isamc)
101     {
102         ISAMC_PP pp;
103         zint occurx = 0;
104         struct it_key key;
105
106         pp = isamc_pp_open (stat_info->zh->reg->isamc, isam_p);
107         occur = isamc_pp_num (pp);
108         while (isamc_pp_read(pp, &key))
109         {
110             occurx++;
111         }
112         assert (occurx == occur);
113         stat_info->no_isam_entries[isamc_type(isam_p)] += occur;
114         isamc_pp_close (pp);
115     }
116     if (stat_info->zh->reg->isamb)
117     {
118         ISAMB_PP pp;
119         struct it_key key;
120         int cat = CAST_ZINT_TO_INT(isam_p & 3);
121         int level;
122         zint size;
123         zint blocks;
124         
125         pp = isamb_pp_open_x(stat_info->zh->reg->isamb, isam_p, &level, 0);
126
127         while (isamb_pp_read(pp, &key))
128         {
129             occur++;
130         }
131         isamb_pp_close_x (pp, &size, &blocks);
132         stat_info->isamb_blocks[cat] += blocks;
133         stat_info->isamb_sizes[cat] += size;
134         if (level > 4)
135             level = 4;
136         stat_info->isamb_levels[cat][level] ++;
137         stat_info->no_isam_entries[cat] += occur;
138     }
139     i=0;
140     while (occur > stat_info->isam_bounds[i] && stat_info->isam_bounds[i])
141         i++;
142     ++(stat_info->isam_occurrences[i]);
143     if (stat_info->dumpwords)
144         print_dict_item(stat_info->zh, name, occur,
145                         firstsys, firstseq, lastsys, lastseq);
146     return 0;
147 }
148
149 static void show_bfs_stats(BFiles bfs)
150 {
151     int i = 0;
152     const char *directory = 0;
153     double used_bytes, max_bytes;
154     printf("Register:\n");
155     while (bfs_register_directory_stat(bfs, i, &directory,
156                                        &used_bytes, &max_bytes))
157     {
158         printf ("%s %10.0lf %10.0lf\n", directory, used_bytes, max_bytes);
159         i++;
160     }
161     i = 0;
162     printf("Shadow:\n");
163     while (bfs_shadow_directory_stat(bfs, i, &directory,
164                                        &used_bytes, &max_bytes))
165     {
166         printf ("%s %10.0lf %10.0lf\n", directory, used_bytes, max_bytes);
167         i++;
168     }
169 }
170
171 int zebra_register_statistics (ZebraHandle zh, int dumpdict)
172 {
173     int i, prev;
174     int before = 0;
175     zint occur;
176     int after = 1000000000;
177     struct inv_stat_info stat_info;
178     char term_dict[2*IT_MAX_WORD+2];
179
180     if (zebra_begin_read (zh))
181         return 1;
182
183     show_bfs_stats(zebra_get_bfs(zh));
184
185     stat_info.zh = zh;
186     stat_info.dumpwords=dumpdict;
187
188     term_dict[0] = 1;
189     term_dict[1] = 0;
190
191     for (i = 0; i<=SINGLETON_TYPE; i++)
192         stat_info.no_isam_entries[i] = 0;
193     stat_info.no_dict_entries = 0;
194     stat_info.no_dict_bytes = 0;
195     stat_info.isam_bounds[0] = 1;
196     stat_info.isam_bounds[1] = 2;
197     stat_info.isam_bounds[2] = 3;
198     stat_info.isam_bounds[3] = 6;
199     stat_info.isam_bounds[4] = 10;
200     stat_info.isam_bounds[5] = 20;
201     stat_info.isam_bounds[6] = 30;
202     stat_info.isam_bounds[7] = 50;
203     stat_info.isam_bounds[8] = 100;
204     stat_info.isam_bounds[9] = 200;
205     stat_info.isam_bounds[10] = 5000;
206     stat_info.isam_bounds[11] = 10000;
207     stat_info.isam_bounds[12] = 20000;
208     stat_info.isam_bounds[13] = 50000;
209     stat_info.isam_bounds[14] = 100000;
210     stat_info.isam_bounds[15] = 200000;
211     stat_info.isam_bounds[16] = 500000;
212     stat_info.isam_bounds[17] = 1000000;
213     stat_info.isam_bounds[18] = 0;
214
215     stat_info.cksum = 0;
216
217     for (i = 0; i<20; i++)
218         stat_info.isam_occurrences[i] = 0;
219
220     for (i = 0; i<10; i++)
221     {
222         int j;
223         for (j = 0; j<5; j++)
224             stat_info.isamb_levels[i][j] = 0;
225         stat_info.isamb_sizes[i] = 0;
226         stat_info.isamb_blocks[i] = 0;
227     }
228
229     dict_scan (zh->reg->dict, term_dict, &before, &after, &stat_info,
230                inv_stat_handle);
231
232     if (zh->reg->isamc)
233     {
234         fprintf (stdout, "   Blocks    Occur  Size KB   Bytes/Entry\n");
235         for (i = 0; isamc_block_used (zh->reg->isamc, i) >= 0; i++)
236         {
237             fprintf (stdout, " %8" ZINT_FORMAT0 " %8" ZINT_FORMAT0,
238                      isamc_block_used (zh->reg->isamc, i),
239                      stat_info.no_isam_entries[i]);
240
241             if (stat_info.no_isam_entries[i])
242                 fprintf(stdout, " %8d   %f",
243                         (int) ((1023.0 + (double)
244                           isamc_block_used(zh->reg->isamc, i) *
245                           isamc_block_size(zh->reg->isamc,i))/1024),
246                         ((double) isamc_block_used(zh->reg->isamc, i) *
247                           isamc_block_size(zh->reg->isamc,i))/
248                         stat_info.no_isam_entries[i]);
249             fprintf (stdout, "\n");
250         }
251     }
252
253     if (zh->reg->isamb)
254     {
255         for (i = 0; i<4; i++)
256         {
257             int j;
258             int bsize = isamb_block_info(zh->reg->isamb, i);
259             if (bsize < 0)
260                 break;
261             fprintf (stdout, "Category   %d\n", i);
262             fprintf (stdout, "Block size %d\n", bsize);
263             fprintf (stdout, "Blocks:    " ZINT_FORMAT "\n", stat_info.isamb_blocks[i]);
264             fprintf (stdout, "Size:      " ZINT_FORMAT "\n", stat_info.isamb_sizes[i]);
265             fprintf (stdout, "Entries:   " ZINT_FORMAT "\n",
266                      stat_info.no_isam_entries[i]);
267             fprintf (stdout, "Total      " ZINT_FORMAT "\n", stat_info.isamb_blocks[i]*
268                      bsize);
269             for (j = 0; j<5; j++)
270                 if (stat_info.isamb_levels[i][j])
271                     fprintf (stdout, "Level%d     %d\n", j,
272                              stat_info.isamb_levels[i][j]);
273             fprintf (stdout, "\n");
274         }
275     }
276     fprintf (stdout, "Checksum       %08lX\n", stat_info.cksum);
277
278     fprintf (stdout, "Distinct words %d\n", stat_info.no_dict_entries);
279     occur = 0;
280     for (i = 0; i<9; i++)
281         occur += stat_info.no_isam_entries[i];
282     fprintf (stdout, "Word pos       " ZINT_FORMAT "\n", occur);
283     fprintf (stdout, "    Occurrences     Words\n");
284     prev = 1;
285     for (i = 0; stat_info.isam_bounds[i]; i++)
286     {
287         int here = stat_info.isam_bounds[i];
288         fprintf (stdout, "%7d-%-7d %7d\n",
289                  prev, here, stat_info.isam_occurrences[i]);
290         prev = here+1;
291     }
292     fprintf (stdout, "%7d-        %7d\n",
293              prev, stat_info.isam_occurrences[i]);
294     xmalloc_trav("unfreed"); /*! while hunting memory leaks */    
295     zebra_end_read (zh);
296     return 0;
297 }
298
299 /*
300  * Local variables:
301  * c-basic-offset: 4
302  * indent-tabs-mode: nil
303  * End:
304  * vim: shiftwidth=4 tabstop=8 expandtab
305  */
306