summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/man/lh_new.3
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/man/lh_new.3')
-rw-r--r--src/lib/libcrypto/man/lh_new.3430
1 files changed, 430 insertions, 0 deletions
diff --git a/src/lib/libcrypto/man/lh_new.3 b/src/lib/libcrypto/man/lh_new.3
new file mode 100644
index 0000000000..2779cf9202
--- /dev/null
+++ b/src/lib/libcrypto/man/lh_new.3
@@ -0,0 +1,430 @@
1.Dd $Mdocdate: November 12 2015 $
2.Dt LH_NEW 3
3.Os
4.Sh NAME
5.Nm lh_new ,
6.Nm lh_free ,
7.Nm lh_insert ,
8.Nm lh_delete ,
9.Nm lh_retrieve ,
10.Nm lh_doall ,
11.Nm lh_doall_arg ,
12.Nm lh_error
13.Nd dynamic hash table
14.Sh SYNOPSIS
15.In openssl/lhash.h
16.Fn DECLARE_LHASH_OF <type>
17.Ft LHASH *
18.Fn lh_<type>_new void
19.Ft void
20.Fo lh_<type>_free
21.Fa "LHASH_OF(<type>) *table"
22.Fc
23.Ft <type> *
24.Fo lh_<type>_insert
25.Fa "LHASH_OF(<type>) *table"
26.Fa "<type> *data"
27.Fc
28.Ft <type> *
29.Fo lh_<type>_delete
30.Fa "LHASH_OF(<type>) *table"
31.Fa "<type> *data"
32.Fc
33.Ft <type> *
34.Fo lh_<type>_retrieve
35.Fa "LHASH_OF<type>) *table"
36.Fa "<type> *data"
37.Fc
38.Ft void
39.Fo lh_<type>_doall
40.Fa "LHASH_OF(<type>) *table"
41.Fa "LHASH_DOALL_FN_TYPE func"
42.Fc
43.Ft void
44.Fo lh_<type>_doall_arg
45.Fa "LHASH_OF(<type>) *table"
46.Fa "LHASH_DOALL_ARG_FN_TYPE func"
47.Fa "<type2>"
48.Fa "<type2> *arg"
49.Fc
50.Ft int
51.Fo lh_<type>_error
52.Fa "LHASH_OF(<type>) *table"
53.Fc
54.Ft typedef int
55.Fo (*LHASH_COMP_FN_TYPE)
56.Fa "const void *"
57.Fa "const void *"
58.Fc
59.Ft typedef unsigned long
60.Fo (*LHASH_HASH_FN_TYPE)
61.Fa "const void *"
62.Fc
63.Ft typedef void
64.Fo (*LHASH_DOALL_FN_TYPE)
65.Fa "const void *"
66.Fc
67.Ft typedef void
68.Fo (*LHASH_DOALL_ARG_FN_TYPE)
69.Fa "const void *"
70.Fa "const void *"
71.Fc
72.Sh DESCRIPTION
73This library implements type-checked dynamic hash tables.
74The hash table entries can be arbitrary structures.
75Usually they consist of key and value fields.
76.Pp
77.Fn lh_<type>_new
78creates a new
79.Vt LHASH_OF(<type>)
80structure to store arbitrary data entries, and provides the hash and
81compare callbacks to be used in organising the table's entries.
82The hash callback takes a pointer to a table entry as its argument
83and returns an unsigned long hash value for its key field.
84The hash value is normally truncated to a power of 2, so make sure that
85your hash function returns well mixed low order bits.
86The compare callback takes two arguments (pointers to two hash table
87entries), and returns 0 if their keys are equal, non-zero otherwise.
88If your hash table will contain items of some particular type and the
89hash and compare callbacks hash and compare these types, then the
90.Fn DECLARE_LHASH_HASH_FN
91and
92.Fn IMPLEMENT_LHASH_COMP_FN
93macros can be used to create callback wrappers of the prototypes
94required by
95.Fn lh_<type>_new .
96These provide per-variable casts before calling the type-specific
97callbacks written by the application author.
98These macros, as well as those used for the doall callbacks, are
99defined as;
100.Bd -literal -offset 2n
101#define DECLARE_LHASH_HASH_FN(name, o_type) \e
102 unsigned long name##_LHASH_HASH(const void *);
103#define IMPLEMENT_LHASH_HASH_FN(name, o_type) \e
104 unsigned long name##_LHASH_HASH(const void *arg) { \e
105 const o_type *a = arg; \e
106 return name##_hash(a); }
107#define LHASH_HASH_FN(name) name##_LHASH_HASH
108
109#define DECLARE_LHASH_COMP_FN(name, o_type) \e
110 int name##_LHASH_COMP(const void *, const void *);
111#define IMPLEMENT_LHASH_COMP_FN(name, o_type) \e
112 int name##_LHASH_COMP(const void *arg1, const void *arg2) { \e
113 const o_type *a = arg1; \e
114 const o_type *b = arg2; \e
115 return name##_cmp(a,b); }
116#define LHASH_COMP_FN(name) name##_LHASH_COMP
117
118#define DECLARE_LHASH_DOALL_FN(name, o_type) \e
119 void name##_LHASH_DOALL(void *);
120#define IMPLEMENT_LHASH_DOALL_FN(name, o_type) \e
121 void name##_LHASH_DOALL(void *arg) { \e
122 o_type *a = arg; \e
123 name##_doall(a); }
124#define LHASH_DOALL_FN(name) name##_LHASH_DOALL
125
126#define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \e
127 void name##_LHASH_DOALL_ARG(void *, void *);
128#define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \e
129 void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \e
130 o_type *a = arg1; \e
131 a_type *b = arg2; \e
132 name##_doall_arg(a, b); }
133#define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG
134.Ed
135.Pp
136An example of a hash table storing (pointers to) structures of type
137\&'STUFF' could be defined as follows;
138.Bd -literal -offset 2n
139/* Calculate the hash value of 'tohash' (implemented elsewhere) */
140unsigned long STUFF_hash(const STUFF *tohash);
141/* Order 'arg1' and 'arg2' (implemented elsewhere) */
142int stuff_cmp(const STUFF *arg1, const STUFF *arg2);
143/* Create type-safe wrapper functions for use in the LHASH internals */
144static IMPLEMENT_LHASH_HASH_FN(stuff, STUFF);
145static IMPLEMENT_LHASH_COMP_FN(stuff, STUFF);
146/* ... */
147int main(int argc, char *argv[]) {
148 /* Create the new hash table using the hash/compare wrappers */
149 LHASH_OF(STUFF) *hashtable =
150 lh_STUFF_new(LHASH_HASH_FN(STUFF_hash),
151 LHASH_COMP_FN(STUFF_cmp));
152 /* ... */
153}
154.Ed
155.Pp
156.Fn lh_<type>_free
157frees the
158.Vt LHASH_OF(<type>)
159structure
160.Fa table .
161Allocated hash table entries will not be freed; consider using
162.Fn lh_<type>_doall
163to deallocate any remaining entries in the hash table (see below).
164.Pp
165.Fn lh_<type>_insert
166inserts the structure pointed to by
167.Fa data
168into
169.Fa table .
170If there already is an entry with the same key, the old value is
171replaced.
172Note that
173.Fn lh_<type>_insert
174stores pointers, the data are not copied.
175.Pp
176.Fn lh_<type>_delete
177deletes an entry from
178.Fa table .
179.Pp
180.Fn lh_<type>_retrieve
181looks up an entry in
182.Fa table .
183Normally,
184.Fa data
185is a structure with the key field(s) set; the function will return a
186pointer to a fully populated structure.
187.Pp
188.Fn lh_<type>_doall
189will, for every entry in the hash table, call
190.Fa func
191with the data item as its parameter.
192For
193.Fn lh_<type>_doall
194and
195.Fn lh_<type>_doall_arg ,
196function pointer casting should be avoided in the callbacks (see
197.Sx NOTES )
198\(em instead use the declare/implement macros to create type-checked
199wrappers that cast variables prior to calling your type-specific
200callbacks.
201An example of this is illustrated here where the callback is used to
202cleanup resources for items in the hash table prior to the hashtable
203itself being deallocated:
204.Bd -literal -offset 2n
205/* Clean up resources belonging to 'a' (this is implemented elsewhere) */
206void STUFF_cleanup_doall(STUFF *a);
207/* Implement a prototype-compatible wrapper for "STUFF_cleanup" */
208IMPLEMENT_LHASH_DOALL_FN(STUFF_cleanup, STUFF)
209 /* ... then later in the code ... */
210/* So to run "STUFF_cleanup" against all items in a hash table ... */
211lh_STUFF_doall(hashtable, LHASH_DOALL_FN(STUFF_cleanup));
212/* Then the hash table itself can be deallocated */
213lh_STUFF_free(hashtable);
214.Ed
215.Pp
216When doing this, be careful if you delete entries from the hash table in
217your callbacks: the table may decrease in size, moving the item that you
218are currently on down lower in the hash table \(em this could cause some
219entries to be skipped during the iteration.
220The second best solution to this problem is to set hash->down_load=0
221before you start (which will stop the hash table ever decreasing in
222size).
223The best solution is probably to avoid deleting items from the hash
224table inside a doall callback!
225.Pp
226.Fn lh_<type>_doall_arg
227is the same as
228.Fn lh_<type>_doall
229except that
230.Fa func
231will be called with
232.Fa arg
233as the second argument and
234.Fa func
235should be of type
236.Vt LHASH_DOALL_ARG_FN_TYPE
237(a callback prototype that is passed both the table entry and an extra
238argument).
239As with
240.Fn lh_<type>_doall ,
241you can instead choose to declare your callback with a prototype
242matching the types you are dealing with and use the declare/implement
243macros to create compatible wrappers that cast variables before calling
244your type-specific callbacks.
245An example of this is demonstrated here (printing all hash table entries
246to a BIO that is provided by the caller):
247.Bd -literal -offset 2n
248/* Print item 'a' to 'output_bio' (this is implemented elsewhere) */
249void STUFF_print_doall_arg(const STUFF *a, BIO *output_bio);
250/* Implement a prototype-compatible wrapper for "STUFF_print" */
251static IMPLEMENT_LHASH_DOALL_ARG_FN(STUFF, const STUFF, BIO)
252 /* ... then later in the code ... */
253/* Print out the entire hashtable to a particular BIO */
254lh_STUFF_doall_arg(hashtable, LHASH_DOALL_ARG_FN(STUFF_print), BIO,
255 logging_bio);
256.Ed
257.Pp
258.Fn lh_<type>_error
259can be used to determine if an error occurred in the last operation.
260.Fn lh_<type>_error
261is a macro.
262.Sh RETURN VALUES
263.Fn lh_<type>_new
264returns
265.Dv NULL
266on error, otherwise a pointer to the new
267.Vt LHASH
268structure.
269.Pp
270When a hash table entry is replaced,
271.Fn lh_<type>_insert
272returns the value being replaced.
273.Dv NULL
274is returned on normal operation and on error.
275.Pp
276.Fn lh_<type>_delete
277returns the entry being deleted.
278.Dv NULL
279is returned if there is no such value in the hash table.
280.Pp
281.Fn lh_<type>_retrieve
282returns the hash table entry if it has been found, or
283.Dv NULL
284otherwise.
285.Pp
286.Fn lh_<type>_error
287returns 1 if an error occurred in the last operation, or 0 otherwise.
288.Pp
289.Fn lh_<type>_free ,
290.Fn lh_<type>_doall ,
291and
292.Fn lh_<type>_doall_arg
293return no values.
294.Sh NOTES
295The various LHASH macros and callback types exist to make it possible to
296write type-checked code without resorting to function-prototype casting
297\(em an evil that makes application code much harder to audit/verify and
298also opens the window of opportunity for stack corruption and other
299hard-to-find bugs.
300It also, apparently, violates ANSI-C.
301.Pp
302The LHASH code regards table entries as constant data.
303As such, it internally represents
304.Fn lh_<type>_insert Ap ed
305items with a
306.Vt const void *
307pointer type.
308This is why callbacks such as those used by
309.Fn lh_<type>_doall
310and
311.Fn lh_<type>_doall_arg
312declare their prototypes with "const", even for the parameters that pass
313back the table items' data pointers \(em for consistency, user-provided
314data is "const" at all times as far as the LHASH code is concerned.
315However, as callers are themselves providing these pointers, they can
316choose whether they too should be treating all such parameters as
317constant.
318.Pp
319As an example, a hash table may be maintained by code that, for
320reasons of encapsulation, has only "const" access to the data being
321indexed in the hash table (i.e. it is returned as "const" from
322elsewhere in their code) \(em in this case the LHASH prototypes are
323appropriate as-is.
324Conversely, if the caller is responsible for the life-time of the data
325in question, then they may well wish to make modifications to table item
326passed back in the
327.Fn lh_<type>_doall
328or
329.Fn lh_<type>_doall_arg
330callbacks (see the "STUFF_cleanup" example above).
331If so, the caller can either cast the "const" away (if they're providing
332the raw callbacks themselves) or use the macros to declare/implement the
333wrapper functions without "const" types.
334.Pp
335Callers that only have "const" access to data they are indexing in a
336table, yet declare callbacks without constant types (or cast the "const"
337away themselves), are therefore creating their own risks/bugs without
338being encouraged to do so by the API.
339On a related note, those auditing code should pay special attention
340to any instances of DECLARE/IMPLEMENT_LHASH_DOALL_[ARG_]_FN macros
341that provide types without any "const" qualifiers.
342.Sh INTERNALS
343The following description is based on the SSLeay documentation:
344.Pp
345The lhash library implements a hash table described in the
346.Em Communications of the ACM
347in 1991.
348What makes this hash table different is that as the table fills,
349the hash table is increased (or decreased) in size via
350.Xr OPENSSL_realloc 3 .
351When a 'resize' is done, instead of all hashes being redistributed over
352twice as many 'buckets', one bucket is split.
353So when an 'expand' is done, there is only a minimal cost to
354redistribute some values.
355Subsequent inserts will cause more single 'bucket' redistributions but
356there will never be a sudden large cost due to redistributing all the
357\&'buckets'.
358.Pp
359The state for a particular hash table is kept in the
360.Vt LHASH
361structure.
362The decision to increase or decrease the hash table size is made
363depending on the 'load' of the hash table.
364The load is the number of items in the hash table divided by the size of
365the hash table.
366The default values are as follows.
367If (hash->up_load < load) => expand.
368if (hash->down_load > load) => contract.
369The
370.Fa up_load
371has a default value of 1 and
372.Fa down_load
373has a default value of 2.
374These numbers can be modified by the application by just playing
375with the
376.Fa up_load
377and
378.Fa down_load
379variables.
380The 'load' is kept in a form which is multiplied by 256.
381So hash->up_load=8*256 will cause a load of 8 to be set.
382.Pp
383If you are interested in performance the field to watch is
384.Fa num_comp_calls .
385The hash library keeps track of the 'hash' value for each item so when a
386lookup is done, the 'hashes' are compared, if there is a match, then a
387full compare is done, and hash->num_comp_calls is incremented.
388If num_comp_calls is not equal to num_delete plus num_retrieve it means
389that your hash function is generating hashes that are the same for
390different values.
391It is probably worth changing your hash function if this is the case
392because even if your hash table has 10 items in a 'bucket', it can be
393searched with 10
394.Vt unsigned long
395compares and 10 linked list traverses.
396This will be much less expensive that 10 calls to your compare function.
397.Pp
398.Fn lh_strhash
399is a demo string hashing function:
400.Pp
401.Dl unsigned long lh_strhash(const char *c);
402.Pp
403Since the LHASH routines would normally be passed structures, this
404routine would not normally be passed to
405.Fn lh_<type>_new ,
406rather it would be used in the function passed to
407.Fn lh_<type>_new .
408.Sh SEE ALSO
409.Xr lh_stats 3
410.Sh HISTORY
411The lhash library is available in all versions of SSLeay and OpenSSL.
412.Fn lh_<type>_error
413was added in SSLeay 0.9.1b.
414.Pp
415In OpenSSL 0.9.7, all lhash functions that were passed function pointers
416were changed for better type safety, and the function types
417.Vt LHASH_COMP_FN_TYPE ,
418.Vt LHASH_HASH_FN_TYPE ,
419.Vt LHASH_DOALL_FN_TYPE ,
420and
421.Vt LHASH_DOALL_ARG_FN_TYPE
422became available.
423.Pp
424In OpenSSL 1.0.0, the lhash interface was revamped for even better type
425checking.
426.Sh BUGS
427.Fn lh_<type>_insert
428returns
429.Dv NULL
430both for success and error.