comparison xml/en/docs/dev/development_guide.xml @ 1914:f8659301a260

Added hash API description.
author Vladimir Homutov <vl@nginx.com>
date Wed, 22 Feb 2017 17:27:40 +0300
parents 42ed974b83a5
children 8b7c3b0ef1a4
comparison
equal deleted inserted replaced
1913:03520b017a3c 1914:f8659301a260
7 <!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> 7 <!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">
8 8
9 <article name="Development guide" 9 <article name="Development guide"
10 link="/en/docs/dev/development_guide.html" 10 link="/en/docs/dev/development_guide.html"
11 lang="en" 11 lang="en"
12 rev="1"> 12 rev="2">
13 13
14 <section name="Introduction" id="introduction"> 14 <section name="Introduction" id="introduction">
15 15
16 16
17 <section name="Code layout" id="code_layout"> 17 <section name="Code layout" id="code_layout">
953 ngx_rbtree_delete(&amp;root->rbtree, node); 953 ngx_rbtree_delete(&amp;root->rbtree, node);
954 </programlisting> 954 </programlisting>
955 955
956 </section> 956 </section>
957 957
958 <section name="Hash" id="hash">
959
960 <para>
961 Hash table functions are are declared in <path>src/core/ngx_string.h</path>.
962 Exact and wildcard matching is supported.
963 The latter requires extra setup and is described in a separate section below.
964 </para>
965
966 <para>
967 To initialize a hash, one needs to know the number of elements in advance,
968 so that nginx can build the hash optimally.
969 Two parameters that need to be configured are <literal>max_size</literal>
970 and <literal>bucket_size</literal>.
971 The details of setting up these are provided in a separate
972 <link doc="../hash.xml">document</link>.
973 Usually, these two parameters are configurable by user.
974 Hash initialization settings are stored as the
975 <literal>ngx_hash_init_t</literal> type,
976 and the hash itself is <literal>ngx_hash_t</literal>:
977 <programlisting>
978 ngx_hash_t foo_hash;
979 ngx_hash_init_t hash;
980
981 hash.hash = &amp;foo_hash;
982 hash.key = ngx_hash_key;
983 hash.max_size = 512;
984 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
985 hash.name = "foo_hash";
986 hash.pool = cf-&gt;pool;
987 hash.temp_pool = cf-&gt;temp_pool;
988 </programlisting>
989 The <literal>key</literal> is a pointer to a function that creates hash integer
990 key from a string.
991 Two generic functions are provided:
992 <literal>ngx_hash_key(data, len)</literal> and
993 <literal>ngx_hash_key_lc(data, len)</literal>.
994 The latter converts a string to lowercase and thus requires the passed string to
995 be writable.
996 If this is not true, <literal>NGX_HASH_READONLY_KEY</literal> flag
997 may be passed to the function, initializing array keys (see below).
998 </para>
999
1000 <para>
1001 The hash keys are stored in <literal>ngx_hash_keys_arrays_t</literal> and
1002 are initialized with <literal>ngx_hash_keys_array_init(arr, type)</literal>:
1003 <programlisting>
1004 ngx_hash_keys_arrays_t foo_keys;
1005
1006 foo_keys.pool = cf-&gt;pool;
1007 foo_keys.temp_pool = cf-&gt;temp_pool;
1008
1009 ngx_hash_keys_array_init(&amp;foo_keys, NGX_HASH_SMALL);
1010 </programlisting>
1011 The second parameter can be either <literal>NGX_HASH_SMALL</literal> or
1012 <literal>NGX_HASH_LARGE</literal> and controls the amount of preallocated
1013 resources for the hash.
1014 If you expect the hash to contain thousands elements,
1015 use <literal>NGX_HASH_LARGE</literal>.
1016 </para>
1017
1018 <para>
1019 The <literal>ngx_hash_add_key(keys_array, key, value, flags)</literal>
1020 function is used to insert keys into hash keys array;
1021 <programlisting>
1022 ngx_str_t k1 = ngx_string("key1");
1023 ngx_str_t k2 = ngx_string("key2");
1024
1025 ngx_hash_add_key(&amp;foo_keys, &amp;k1, &amp;my_data_ptr_1, NGX_HASH_READONLY_KEY);
1026 ngx_hash_add_key(&amp;foo_keys, &amp;k2, &amp;my_data_ptr_2, NGX_HASH_READONLY_KEY);
1027 </programlisting>
1028 </para>
1029
1030 <para>
1031 Now, the hash table may be built using the call to
1032 <literal>ngx_hash_init(hinit, key_names, nelts)</literal>:
1033
1034 <programlisting>
1035 ngx_hash_init(&amp;hash, foo_keys.keys.elts, foo_keys.keys.nelts);
1036 </programlisting>
1037
1038 This may fail, if <literal>max_size</literal> or <literal>bucket_size</literal>
1039 parameters are not big enough.
1040 When the hash is built, <literal>ngx_hash_find(hash, key, name, len)</literal>
1041 function may be used to look up elements:
1042 <programlisting>
1043 my_data_t *data;
1044 ngx_uint_t key;
1045
1046 key = ngx_hash_key(k1.data, k1.len);
1047
1048 data = ngx_hash_find(&amp;foo_hash, key, k1.data, k1.len);
1049 if (data == NULL) {
1050 /* key not found */
1051 }
1052 </programlisting>
1053
1054 </para>
1055
1056 <section name="Wildcard matching" id="wildcard_matching">
1057
1058 <para>
1059 To create a hash that works with wildcards,
1060 <literal>ngx_hash_combined_t</literal> type is used.
1061 It includes the hash type described above and has two additional keys arrays:
1062 <literal>dns_wc_head</literal> and <literal>dns_wc_tail</literal>.
1063 The initialization of basic properties is done similarly to a usual hash:
1064 <programlisting>
1065 ngx_hash_init_t hash
1066 ngx_hash_combined_t foo_hash;
1067
1068 hash.hash = &amp;foo_hash.hash;
1069 hash.key = ...;
1070 </programlisting>
1071 </para>
1072
1073 <para>
1074 It is possible to add wildcard keys using the
1075 <literal>NGX_HASH_WILDCARD_KEY</literal> flag:
1076 <programlisting>
1077 /* k1 = ".example.org"; */
1078 /* k2 = "foo.*"; */
1079 ngx_hash_add_key(&amp;foo_keys, &amp;k1, &amp;data1, NGX_HASH_WILDCARD_KEY);
1080 ngx_hash_add_key(&amp;foo_keys, &amp;k2, &amp;data2, NGX_HASH_WILDCARD_KEY);
1081 </programlisting>
1082 The function recognizes wildcards and adds keys into corresponding arrays.
1083 Please refer to the
1084 <link doc="../http/ngx_http_map_module.xml" id="map"/> module
1085 documentation for the description of the wildcard syntax and
1086 matching algorithm.
1087 </para>
1088
1089 <para>
1090 Depending on the contents of added keys, you may need to initialize up to three
1091 keys arrays: one for exact matching (described above), and two for matching
1092 starting from head or tail of a string:
1093 <programlisting>
1094 if (foo_keys.dns_wc_head.nelts) {
1095
1096 ngx_qsort(foo_keys.dns_wc_head.elts,
1097 (size_t) foo_keys.dns_wc_head.nelts,
1098 sizeof(ngx_hash_key_t),
1099 cmp_dns_wildcards);
1100
1101 hash.hash = NULL;
1102 hash.temp_pool = pool;
1103
1104 if (ngx_hash_wildcard_init(&amp;hash, foo_keys.dns_wc_head.elts,
1105 foo_keys.dns_wc_head.nelts)
1106 != NGX_OK)
1107 {
1108 return NGX_ERROR;
1109 }
1110
1111 foo_hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
1112 }
1113 </programlisting>
1114 The keys array needs to be sorted, and initialization results must be added
1115 to the combined hash.
1116 The initialization of <literal>dns_wc_tail</literal> array is done similarly.
1117 </para>
1118
1119 <para>
1120 The lookup in a combined hash is handled by the
1121 <literal>ngx_hash_find_combined(chash, key, name, len)</literal>:
1122 <programlisting>
1123 /* key = "bar.example.org"; - will match ".example.org" */
1124 /* key = "foo.example.com"; - will match "foo.*" */
1125
1126 hkey = ngx_hash_key(key.data, key.len);
1127 res = ngx_hash_find_combined(&amp;foo_hash, hkey, key.data, key.len);
1128 </programlisting>
1129 </para>
1130
1131 </section>
1132
1133 </section>
958 1134
959 </section> 1135 </section>
960 1136
961 1137
962 <section name="Memory management" id="memory_management"> 1138 <section name="Memory management" id="memory_management">