wintest: add option to select the dns backend
[Samba/gebeck_regimport.git] / lib / ccan / likely / likely.c
blob1114efc2077f81895b1cf535cc828fc2aac4c33f
1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2 #ifdef CCAN_LIKELY_DEBUG
3 #include <ccan/likely/likely.h>
4 #include <ccan/hash/hash.h>
5 #include <ccan/htable/htable_type.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 struct trace {
9 const char *condstr;
10 const char *file;
11 unsigned int line;
12 bool expect;
13 unsigned long count, right;
16 static size_t hash_trace(const struct trace *trace)
18 return hash(trace->condstr, strlen(trace->condstr),
19 hash(trace->file, strlen(trace->file),
20 trace->line + trace->expect));
23 static bool trace_eq(const struct trace *t1, const struct trace *t2)
25 return t1->condstr == t2->condstr
26 && t1->file == t2->file
27 && t1->line == t2->line
28 && t1->expect == t2->expect;
31 /* struct thash */
32 HTABLE_DEFINE_TYPE(struct trace, (const struct trace *), hash_trace, trace_eq,
33 thash);
35 static struct thash htable
36 = { HTABLE_INITIALIZER(htable.raw, thash_hash, NULL) };
38 static void init_trace(struct trace *trace,
39 const char *condstr, const char *file, unsigned int line,
40 bool expect)
42 trace->condstr = condstr;
43 trace->file = file;
44 trace->line = line;
45 trace->expect = expect;
46 trace->count = trace->right = 0;
49 static struct trace *add_trace(const struct trace *t)
51 struct trace *trace = malloc(sizeof(*trace));
52 *trace = *t;
53 thash_add(&htable, trace);
54 return trace;
57 long _likely_trace(bool cond, bool expect,
58 const char *condstr,
59 const char *file, unsigned int line)
61 struct trace *p, trace;
63 init_trace(&trace, condstr, file, line, expect);
64 p = thash_get(&htable, &trace);
65 if (!p)
66 p = add_trace(&trace);
68 p->count++;
69 if (cond == expect)
70 p->right++;
72 return cond;
75 static double right_ratio(const struct trace *t)
77 return (double)t->right / t->count;
80 char *likely_stats(unsigned int min_hits, unsigned int percent)
82 struct trace *worst;
83 double worst_ratio;
84 struct thash_iter i;
85 char *ret;
86 struct trace *t;
88 worst = NULL;
89 worst_ratio = 2;
91 /* This is O(n), but it's not likely called that often. */
92 for (t = thash_first(&htable, &i); t; t = thash_next(&htable, &i)) {
93 if (t->count >= min_hits) {
94 if (right_ratio(t) < worst_ratio) {
95 worst = t;
96 worst_ratio = right_ratio(t);
101 if (worst_ratio * 100 > percent)
102 return NULL;
104 ret = malloc(strlen(worst->condstr) +
105 strlen(worst->file) +
106 sizeof(long int) * 8 +
107 sizeof("%s:%u:%slikely(%s) correct %u%% (%lu/%lu)"));
108 sprintf(ret, "%s:%u:%slikely(%s) correct %u%% (%lu/%lu)",
109 worst->file, worst->line,
110 worst->expect ? "" : "un", worst->condstr,
111 (unsigned)(worst_ratio * 100),
112 worst->right, worst->count);
114 thash_del(&htable, worst);
115 free(worst);
117 return ret;
120 void likely_stats_reset(void)
122 struct thash_iter i;
123 struct trace *t;
125 /* This is a bit better than O(n^2), but we have to loop since
126 * first/next during delete is unreliable. */
127 while ((t = thash_first(&htable, &i)) != NULL) {
128 for (; t; t = thash_next(&htable, &i)) {
129 thash_del(&htable, t);
130 free(t);
134 thash_clear(&htable);
136 #endif /*CCAN_LIKELY_DEBUG*/