s3:registry: do not use regdb functions during db upgrade
[Samba/gebeck_regimport.git] / lib / ccan / likely / likely.c
blobfaa2bd8eb8fe22e3c8d85df77883b6550008368c
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.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 static struct htable *htable;
10 struct trace {
11 const char *condstr;
12 const char *file;
13 unsigned int line;
14 bool expect;
15 unsigned long count, right;
18 /* We hash the pointers, which will be identical for same call. */
19 static unsigned long hash_trace(const struct trace *trace)
21 return hash_pointer(trace->condstr,
22 hash_pointer(trace->file,
23 trace->line + trace->expect));
26 static bool hash_cmp(const void *htelem, void *cmpdata)
28 const struct trace *t1 = htelem, *t2 = cmpdata;
29 return t1->condstr == t2->condstr
30 && t1->file == t2->file
31 && t1->line == t2->line
32 && t1->expect == t2->expect;
35 static size_t rehash(const void *elem, void *priv)
37 return hash_trace(elem);
40 static void init_trace(struct trace *trace,
41 const char *condstr, const char *file, unsigned int line,
42 bool expect)
44 trace->condstr = condstr;
45 trace->file = file;
46 trace->line = line;
47 trace->expect = expect;
48 trace->count = trace->right = 0;
51 static struct trace *add_trace(const char *condstr,
52 const char *file, unsigned int line, bool expect)
54 struct trace *trace = malloc(sizeof(*trace));
55 init_trace(trace, condstr, file, line, expect);
56 htable_add(htable, hash_trace(trace), trace);
57 return trace;
60 long _likely_trace(bool cond, bool expect,
61 const char *condstr,
62 const char *file, unsigned int line)
64 struct trace *p, trace;
66 if (!htable)
67 htable = htable_new(rehash, NULL);
69 init_trace(&trace, condstr, file, line, expect);
70 p = htable_get(htable, hash_trace(&trace), hash_cmp, &trace);
71 if (!p)
72 p = add_trace(condstr, file, line, expect);
74 p->count++;
75 if (cond == expect)
76 p->right++;
78 return cond;
81 struct get_stats_info {
82 struct trace *worst;
83 unsigned int min_hits;
84 double worst_ratio;
87 static double right_ratio(const struct trace *t)
89 return (double)t->right / t->count;
92 static void get_stats(struct trace *trace, struct get_stats_info *info)
94 if (trace->count < info->min_hits)
95 return;
97 if (right_ratio(trace) < info->worst_ratio) {
98 info->worst = trace;
99 info->worst_ratio = right_ratio(trace);
103 const char *likely_stats(unsigned int min_hits, unsigned int percent)
105 struct get_stats_info info;
106 struct htable_iter i;
107 char *ret;
108 struct trace *trace;
110 if (!htable)
111 return NULL;
113 info.min_hits = min_hits;
114 info.worst = NULL;
115 info.worst_ratio = 2;
117 /* This is O(n), but it's not likely called that often. */
118 for (trace = htable_first(htable, &i);
119 trace;
120 trace = htable_next(htable,&i)) {
121 get_stats(trace, &info);
124 if (info.worst_ratio * 100 > percent)
125 return NULL;
127 ret = malloc(strlen(info.worst->condstr) +
128 strlen(info.worst->file) +
129 sizeof(long int) * 8 +
130 sizeof("%s:%u:%slikely(%s) correct %u%% (%lu/%lu)"));
131 sprintf(ret, "%s:%u:%slikely(%s) correct %u%% (%lu/%lu)",
132 info.worst->file, info.worst->line,
133 info.worst->expect ? "" : "un", info.worst->condstr,
134 (unsigned)(info.worst_ratio * 100),
135 info.worst->right, info.worst->count);
137 htable_del(htable, hash_trace(info.worst), info.worst);
138 free(info.worst);
140 return ret;
142 #endif /*CCAN_LIKELY_DEBUG*/