hash_bigkey.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /*-
  2. * Copyright (c) 1990, 1993, 1994
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * This code is derived from software contributed to Berkeley by
  6. * Margo Seltzer.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. All advertising materials mentioning features or use of this software
  17. * must display the following acknowledgement:
  18. * This product includes software developed by the University of
  19. * California, Berkeley and its contributors.
  20. * 4. Neither the name of the University nor the names of its contributors
  21. * may be used to endorse or promote products derived from this software
  22. * without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34. * SUCH DAMAGE.
  35. */
  36. #if defined(LIBC_SCCS) && !defined(lint)
  37. static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
  38. #endif /* LIBC_SCCS and not lint */
  39. /*
  40. * PACKAGE: hash
  41. * DESCRIPTION:
  42. * Big key/data handling for the hashing package.
  43. *
  44. * ROUTINES:
  45. * External
  46. * __big_keydata
  47. * __big_split
  48. * __big_insert
  49. * __big_return
  50. * __big_delete
  51. * __find_last_page
  52. * Internal
  53. * collect_key
  54. * collect_data
  55. */
  56. #include <sys/param.h>
  57. #include <errno.h>
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #ifdef DEBUG
  62. #include <assert.h>
  63. #endif
  64. #include "../include/db.h"
  65. #include "hash.h"
  66. #include "page.h"
  67. #include "extern.h"
  68. static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int));
  69. static int collect_data __P((HTAB *, BUFHEAD *, int, int));
  70. /*
  71. * Big_insert
  72. *
  73. * You need to do an insert and the key/data pair is too big
  74. *
  75. * Returns:
  76. * 0 ==> OK
  77. *-1 ==> ERROR
  78. */
  79. extern int
  80. __big_insert(hashp, bufp, key, val)
  81. HTAB *hashp;
  82. BUFHEAD *bufp;
  83. const DBT *key, *val;
  84. {
  85. register u_int16_t *p;
  86. int key_size, n, val_size;
  87. u_int16_t space, move_bytes, off;
  88. char *cp, *key_data, *val_data;
  89. cp = bufp->page; /* Character pointer of p. */
  90. p = (u_int16_t *)cp;
  91. key_data = (char *)key->data;
  92. key_size = key->size;
  93. val_data = (char *)val->data;
  94. val_size = val->size;
  95. /* First move the Key */
  96. for (space = FREESPACE(p) - BIGOVERHEAD; key_size;
  97. space = FREESPACE(p) - BIGOVERHEAD) {
  98. move_bytes = MIN(space, key_size);
  99. off = OFFSET(p) - move_bytes;
  100. memmove(cp + off, key_data, move_bytes);
  101. key_size -= move_bytes;
  102. key_data += move_bytes;
  103. n = p[0];
  104. p[++n] = off;
  105. p[0] = ++n;
  106. FREESPACE(p) = off - PAGE_META(n);
  107. OFFSET(p) = off;
  108. p[n] = PARTIAL_KEY;
  109. bufp = __add_ovflpage(hashp, bufp);
  110. if (!bufp)
  111. return (-1);
  112. n = p[0];
  113. if (!key_size) {
  114. if (FREESPACE(p)) {
  115. move_bytes = MIN(FREESPACE(p), val_size);
  116. off = OFFSET(p) - move_bytes;
  117. p[n] = off;
  118. memmove(cp + off, val_data, move_bytes);
  119. val_data += move_bytes;
  120. val_size -= move_bytes;
  121. p[n - 2] = FULL_KEY_DATA;
  122. FREESPACE(p) = FREESPACE(p) - move_bytes;
  123. OFFSET(p) = off;
  124. } else
  125. p[n - 2] = FULL_KEY;
  126. }
  127. p = (u_int16_t *)bufp->page;
  128. cp = bufp->page;
  129. bufp->flags |= BUF_MOD;
  130. }
  131. /* Now move the data */
  132. for (space = FREESPACE(p) - BIGOVERHEAD; val_size;
  133. space = FREESPACE(p) - BIGOVERHEAD) {
  134. move_bytes = MIN(space, val_size);
  135. /*
  136. * Here's the hack to make sure that if the data ends on the
  137. * same page as the key ends, FREESPACE is at least one.
  138. */
  139. if ((int) space == val_size && (size_t) val_size == val->size)
  140. move_bytes--;
  141. off = OFFSET(p) - move_bytes;
  142. memmove(cp + off, val_data, move_bytes);
  143. val_size -= move_bytes;
  144. val_data += move_bytes;
  145. n = p[0];
  146. p[++n] = off;
  147. p[0] = ++n;
  148. FREESPACE(p) = off - PAGE_META(n);
  149. OFFSET(p) = off;
  150. if (val_size) {
  151. p[n] = FULL_KEY;
  152. bufp = __add_ovflpage(hashp, bufp);
  153. if (!bufp)
  154. return (-1);
  155. cp = bufp->page;
  156. p = (u_int16_t *)cp;
  157. } else
  158. p[n] = FULL_KEY_DATA;
  159. bufp->flags |= BUF_MOD;
  160. }
  161. return (0);
  162. }
  163. /*
  164. * Called when bufp's page contains a partial key (index should be 1)
  165. *
  166. * All pages in the big key/data pair except bufp are freed. We cannot
  167. * free bufp because the page pointing to it is lost and we can't get rid
  168. * of its pointer.
  169. *
  170. * Returns:
  171. * 0 => OK
  172. *-1 => ERROR
  173. */
  174. extern int
  175. __big_delete(hashp, bufp)
  176. HTAB *hashp;
  177. BUFHEAD *bufp;
  178. {
  179. register BUFHEAD *last_bfp, *rbufp;
  180. u_int16_t *bp, pageno;
  181. int key_done, n;
  182. rbufp = bufp;
  183. last_bfp = NULL;
  184. bp = (u_int16_t *)bufp->page;
  185. pageno = 0;
  186. key_done = 0;
  187. while (!key_done || (bp[2] != FULL_KEY_DATA)) {
  188. if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA)
  189. key_done = 1;
  190. /*
  191. * If there is freespace left on a FULL_KEY_DATA page, then
  192. * the data is short and fits entirely on this page, and this
  193. * is the last page.
  194. */
  195. if (bp[2] == FULL_KEY_DATA && FREESPACE(bp))
  196. break;
  197. pageno = bp[bp[0] - 1];
  198. rbufp->flags |= BUF_MOD;
  199. rbufp = __get_buf(hashp, pageno, rbufp, 0);
  200. if (last_bfp)
  201. __free_ovflpage(hashp, last_bfp);
  202. last_bfp = rbufp;
  203. if (!rbufp)
  204. return (-1); /* Error. */
  205. bp = (u_int16_t *)rbufp->page;
  206. }
  207. /*
  208. * If we get here then rbufp points to the last page of the big
  209. * key/data pair. Bufp points to the first one -- it should now be
  210. * empty pointing to the next page after this pair. Can't free it
  211. * because we don't have the page pointing to it.
  212. */
  213. /* This is information from the last page of the pair. */
  214. n = bp[0];
  215. pageno = bp[n - 1];
  216. /* Now, bp is the first page of the pair. */
  217. bp = (u_int16_t *)bufp->page;
  218. if (n > 2) {
  219. /* There is an overflow page. */
  220. bp[1] = pageno;
  221. bp[2] = OVFLPAGE;
  222. bufp->ovfl = rbufp->ovfl;
  223. } else
  224. /* This is the last page. */
  225. bufp->ovfl = NULL;
  226. n -= 2;
  227. bp[0] = n;
  228. FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
  229. OFFSET(bp) = hashp->BSIZE - 1;
  230. bufp->flags |= BUF_MOD;
  231. if (rbufp)
  232. __free_ovflpage(hashp, rbufp);
  233. if (last_bfp && last_bfp != rbufp)
  234. __free_ovflpage(hashp, last_bfp);
  235. hashp->NKEYS--;
  236. return (0);
  237. }
  238. /*
  239. * Returns:
  240. * 0 = key not found
  241. * -1 = get next overflow page
  242. * -2 means key not found and this is big key/data
  243. * -3 error
  244. */
  245. extern int
  246. __find_bigpair(hashp, bufp, ndx, key, size)
  247. HTAB *hashp;
  248. BUFHEAD *bufp;
  249. int ndx;
  250. char *key;
  251. int size;
  252. {
  253. register u_int16_t *bp;
  254. register char *p;
  255. int ksize;
  256. u_int16_t bytes;
  257. char *kkey;
  258. bp = (u_int16_t *)bufp->page;
  259. p = bufp->page;
  260. ksize = size;
  261. kkey = key;
  262. for (bytes = hashp->BSIZE - bp[ndx];
  263. bytes <= size && bp[ndx + 1] == PARTIAL_KEY;
  264. bytes = hashp->BSIZE - bp[ndx]) {
  265. if (memcmp(p + bp[ndx], kkey, bytes))
  266. return (-2);
  267. kkey += bytes;
  268. ksize -= bytes;
  269. bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0);
  270. if (!bufp)
  271. return (-3);
  272. p = bufp->page;
  273. bp = (u_int16_t *)p;
  274. ndx = 1;
  275. }
  276. if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {
  277. #ifdef HASH_STATISTICS
  278. ++hash_collisions;
  279. #endif
  280. return (-2);
  281. } else
  282. return (ndx);
  283. }
  284. /*
  285. * Given the buffer pointer of the first overflow page of a big pair,
  286. * find the end of the big pair
  287. *
  288. * This will set bpp to the buffer header of the last page of the big pair.
  289. * It will return the pageno of the overflow page following the last page
  290. * of the pair; 0 if there isn't any (i.e. big pair is the last key in the
  291. * bucket)
  292. */
  293. extern u_int16_t
  294. __find_last_page(hashp, bpp)
  295. HTAB *hashp;
  296. BUFHEAD **bpp;
  297. {
  298. BUFHEAD *bufp;
  299. u_int16_t *bp, pageno;
  300. int n;
  301. bufp = *bpp;
  302. bp = (u_int16_t *)bufp->page;
  303. for (;;) {
  304. n = bp[0];
  305. /*
  306. * This is the last page if: the tag is FULL_KEY_DATA and
  307. * either only 2 entries OVFLPAGE marker is explicit there
  308. * is freespace on the page.
  309. */
  310. if (bp[2] == FULL_KEY_DATA &&
  311. ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp))))
  312. break;
  313. pageno = bp[n - 1];
  314. bufp = __get_buf(hashp, pageno, bufp, 0);
  315. if (!bufp)
  316. return (0); /* Need to indicate an error! */
  317. bp = (u_int16_t *)bufp->page;
  318. }
  319. *bpp = bufp;
  320. if (bp[0] > 2)
  321. return (bp[3]);
  322. else
  323. return (0);
  324. }
  325. /*
  326. * Return the data for the key/data pair that begins on this page at this
  327. * index (index should always be 1).
  328. */
  329. extern int
  330. __big_return(hashp, bufp, ndx, val, set_current)
  331. HTAB *hashp;
  332. BUFHEAD *bufp;
  333. int ndx;
  334. DBT *val;
  335. int set_current;
  336. {
  337. BUFHEAD *save_p;
  338. u_int16_t *bp, len, off, save_addr;
  339. char *tp;
  340. bp = (u_int16_t *)bufp->page;
  341. while (bp[ndx + 1] == PARTIAL_KEY) {
  342. bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
  343. if (!bufp)
  344. return (-1);
  345. bp = (u_int16_t *)bufp->page;
  346. ndx = 1;
  347. }
  348. if (bp[ndx + 1] == FULL_KEY) {
  349. bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
  350. if (!bufp)
  351. return (-1);
  352. bp = (u_int16_t *)bufp->page;
  353. save_p = bufp;
  354. save_addr = save_p->addr;
  355. off = bp[1];
  356. len = 0;
  357. } else
  358. if (!FREESPACE(bp)) {
  359. /*
  360. * This is a hack. We can't distinguish between
  361. * FULL_KEY_DATA that contains complete data or
  362. * incomplete data, so we require that if the data
  363. * is complete, there is at least 1 byte of free
  364. * space left.
  365. */
  366. off = bp[bp[0]];
  367. len = bp[1] - off;
  368. save_p = bufp;
  369. save_addr = bufp->addr;
  370. bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
  371. if (!bufp)
  372. return (-1);
  373. bp = (u_int16_t *)bufp->page;
  374. } else {
  375. /* The data is all on one page. */
  376. tp = (char *)bp;
  377. off = bp[bp[0]];
  378. val->data = (u_char *)tp + off;
  379. val->size = bp[1] - off;
  380. if (set_current) {
  381. if (bp[0] == 2) { /* No more buckets in
  382. * chain */
  383. hashp->cpage = NULL;
  384. hashp->cbucket++;
  385. hashp->cndx = 1;
  386. } else {
  387. hashp->cpage = __get_buf(hashp,
  388. bp[bp[0] - 1], bufp, 0);
  389. if (!hashp->cpage)
  390. return (-1);
  391. hashp->cndx = 1;
  392. if (!((u_int16_t *)
  393. hashp->cpage->page)[0]) {
  394. hashp->cbucket++;
  395. hashp->cpage = NULL;
  396. }
  397. }
  398. }
  399. return (0);
  400. }
  401. val->size = collect_data(hashp, bufp, (int)len, set_current);
  402. if (val->size == (size_t) -1)
  403. return (-1);
  404. if (save_p->addr != save_addr) {
  405. /* We are pretty short on buffers. */
  406. errno = EINVAL; /* OUT OF BUFFERS */
  407. return (-1);
  408. }
  409. memmove(hashp->tmp_buf, (save_p->page) + off, len);
  410. val->data = (u_char *)hashp->tmp_buf;
  411. return (0);
  412. }
  413. /*
  414. * Count how big the total datasize is by recursing through the pages. Then
  415. * allocate a buffer and copy the data as you recurse up.
  416. */
  417. static int
  418. collect_data(hashp, bufp, len, set)
  419. HTAB *hashp;
  420. BUFHEAD *bufp;
  421. int len, set;
  422. {
  423. register u_int16_t *bp;
  424. register char *p;
  425. BUFHEAD *xbp;
  426. u_int16_t save_addr;
  427. int mylen, totlen;
  428. p = bufp->page;
  429. bp = (u_int16_t *)p;
  430. mylen = hashp->BSIZE - bp[1];
  431. save_addr = bufp->addr;
  432. if (bp[2] == FULL_KEY_DATA) { /* End of Data */
  433. totlen = len + mylen;
  434. if (hashp->tmp_buf)
  435. free(hashp->tmp_buf);
  436. if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL)
  437. return (-1);
  438. if (set) {
  439. hashp->cndx = 1;
  440. if (bp[0] == 2) { /* No more buckets in chain */
  441. hashp->cpage = NULL;
  442. hashp->cbucket++;
  443. } else {
  444. hashp->cpage =
  445. __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
  446. if (!hashp->cpage)
  447. return (-1);
  448. else if (!((u_int16_t *)hashp->cpage->page)[0]) {
  449. hashp->cbucket++;
  450. hashp->cpage = NULL;
  451. }
  452. }
  453. }
  454. } else {
  455. xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
  456. if (!xbp || ((totlen =
  457. collect_data(hashp, xbp, len + mylen, set)) < 1))
  458. return (-1);
  459. }
  460. if (bufp->addr != save_addr) {
  461. errno = EINVAL; /* Out of buffers. */
  462. return (-1);
  463. }
  464. memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen);
  465. return (totlen);
  466. }
  467. /*
  468. * Fill in the key and data for this big pair.
  469. */
  470. extern int
  471. __big_keydata(hashp, bufp, key, val, set)
  472. HTAB *hashp;
  473. BUFHEAD *bufp;
  474. DBT *key, *val;
  475. int set;
  476. {
  477. key->size = collect_key(hashp, bufp, 0, val, set);
  478. if (key->size == (size_t) -1)
  479. return (-1);
  480. key->data = (u_char *)hashp->tmp_key;
  481. return (0);
  482. }
  483. /*
  484. * Count how big the total key size is by recursing through the pages. Then
  485. * collect the data, allocate a buffer and copy the key as you recurse up.
  486. */
  487. static int
  488. collect_key(hashp, bufp, len, val, set)
  489. HTAB *hashp;
  490. BUFHEAD *bufp;
  491. int len;
  492. DBT *val;
  493. int set;
  494. {
  495. BUFHEAD *xbp;
  496. char *p;
  497. int mylen, totlen;
  498. u_int16_t *bp, save_addr;
  499. p = bufp->page;
  500. bp = (u_int16_t *)p;
  501. mylen = hashp->BSIZE - bp[1];
  502. save_addr = bufp->addr;
  503. totlen = len + mylen;
  504. if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */
  505. if (hashp->tmp_key != NULL)
  506. free(hashp->tmp_key);
  507. if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL)
  508. return (-1);
  509. if (__big_return(hashp, bufp, 1, val, set))
  510. return (-1);
  511. } else {
  512. xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
  513. if (!xbp || ((totlen =
  514. collect_key(hashp, xbp, totlen, val, set)) < 1))
  515. return (-1);
  516. }
  517. if (bufp->addr != save_addr) {
  518. errno = EINVAL; /* MIS -- OUT OF BUFFERS */
  519. return (-1);
  520. }
  521. memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen);
  522. return (totlen);
  523. }
  524. /*
  525. * Returns:
  526. * 0 => OK
  527. * -1 => error
  528. */
  529. extern int
  530. __big_split(hashp, op, np, big_keyp, addr, obucket, ret)
  531. HTAB *hashp;
  532. BUFHEAD *op; /* Pointer to where to put keys that go in old bucket */
  533. BUFHEAD *np; /* Pointer to new bucket page */
  534. /* Pointer to first page containing the big key/data */
  535. BUFHEAD *big_keyp;
  536. int addr; /* Address of big_keyp */
  537. u_int32_t obucket;/* Old Bucket */
  538. SPLIT_RETURN *ret;
  539. {
  540. register BUFHEAD *tmpp;
  541. register u_int16_t *tp;
  542. BUFHEAD *bp;
  543. DBT key, val;
  544. u_int32_t change;
  545. u_int16_t free_space, n, off;
  546. bp = big_keyp;
  547. /* Now figure out where the big key/data goes */
  548. if (__big_keydata(hashp, big_keyp, &key, &val, 0))
  549. return (-1);
  550. change = (__call_hash(hashp, key.data, key.size) != obucket);
  551. if ((ret->next_addr = __find_last_page(hashp, &big_keyp))) {
  552. if (!(ret->nextp =
  553. __get_buf(hashp, ret->next_addr, big_keyp, 0)))
  554. return (-1);;
  555. } else
  556. ret->nextp = NULL;
  557. /* Now make one of np/op point to the big key/data pair */
  558. #ifdef DEBUG
  559. assert(np->ovfl == NULL);
  560. #endif
  561. if (change)
  562. tmpp = np;
  563. else
  564. tmpp = op;
  565. tmpp->flags |= BUF_MOD;
  566. #ifdef DEBUG1
  567. (void)fprintf(stderr,
  568. "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
  569. (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
  570. #endif
  571. tmpp->ovfl = bp; /* one of op/np point to big_keyp */
  572. tp = (u_int16_t *)tmpp->page;
  573. #ifdef DEBUG
  574. assert(FREESPACE(tp) >= OVFLSIZE);
  575. #endif
  576. n = tp[0];
  577. off = OFFSET(tp);
  578. free_space = FREESPACE(tp);
  579. tp[++n] = (u_int16_t)addr;
  580. tp[++n] = OVFLPAGE;
  581. tp[0] = n;
  582. OFFSET(tp) = off;
  583. FREESPACE(tp) = free_space - OVFLSIZE;
  584. /*
  585. * Finally, set the new and old return values. BIG_KEYP contains a
  586. * pointer to the last page of the big key_data pair. Make sure that
  587. * big_keyp has no following page (2 elements) or create an empty
  588. * following page.
  589. */
  590. ret->newp = np;
  591. ret->oldp = op;
  592. tp = (u_int16_t *)big_keyp->page;
  593. big_keyp->flags |= BUF_MOD;
  594. if (tp[0] > 2) {
  595. /*
  596. * There may be either one or two offsets on this page. If
  597. * there is one, then the overflow page is linked on normally
  598. * and tp[4] is OVFLPAGE. If there are two, tp[4] contains
  599. * the second offset and needs to get stuffed in after the
  600. * next overflow page is added.
  601. */
  602. n = tp[4];
  603. free_space = FREESPACE(tp);
  604. off = OFFSET(tp);
  605. tp[0] -= 2;
  606. FREESPACE(tp) = free_space + OVFLSIZE;
  607. OFFSET(tp) = off;
  608. tmpp = __add_ovflpage(hashp, big_keyp);
  609. if (!tmpp)
  610. return (-1);
  611. tp[4] = n;
  612. } else
  613. tmpp = big_keyp;
  614. if (change)
  615. ret->newp = tmpp;
  616. else
  617. ret->oldp = tmpp;
  618. return (0);
  619. }