sdbm_pair.c
上传用户:whbkdz
上传日期:2021-11-17
资源大小:6439k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2.  * contributor license agreements.  See the NOTICE file distributed with
  3.  * this work for additional information regarding copyright ownership.
  4.  * The ASF licenses this file to You under the Apache License, Version 2.0
  5.  * (the "License"); you may not use this file except in compliance with
  6.  * the License.  You may obtain a copy of the License at
  7.  *
  8.  *     http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. /*
  17.  * sdbm - ndbm work-alike hashed database library
  18.  * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
  19.  * author: oz@nexus.yorku.ca
  20.  * status: ex-public domain.
  21.  *
  22.  * page-level routines
  23.  */
  24. #include "apr_sdbm.h"
  25. #include "sdbm_tune.h"
  26. #include "sdbm_pair.h"
  27. #include "sdbm_private.h"
  28. #include <string.h> /* for memset() */
  29. #define exhash(item) sdbm_hash((item).dptr, (item).dsize)
  30. /* 
  31.  * forward 
  32.  */
  33. static int seepair(char *, int, char *, int);
  34. /*
  35.  * page format:
  36.  * +------------------------------+
  37.  * ino | n | keyoff | datoff | keyoff |
  38.  *  +------------+--------+--------+
  39.  * | datoff | - - - ---->        |
  40.  * +--------+---------------------+
  41.  * |  F R E E A R E A       |
  42.  * +--------------+---------------+
  43.  * |  <---- - - - | data          |
  44.  * +--------+-----+----+----------+
  45.  * |  key   | data     | key      |
  46.  * +--------+----------+----------+
  47.  *
  48.  * calculating the offsets for free area:  if the number
  49.  * of entries (ino[0]) is zero, the offset to the END of
  50.  * the free area is the block size. Otherwise, it is the
  51.  * nth (ino[ino[0]]) entry's offset.
  52.  */
  53. int
  54. fitpair(pag, need)
  55. char *pag;
  56. int need;
  57. {
  58. register int n;
  59. register int off;
  60. register int avail;
  61. register short *ino = (short *) pag;
  62. off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
  63. avail = off - (n + 1) * sizeof(short);
  64. need += 2 * sizeof(short);
  65. debug(("avail %d need %dn", avail, need));
  66. return need <= avail;
  67. }
  68. void
  69. putpair(pag, key, val)
  70. char *pag;
  71. apr_sdbm_datum_t key;
  72. apr_sdbm_datum_t val;
  73. {
  74. register int n;
  75. register int off;
  76. register short *ino = (short *) pag;
  77. off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
  78. /*
  79.  * enter the key first
  80.  */
  81. off -= key.dsize;
  82. (void) memcpy(pag + off, key.dptr, key.dsize);
  83. ino[n + 1] = off;
  84. /*
  85.  * now the data
  86.  */
  87. off -= val.dsize;
  88. (void) memcpy(pag + off, val.dptr, val.dsize);
  89. ino[n + 2] = off;
  90. /*
  91.  * adjust item count
  92.  */
  93. ino[0] += 2;
  94. }
  95. apr_sdbm_datum_t
  96. getpair(pag, key)
  97. char *pag;
  98. apr_sdbm_datum_t key;
  99. {
  100. register int i;
  101. register int n;
  102. apr_sdbm_datum_t val;
  103. register short *ino = (short *) pag;
  104. if ((n = ino[0]) == 0)
  105. return sdbm_nullitem;
  106. if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
  107. return sdbm_nullitem;
  108. val.dptr = pag + ino[i + 1];
  109. val.dsize = ino[i] - ino[i + 1];
  110. return val;
  111. }
  112. int
  113. duppair(pag, key)
  114. char *pag;
  115. apr_sdbm_datum_t key;
  116. {
  117. register short *ino = (short *) pag;
  118. return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
  119. }
  120. apr_sdbm_datum_t
  121. getnkey(pag, num)
  122. char *pag;
  123. int num;
  124. {
  125. apr_sdbm_datum_t key;
  126. register int off;
  127. register short *ino = (short *) pag;
  128. num = num * 2 - 1;
  129. if (ino[0] == 0 || num > ino[0])
  130. return sdbm_nullitem;
  131. off = (num > 1) ? ino[num - 1] : PBLKSIZ;
  132. key.dptr = pag + ino[num];
  133. key.dsize = off - ino[num];
  134. return key;
  135. }
  136. int
  137. delpair(pag, key)
  138. char *pag;
  139. apr_sdbm_datum_t key;
  140. {
  141. register int n;
  142. register int i;
  143. register short *ino = (short *) pag;
  144. if ((n = ino[0]) == 0)
  145. return 0;
  146. if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
  147. return 0;
  148. /*
  149.  * found the key. if it is the last entry
  150.  * [i.e. i == n - 1] we just adjust the entry count.
  151.  * hard case: move all data down onto the deleted pair,
  152.  * shift offsets onto deleted offsets, and adjust them.
  153.  * [note: 0 < i < n]
  154.  */
  155. if (i < n - 1) {
  156. register int m;
  157. register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
  158. register char *src = pag + ino[i + 1];
  159. register short zoo = (short) (dst - src);
  160. debug(("free-up %d ", zoo));
  161. /*
  162.  * shift data/keys down
  163.  */
  164. m = ino[i + 1] - ino[n];
  165. #undef DUFF /* just use memmove. it should be plenty fast. */
  166. #ifdef DUFF
  167. #define MOVB  *--dst = *--src
  168. if (m > 0) {
  169. register int loop = (m + 8 - 1) >> 3;
  170. switch (m & (8 - 1)) {
  171. case 0: do {
  172. MOVB; case 7: MOVB;
  173. case 6: MOVB; case 5: MOVB;
  174. case 4: MOVB; case 3: MOVB;
  175. case 2: MOVB; case 1: MOVB;
  176. } while (--loop);
  177. }
  178. }
  179. #else
  180. dst -= m;
  181. src -= m;
  182. memmove(dst, src, m);
  183. #endif
  184. /*
  185.  * adjust offset index up
  186.  */
  187. while (i < n - 1) {
  188. ino[i] = ino[i + 2] + zoo;
  189. i++;
  190. }
  191. }
  192. ino[0] -= 2;
  193. return 1;
  194. }
  195. /*
  196.  * search for the key in the page.
  197.  * return offset index in the range 0 < i < n.
  198.  * return 0 if not found.
  199.  */
  200. static int
  201. seepair(pag, n, key, siz)
  202. char *pag;
  203. register int n;
  204. register char *key;
  205. register int siz;
  206. {
  207. register int i;
  208. register int off = PBLKSIZ;
  209. register short *ino = (short *) pag;
  210. for (i = 1; i < n; i += 2) {
  211. if (siz == off - ino[i] &&
  212.     memcmp(key, pag + ino[i], siz) == 0)
  213. return i;
  214. off = ino[i + 1];
  215. }
  216. return 0;
  217. }
  218. void
  219. splpage(pag, new, sbit)
  220. char *pag;
  221. char *new;
  222. long sbit;
  223. {
  224. apr_sdbm_datum_t key;
  225. apr_sdbm_datum_t val;
  226. register int n;
  227. register int off = PBLKSIZ;
  228. char cur[PBLKSIZ];
  229. register short *ino = (short *) cur;
  230. (void) memcpy(cur, pag, PBLKSIZ);
  231. (void) memset(pag, 0, PBLKSIZ);
  232. (void) memset(new, 0, PBLKSIZ);
  233. n = ino[0];
  234. for (ino++; n > 0; ino += 2) {
  235. key.dptr = cur + ino[0]; 
  236. key.dsize = off - ino[0];
  237. val.dptr = cur + ino[1];
  238. val.dsize = ino[0] - ino[1];
  239. /*
  240.  * select the page pointer (by looking at sbit) and insert
  241.  */
  242. (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
  243. off = ino[1];
  244. n -= 2;
  245. }
  246. debug(("%d split %d/%dn", ((short *) cur)[0] / 2, 
  247.        ((short *) new)[0] / 2,
  248.        ((short *) pag)[0] / 2));
  249. }
  250. /*
  251.  * check page sanity: 
  252.  * number of entries should be something
  253.  * reasonable, and all offsets in the index should be in order.
  254.  * this could be made more rigorous.
  255.  */
  256. int
  257. chkpage(pag)
  258. char *pag;
  259. {
  260. register int n;
  261. register int off;
  262. register short *ino = (short *) pag;
  263. if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
  264. return 0;
  265. if (n > 0) {
  266. off = PBLKSIZ;
  267. for (ino++; n > 0; ino += 2) {
  268. if (ino[0] > off || ino[1] > off ||
  269.     ino[1] > ino[0])
  270. return 0;
  271. off = ino[1];
  272. n -= 2;
  273. }
  274. }
  275. return 1;
  276. }