hash_page.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:48k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. /*
  8.  * Copyright (c) 1990, 1993, 1994
  9.  * Margo Seltzer.  All rights reserved.
  10.  */
  11. /*
  12.  * Copyright (c) 1990, 1993, 1994
  13.  * The Regents of the University of California.  All rights reserved.
  14.  *
  15.  * This code is derived from software contributed to Berkeley by
  16.  * Margo Seltzer.
  17.  *
  18.  * Redistribution and use in source and binary forms, with or without
  19.  * modification, are permitted provided that the following conditions
  20.  * are met:
  21.  * 1. Redistributions of source code must retain the above copyright
  22.  *    notice, this list of conditions and the following disclaimer.
  23.  * 2. Redistributions in binary form must reproduce the above copyright
  24.  *    notice, this list of conditions and the following disclaimer in the
  25.  *    documentation and/or other materials provided with the distribution.
  26.  * 3. Neither the name of the University nor the names of its contributors
  27.  *    may be used to endorse or promote products derived from this software
  28.  *    without specific prior written permission.
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  31.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  34.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  38.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  39.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  40.  * SUCH DAMAGE.
  41.  */
  42. #include "db_config.h"
  43. #ifndef lint
  44. static const char revid[] = "$Id: hash_page.c,v 11.87 2002/08/15 02:46:20 bostic Exp $";
  45. #endif /* not lint */
  46. /*
  47.  * PACKAGE:  hashing
  48.  *
  49.  * DESCRIPTION:
  50.  * Page manipulation for hashing package.
  51.  */
  52. #ifndef NO_SYSTEM_INCLUDES
  53. #include <sys/types.h>
  54. #include <string.h>
  55. #endif
  56. #include "db_int.h"
  57. #include "dbinc/db_page.h"
  58. #include "dbinc/db_shash.h"
  59. #include "dbinc/hash.h"
  60. #include "dbinc/lock.h"
  61. static int __ham_c_delpg
  62.     __P((DBC *, db_pgno_t, db_pgno_t, u_int32_t, db_ham_mode, u_int32_t *));
  63. /*
  64.  * PUBLIC: int __ham_item __P((DBC *, db_lockmode_t, db_pgno_t *));
  65.  */
  66. int
  67. __ham_item(dbc, mode, pgnop)
  68. DBC *dbc;
  69. db_lockmode_t mode;
  70. db_pgno_t *pgnop;
  71. {
  72. DB *dbp;
  73. HASH_CURSOR *hcp;
  74. db_pgno_t next_pgno;
  75. int ret;
  76. dbp = dbc->dbp;
  77. hcp = (HASH_CURSOR *)dbc->internal;
  78. if (F_ISSET(hcp, H_DELETED)) {
  79. __db_err(dbp->dbenv, "Attempt to return a deleted item");
  80. return (EINVAL);
  81. }
  82. F_CLR(hcp, H_OK | H_NOMORE);
  83. /* Check if we need to get a page for this cursor. */
  84. if ((ret = __ham_get_cpage(dbc, mode)) != 0)
  85. return (ret);
  86. recheck:
  87. /* Check if we are looking for space in which to insert an item. */
  88. if (hcp->seek_size && hcp->seek_found_page == PGNO_INVALID &&
  89.     hcp->seek_size < P_FREESPACE(dbp, hcp->page))
  90. hcp->seek_found_page = hcp->pgno;
  91. /* Check for off-page duplicates. */
  92. if (hcp->indx < NUM_ENT(hcp->page) &&
  93.     HPAGE_TYPE(dbp, hcp->page, H_DATAINDEX(hcp->indx)) == H_OFFDUP) {
  94. memcpy(pgnop,
  95.     HOFFDUP_PGNO(H_PAIRDATA(dbp, hcp->page, hcp->indx)),
  96.     sizeof(db_pgno_t));
  97. F_SET(hcp, H_OK);
  98. return (0);
  99. }
  100. /* Check if we need to go on to the next page. */
  101. if (F_ISSET(hcp, H_ISDUP))
  102. /*
  103.  * ISDUP is set, and offset is at the beginning of the datum.
  104.  * We need to grab the length of the datum, then set the datum
  105.  * pointer to be the beginning of the datum.
  106.  */
  107. memcpy(&hcp->dup_len,
  108.     HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx)) +
  109.     hcp->dup_off, sizeof(db_indx_t));
  110. if (hcp->indx >= (db_indx_t)NUM_ENT(hcp->page)) {
  111. /* Fetch next page. */
  112. if (NEXT_PGNO(hcp->page) == PGNO_INVALID) {
  113. F_SET(hcp, H_NOMORE);
  114. return (DB_NOTFOUND);
  115. }
  116. next_pgno = NEXT_PGNO(hcp->page);
  117. hcp->indx = 0;
  118. if ((ret = __ham_next_cpage(dbc, next_pgno, 0)) != 0)
  119. return (ret);
  120. goto recheck;
  121. }
  122. F_SET(hcp, H_OK);
  123. return (0);
  124. }
  125. /*
  126.  * PUBLIC: int __ham_item_reset __P((DBC *));
  127.  */
  128. int
  129. __ham_item_reset(dbc)
  130. DBC *dbc;
  131. {
  132. DB *dbp;
  133. DB_MPOOLFILE *mpf;
  134. HASH_CURSOR *hcp;
  135. int ret;
  136. dbp = dbc->dbp;
  137. mpf = dbp->mpf;
  138. hcp = (HASH_CURSOR *)dbc->internal;
  139. ret = 0;
  140. if (hcp->page != NULL)
  141. ret = mpf->put(mpf, hcp->page, 0);
  142. __ham_item_init(dbc);
  143. return (ret);
  144. }
  145. /*
  146.  * PUBLIC: void __ham_item_init __P((DBC *));
  147.  */
  148. void
  149. __ham_item_init(dbc)
  150. DBC *dbc;
  151. {
  152. HASH_CURSOR *hcp;
  153. hcp = (HASH_CURSOR *)dbc->internal;
  154. /*
  155.  * If this cursor still holds any locks, we must
  156.  * release them if we are not running with transactions.
  157.  */
  158. (void)__TLPUT(dbc, hcp->lock);
  159. /*
  160.  * The following fields must *not* be initialized here
  161.  * because they may have meaning across inits.
  162.  * hlock, hdr, split_buf, stats
  163.  */
  164. hcp->bucket = BUCKET_INVALID;
  165. hcp->lbucket = BUCKET_INVALID;
  166. LOCK_INIT(hcp->lock);
  167. hcp->lock_mode = DB_LOCK_NG;
  168. hcp->dup_off = 0;
  169. hcp->dup_len = 0;
  170. hcp->dup_tlen = 0;
  171. hcp->seek_size = 0;
  172. hcp->seek_found_page = PGNO_INVALID;
  173. hcp->flags = 0;
  174. hcp->pgno = PGNO_INVALID;
  175. hcp->indx = NDX_INVALID;
  176. hcp->page = NULL;
  177. }
  178. /*
  179.  * Returns the last item in a bucket.
  180.  *
  181.  * PUBLIC: int __ham_item_last __P((DBC *, db_lockmode_t, db_pgno_t *));
  182.  */
  183. int
  184. __ham_item_last(dbc, mode, pgnop)
  185. DBC *dbc;
  186. db_lockmode_t mode;
  187. db_pgno_t *pgnop;
  188. {
  189. HASH_CURSOR *hcp;
  190. int ret;
  191. hcp = (HASH_CURSOR *)dbc->internal;
  192. if ((ret = __ham_item_reset(dbc)) != 0)
  193. return (ret);
  194. hcp->bucket = hcp->hdr->max_bucket;
  195. hcp->pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
  196. F_SET(hcp, H_OK);
  197. return (__ham_item_prev(dbc, mode, pgnop));
  198. }
  199. /*
  200.  * PUBLIC: int __ham_item_first __P((DBC *, db_lockmode_t, db_pgno_t *));
  201.  */
  202. int
  203. __ham_item_first(dbc, mode, pgnop)
  204. DBC *dbc;
  205. db_lockmode_t mode;
  206. db_pgno_t *pgnop;
  207. {
  208. HASH_CURSOR *hcp;
  209. int ret;
  210. hcp = (HASH_CURSOR *)dbc->internal;
  211. if ((ret = __ham_item_reset(dbc)) != 0)
  212. return (ret);
  213. F_SET(hcp, H_OK);
  214. hcp->bucket = 0;
  215. hcp->pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
  216. return (__ham_item_next(dbc, mode, pgnop));
  217. }
  218. /*
  219.  * __ham_item_prev --
  220.  * Returns a pointer to key/data pair on a page.  In the case of
  221.  * bigkeys, just returns the page number and index of the bigkey
  222.  * pointer pair.
  223.  *
  224.  * PUBLIC: int __ham_item_prev __P((DBC *, db_lockmode_t, db_pgno_t *));
  225.  */
  226. int
  227. __ham_item_prev(dbc, mode, pgnop)
  228. DBC *dbc;
  229. db_lockmode_t mode;
  230. db_pgno_t *pgnop;
  231. {
  232. DB *dbp;
  233. HASH_CURSOR *hcp;
  234. db_pgno_t next_pgno;
  235. int ret;
  236. hcp = (HASH_CURSOR *)dbc->internal;
  237. dbp = dbc->dbp;
  238. /*
  239.  * There are 5 cases for backing up in a hash file.
  240.  * Case 1: In the middle of a page, no duplicates, just dec the index.
  241.  * Case 2: In the middle of a duplicate set, back up one.
  242.  * Case 3: At the beginning of a duplicate set, get out of set and
  243.  * back up to next key.
  244.  * Case 4: At the beginning of a page; go to previous page.
  245.  * Case 5: At the beginning of a bucket; go to prev bucket.
  246.  */
  247. F_CLR(hcp, H_OK | H_NOMORE | H_DELETED);
  248. if ((ret = __ham_get_cpage(dbc, mode)) != 0)
  249. return (ret);
  250. /*
  251.  * First handle the duplicates.  Either you'll get the key here
  252.  * or you'll exit the duplicate set and drop into the code below
  253.  * to handle backing up through keys.
  254.  */
  255. if (!F_ISSET(hcp, H_NEXT_NODUP) && F_ISSET(hcp, H_ISDUP)) {
  256. if (HPAGE_TYPE(dbp, hcp->page, H_DATAINDEX(hcp->indx)) ==
  257.     H_OFFDUP) {
  258. memcpy(pgnop,
  259.     HOFFDUP_PGNO(H_PAIRDATA(dbp, hcp->page, hcp->indx)),
  260.     sizeof(db_pgno_t));
  261. F_SET(hcp, H_OK);
  262. return (0);
  263. }
  264. /* Duplicates are on-page. */
  265. if (hcp->dup_off != 0) {
  266. memcpy(&hcp->dup_len, HKEYDATA_DATA(
  267.     H_PAIRDATA(dbp, hcp->page, hcp->indx))
  268.     + hcp->dup_off - sizeof(db_indx_t),
  269.     sizeof(db_indx_t));
  270. hcp->dup_off -=
  271.     DUP_SIZE(hcp->dup_len);
  272. return (__ham_item(dbc, mode, pgnop));
  273. }
  274. }
  275. /*
  276.  * If we get here, we are not in a duplicate set, and just need
  277.  * to back up the cursor.  There are still three cases:
  278.  * midpage, beginning of page, beginning of bucket.
  279.  */
  280. if (F_ISSET(hcp, H_DUPONLY)) {
  281. F_CLR(hcp, H_OK);
  282. F_SET(hcp, H_NOMORE);
  283. return (0);
  284. } else
  285. /*
  286.  * We are no longer in a dup set;  flag this so the dup code
  287.  * will reinitialize should we stumble upon another one.
  288.  */
  289. F_CLR(hcp, H_ISDUP);
  290. if (hcp->indx == 0) { /* Beginning of page. */
  291. hcp->pgno = PREV_PGNO(hcp->page);
  292. if (hcp->pgno == PGNO_INVALID) {
  293. /* Beginning of bucket. */
  294. F_SET(hcp, H_NOMORE);
  295. return (DB_NOTFOUND);
  296. } else if ((ret =
  297.     __ham_next_cpage(dbc, hcp->pgno, 0)) != 0)
  298. return (ret);
  299. else
  300. hcp->indx = NUM_ENT(hcp->page);
  301. }
  302. /*
  303.  * Either we've got the cursor set up to be decremented, or we
  304.  * have to find the end of a bucket.
  305.  */
  306. if (hcp->indx == NDX_INVALID) {
  307. DB_ASSERT(hcp->page != NULL);
  308. hcp->indx = NUM_ENT(hcp->page);
  309. for (next_pgno = NEXT_PGNO(hcp->page);
  310.     next_pgno != PGNO_INVALID;
  311.     next_pgno = NEXT_PGNO(hcp->page)) {
  312. if ((ret = __ham_next_cpage(dbc, next_pgno, 0)) != 0)
  313. return (ret);
  314. hcp->indx = NUM_ENT(hcp->page);
  315. }
  316. if (hcp->indx == 0) {
  317. /* Bucket was empty. */
  318. F_SET(hcp, H_NOMORE);
  319. return (DB_NOTFOUND);
  320. }
  321. }
  322. hcp->indx -= 2;
  323. return (__ham_item(dbc, mode, pgnop));
  324. }
  325. /*
  326.  * Sets the cursor to the next key/data pair on a page.
  327.  *
  328.  * PUBLIC: int __ham_item_next __P((DBC *, db_lockmode_t, db_pgno_t *));
  329.  */
  330. int
  331. __ham_item_next(dbc, mode, pgnop)
  332. DBC *dbc;
  333. db_lockmode_t mode;
  334. db_pgno_t *pgnop;
  335. {
  336. HASH_CURSOR *hcp;
  337. int ret;
  338. hcp = (HASH_CURSOR *)dbc->internal;
  339. if ((ret = __ham_get_cpage(dbc, mode)) != 0)
  340. return (ret);
  341. /*
  342.  * Deleted on-page duplicates are a weird case. If we delete the last
  343.  * one, then our cursor is at the very end of a duplicate set and
  344.  * we actually need to go on to the next key.
  345.  */
  346. if (F_ISSET(hcp, H_DELETED)) {
  347. if (hcp->indx != NDX_INVALID &&
  348.     F_ISSET(hcp, H_ISDUP) &&
  349.     HPAGE_TYPE(dbc->dbp, hcp->page, H_DATAINDEX(hcp->indx))
  350. == H_DUPLICATE && hcp->dup_tlen == hcp->dup_off) {
  351. if (F_ISSET(hcp, H_DUPONLY)) {
  352. F_CLR(hcp, H_OK);
  353. F_SET(hcp, H_NOMORE);
  354. return (0);
  355. } else {
  356. F_CLR(hcp, H_ISDUP);
  357. hcp->indx += 2;
  358. }
  359. } else if (!F_ISSET(hcp, H_ISDUP) && F_ISSET(hcp, H_DUPONLY)) {
  360. F_CLR(hcp, H_OK);
  361. F_SET(hcp, H_NOMORE);
  362. return (0);
  363. } else if (F_ISSET(hcp, H_ISDUP) &&
  364.     F_ISSET(hcp, H_NEXT_NODUP)) {
  365. F_CLR(hcp, H_ISDUP);
  366. hcp->indx += 2;
  367. }
  368. F_CLR(hcp, H_DELETED);
  369. } else if (hcp->indx == NDX_INVALID) {
  370. hcp->indx = 0;
  371. F_CLR(hcp, H_ISDUP);
  372. } else if (F_ISSET(hcp, H_NEXT_NODUP)) {
  373. hcp->indx += 2;
  374. F_CLR(hcp, H_ISDUP);
  375. } else if (F_ISSET(hcp, H_ISDUP) && hcp->dup_tlen != 0) {
  376. if (hcp->dup_off + DUP_SIZE(hcp->dup_len) >=
  377.     hcp->dup_tlen && F_ISSET(hcp, H_DUPONLY)) {
  378. F_CLR(hcp, H_OK);
  379. F_SET(hcp, H_NOMORE);
  380. return (0);
  381. }
  382. hcp->dup_off += DUP_SIZE(hcp->dup_len);
  383. if (hcp->dup_off >= hcp->dup_tlen) {
  384. F_CLR(hcp, H_ISDUP);
  385. hcp->indx += 2;
  386. }
  387. } else if (F_ISSET(hcp, H_DUPONLY)) {
  388. F_CLR(hcp, H_OK);
  389. F_SET(hcp, H_NOMORE);
  390. return (0);
  391. } else {
  392. hcp->indx += 2;
  393. F_CLR(hcp, H_ISDUP);
  394. }
  395. return (__ham_item(dbc, mode, pgnop));
  396. }
  397. /*
  398.  * PUBLIC: void __ham_putitem __P((DB *, PAGE *p, const DBT *, int));
  399.  *
  400.  * This is a little bit sleazy in that we're overloading the meaning
  401.  * of the H_OFFPAGE type here.  When we recover deletes, we have the
  402.  * entire entry instead of having only the DBT, so we'll pass type
  403.  * H_OFFPAGE to mean, "copy the whole entry" as opposed to constructing
  404.  * an H_KEYDATA around it.
  405.  */
  406. void
  407. __ham_putitem(dbp, p, dbt, type)
  408. DB *dbp;
  409. PAGE *p;
  410. const DBT *dbt;
  411. int type;
  412. {
  413. u_int16_t n, off;
  414. db_indx_t *inp;
  415. n = NUM_ENT(p);
  416. inp = P_INP(dbp, p);
  417. /* Put the item element on the page. */
  418. if (type == H_OFFPAGE) {
  419. off = HOFFSET(p) - dbt->size;
  420. HOFFSET(p) = inp[n] = off;
  421. memcpy(P_ENTRY(dbp, p, n), dbt->data, dbt->size);
  422. } else {
  423. off = HOFFSET(p) - HKEYDATA_SIZE(dbt->size);
  424. HOFFSET(p) = inp[n] = off;
  425. PUT_HKEYDATA(P_ENTRY(dbp, p, n), dbt->data, dbt->size, type);
  426. }
  427. /* Adjust page info. */
  428. NUM_ENT(p) += 1;
  429. }
  430. /*
  431.  * PUBLIC: void __ham_reputpair  __P((DB *, PAGE *,
  432.  * PUBLIC:    u_int32_t, const DBT *, const DBT *));
  433.  *
  434.  * This is a special case to restore a key/data pair to its original
  435.  * location during recovery.  We are guaranteed that the pair fits
  436.  * on the page and is not the last pair on the page (because if it's
  437.  * the last pair, the normal insert works).
  438.  */
  439. void
  440. __ham_reputpair(dbp, p, ndx, key, data)
  441. DB *dbp;
  442. PAGE *p;
  443. u_int32_t ndx;
  444. const DBT *key, *data;
  445. {
  446. db_indx_t i, *inp, movebytes, newbytes;
  447. size_t psize;
  448. u_int8_t *from;
  449. psize = dbp->pgsize;
  450. inp = P_INP(dbp, p);
  451. /* First shuffle the existing items up on the page.  */
  452. movebytes = (db_indx_t)(
  453.     (ndx == 0 ? psize : inp[H_DATAINDEX(ndx - 2)]) - HOFFSET(p));
  454. newbytes = key->size + data->size;
  455. from = (u_int8_t *)p + HOFFSET(p);
  456. memmove(from - newbytes, from, movebytes);
  457. /*
  458.  * Adjust the indices and move them up 2 spaces. Note that we
  459.  * have to check the exit condition inside the loop just in case
  460.  * we are dealing with index 0 (db_indx_t's are unsigned).
  461.  */
  462. for (i = NUM_ENT(p) - 1; ; i-- ) {
  463. inp[i + 2] = inp[i] - newbytes;
  464. if (i == H_KEYINDEX(ndx))
  465. break;
  466. }
  467. /* Put the key and data on the page. */
  468. inp[H_KEYINDEX(ndx)] = (db_indx_t)(
  469.     (ndx == 0 ? psize : inp[H_DATAINDEX(ndx - 2)]) - key->size);
  470. inp[H_DATAINDEX(ndx)] = inp[H_KEYINDEX(ndx)] - data->size;
  471. memcpy(P_ENTRY(dbp, p, H_KEYINDEX(ndx)), key->data, key->size);
  472. memcpy(P_ENTRY(dbp, p, H_DATAINDEX(ndx)), data->data, data->size);
  473. /* Adjust page info. */
  474. HOFFSET(p) -= newbytes;
  475. NUM_ENT(p) += 2;
  476. }
  477. /*
  478.  * PUBLIC: int __ham_del_pair __P((DBC *, int));
  479.  */
  480. int
  481. __ham_del_pair(dbc, reclaim_page)
  482. DBC *dbc;
  483. int reclaim_page;
  484. {
  485. DB *dbp;
  486. DBT data_dbt, key_dbt;
  487. DB_LSN new_lsn, *n_lsn, tmp_lsn;
  488. DB_MPOOLFILE *mpf;
  489. HASH_CURSOR *hcp;
  490. PAGE *n_pagep, *nn_pagep, *p, *p_pagep;
  491. db_ham_mode op;
  492. db_indx_t ndx;
  493. db_pgno_t chg_pgno, pgno, tmp_pgno;
  494. int ret, t_ret;
  495. u_int32_t order;
  496. dbp = dbc->dbp;
  497. mpf = dbp->mpf;
  498. hcp = (HASH_CURSOR *)dbc->internal;
  499. n_pagep = p_pagep = nn_pagep = NULL;
  500. ndx = hcp->indx;
  501. if (hcp->page == NULL &&
  502.     (ret = mpf->get(mpf, &hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
  503. return (ret);
  504. p = hcp->page;
  505. /*
  506.  * We optimize for the normal case which is when neither the key nor
  507.  * the data are large.  In this case, we write a single log record
  508.  * and do the delete.  If either is large, we'll call __big_delete
  509.  * to remove the big item and then update the page to remove the
  510.  * entry referring to the big item.
  511.  */
  512. ret = 0;
  513. if (HPAGE_PTYPE(H_PAIRKEY(dbp, p, ndx)) == H_OFFPAGE) {
  514. memcpy(&pgno, HOFFPAGE_PGNO(P_ENTRY(dbp, p, H_KEYINDEX(ndx))),
  515.     sizeof(db_pgno_t));
  516. ret = __db_doff(dbc, pgno);
  517. }
  518. if (ret == 0)
  519. switch (HPAGE_PTYPE(H_PAIRDATA(dbp, p, ndx))) {
  520. case H_OFFPAGE:
  521. memcpy(&pgno,
  522.     HOFFPAGE_PGNO(P_ENTRY(dbp, p, H_DATAINDEX(ndx))),
  523.     sizeof(db_pgno_t));
  524. ret = __db_doff(dbc, pgno);
  525. break;
  526. case H_OFFDUP:
  527. case H_DUPLICATE:
  528. /*
  529.  * If we delete a pair that is/was a duplicate, then
  530.  * we had better clear the flag so that we update the
  531.  * cursor appropriately.
  532.  */
  533. F_CLR(hcp, H_ISDUP);
  534. break;
  535. }
  536. if (ret)
  537. return (ret);
  538. /* Now log the delete off this page. */
  539. if (DBC_LOGGING(dbc)) {
  540. key_dbt.data = P_ENTRY(dbp, p, H_KEYINDEX(ndx));
  541. key_dbt.size = LEN_HITEM(dbp, p, dbp->pgsize, H_KEYINDEX(ndx));
  542. data_dbt.data = P_ENTRY(dbp, p, H_DATAINDEX(ndx));
  543. data_dbt.size = LEN_HITEM(dbp, p, dbp->pgsize, H_DATAINDEX(ndx));
  544. if ((ret = __ham_insdel_log(dbp,
  545.     dbc->txn, &new_lsn, 0, DELPAIR, PGNO(p), (u_int32_t)ndx,
  546.     &LSN(p), &key_dbt, &data_dbt)) != 0)
  547. return (ret);
  548. } else
  549. LSN_NOT_LOGGED(new_lsn);
  550. /* Move lsn onto page. */
  551. LSN(p) = new_lsn;
  552. /* Do the delete. */
  553. __ham_dpair(dbp, p, ndx);
  554. /*
  555.  * Mark item deleted so that we don't try to return it, and
  556.  * so that we update the cursor correctly on the next call
  557.  * to next.
  558.  */
  559. F_SET(hcp, H_DELETED);
  560. F_CLR(hcp, H_OK);
  561. /*
  562.  * Update cursors that are on the page where the delete happend.
  563.  */
  564. if ((ret = __ham_c_update(dbc, 0, 0, 0)) != 0)
  565. return (ret);
  566. /*
  567.  * If we are locking, we will not maintain this, because it is
  568.  * a hot spot.
  569.  *
  570.  * XXX
  571.  * Perhaps we can retain incremental numbers and apply them later.
  572.  */
  573. if (!STD_LOCKING(dbc)) {
  574. --hcp->hdr->nelem;
  575. if ((ret = __ham_dirty_meta(dbc)) != 0)
  576. return (ret);
  577. }
  578. /*
  579.  * If we need to reclaim the page, then check if the page is empty.
  580.  * There are two cases.  If it's empty and it's not the first page
  581.  * in the bucket (i.e., the bucket page) then we can simply remove
  582.  * it. If it is the first chain in the bucket, then we need to copy
  583.  * the second page into it and remove the second page.
  584.  * If its the only page in the bucket we leave it alone.
  585.  */
  586. if (!reclaim_page ||
  587.     NUM_ENT(p) != 0 ||
  588.     (PREV_PGNO(p) == PGNO_INVALID && NEXT_PGNO(p) == PGNO_INVALID))
  589. return (mpf->set(mpf, p, DB_MPOOL_DIRTY));
  590. if (PREV_PGNO(p) == PGNO_INVALID) {
  591. /*
  592.  * First page in chain is empty and we know that there
  593.  * are more pages in the chain.
  594.  */
  595. if ((ret = mpf->get(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
  596. return (ret);
  597. if (NEXT_PGNO(n_pagep) != PGNO_INVALID && (ret =
  598.     mpf->get(mpf, &NEXT_PGNO(n_pagep), 0, &nn_pagep)) != 0)
  599. goto err;
  600. if (DBC_LOGGING(dbc)) {
  601. key_dbt.data = n_pagep;
  602. key_dbt.size = dbp->pgsize;
  603. if ((ret = __ham_copypage_log(dbp,
  604.     dbc->txn, &new_lsn, 0, PGNO(p),
  605.     &LSN(p), PGNO(n_pagep), &LSN(n_pagep),
  606.     NEXT_PGNO(n_pagep),
  607.     nn_pagep == NULL ? NULL : &LSN(nn_pagep),
  608.     &key_dbt)) != 0)
  609. goto err;
  610. } else
  611. LSN_NOT_LOGGED(new_lsn);
  612. /* Move lsn onto page. */
  613. LSN(p) = new_lsn; /* Structure assignment. */
  614. LSN(n_pagep) = new_lsn;
  615. if (NEXT_PGNO(n_pagep) != PGNO_INVALID)
  616. LSN(nn_pagep) = new_lsn;
  617. if (nn_pagep != NULL) {
  618. PREV_PGNO(nn_pagep) = PGNO(p);
  619. if ((ret =
  620.     mpf->put(mpf, nn_pagep, DB_MPOOL_DIRTY)) != 0) {
  621. nn_pagep = NULL;
  622. goto err;
  623. }
  624. }
  625. tmp_pgno = PGNO(p);
  626. tmp_lsn = LSN(p);
  627. memcpy(p, n_pagep, dbp->pgsize);
  628. PGNO(p) = tmp_pgno;
  629. LSN(p) = tmp_lsn;
  630. PREV_PGNO(p) = PGNO_INVALID;
  631. /*
  632.  * Update cursors to reflect the fact that records
  633.  * on the second page have moved to the first page.
  634.  */
  635. if ((ret = __ham_c_delpg(dbc, PGNO(n_pagep),
  636.     PGNO(p), 0, DB_HAM_DELFIRSTPG, &order)) != 0)
  637. goto err;
  638. /*
  639.  * Update the cursor to reflect its new position.
  640.  */
  641. hcp->indx = 0;
  642. hcp->pgno = PGNO(p);
  643. hcp->order += order;
  644. if ((ret = mpf->set(mpf, p, DB_MPOOL_DIRTY)) != 0)
  645. goto err;
  646. if ((ret = __db_free(dbc, n_pagep)) != 0) {
  647. n_pagep = NULL;
  648. goto err;
  649. }
  650. } else {
  651. if ((ret = mpf->get(mpf, &PREV_PGNO(p), 0, &p_pagep)) != 0)
  652. goto err;
  653. if (NEXT_PGNO(p) != PGNO_INVALID) {
  654. if ((ret =
  655.     mpf->get(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
  656. goto err;
  657. n_lsn = &LSN(n_pagep);
  658. } else {
  659. n_pagep = NULL;
  660. n_lsn = NULL;
  661. }
  662. NEXT_PGNO(p_pagep) = NEXT_PGNO(p);
  663. if (n_pagep != NULL)
  664. PREV_PGNO(n_pagep) = PGNO(p_pagep);
  665. if (DBC_LOGGING(dbc)) {
  666. if ((ret = __ham_newpage_log(dbp, dbc->txn,
  667.     &new_lsn, 0, DELOVFL, PREV_PGNO(p), &LSN(p_pagep),
  668.     PGNO(p), &LSN(p), NEXT_PGNO(p), n_lsn)) != 0)
  669. goto err;
  670. } else
  671. LSN_NOT_LOGGED(new_lsn);
  672. /* Move lsn onto page. */
  673. LSN(p_pagep) = new_lsn; /* Structure assignment. */
  674. if (n_pagep)
  675. LSN(n_pagep) = new_lsn;
  676. LSN(p) = new_lsn;
  677. if (NEXT_PGNO(p) == PGNO_INVALID) {
  678. /*
  679.  * There is no next page; put the cursor on the
  680.  * previous page as if we'd deleted the last item
  681.  * on that page, with index after the last valid
  682.  * entry.
  683.  *
  684.  * The deleted flag was set up above.
  685.  */
  686. hcp->pgno = PGNO(p_pagep);
  687. hcp->indx = NUM_ENT(p_pagep);
  688. op = DB_HAM_DELLASTPG;
  689. } else {
  690. /*
  691.  * There is a next page, so put the cursor at
  692.  * the beginning of it.
  693.  */
  694. hcp->pgno = NEXT_PGNO(p);
  695. hcp->indx = 0;
  696. op = DB_HAM_DELMIDPG;
  697. }
  698. /*
  699.  * Since we are about to delete the cursor page and we have
  700.  * just moved the cursor, we need to make sure that the
  701.  * old page pointer isn't left hanging around in the cursor.
  702.  */
  703. hcp->page = NULL;
  704. chg_pgno = PGNO(p);
  705. ret = __db_free(dbc, p);
  706. if ((t_ret =
  707.     mpf->put(mpf, p_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
  708. ret = t_ret;
  709. if (n_pagep != NULL && (t_ret =
  710.     mpf->put(mpf, n_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
  711. ret = t_ret;
  712. if (ret != 0)
  713. return (ret);
  714. if ((ret = __ham_c_delpg(dbc,
  715.     chg_pgno, hcp->pgno, hcp->indx, op, &order)) != 0)
  716. return (ret);
  717. hcp->order += order;
  718. }
  719. return (ret);
  720. err: /* Clean up any pages. */
  721. if (n_pagep != NULL)
  722. (void)mpf->put(mpf, n_pagep, 0);
  723. if (nn_pagep != NULL)
  724. (void)mpf->put(mpf, nn_pagep, 0);
  725. if (p_pagep != NULL)
  726. (void)mpf->put(mpf, p_pagep, 0);
  727. return (ret);
  728. }
  729. /*
  730.  * __ham_replpair --
  731.  * Given the key data indicated by the cursor, replace part/all of it
  732.  * according to the fields in the dbt.
  733.  *
  734.  * PUBLIC: int __ham_replpair __P((DBC *, DBT *, u_int32_t));
  735.  */
  736. int
  737. __ham_replpair(dbc, dbt, make_dup)
  738. DBC *dbc;
  739. DBT *dbt;
  740. u_int32_t make_dup;
  741. {
  742. DB *dbp;
  743. DBT old_dbt, tdata, tmp;
  744. DB_ENV *dbenv;
  745. DB_LSN new_lsn;
  746. HASH_CURSOR *hcp;
  747. int32_t change; /* XXX: Possible overflow. */
  748. u_int32_t dup_flag, len, memsize;
  749. int beyond_eor, is_big, ret, type;
  750. u_int8_t *beg, *dest, *end, *hk, *src;
  751. void *memp;
  752. /*
  753.  * Big item replacements are handled in generic code.
  754.  * Items that fit on the current page fall into 4 classes.
  755.  * 1. On-page element, same size
  756.  * 2. On-page element, new is bigger (fits)
  757.  * 3. On-page element, new is bigger (does not fit)
  758.  * 4. On-page element, old is bigger
  759.  * Numbers 1, 2, and 4 are essentially the same (and should
  760.  * be the common case).  We handle case 3 as a delete and
  761.  * add.
  762.  */
  763. dbp = dbc->dbp;
  764. dbenv = dbp->dbenv;
  765. hcp = (HASH_CURSOR *)dbc->internal;
  766. /*
  767.  * We need to compute the number of bytes that we are adding or
  768.  * removing from the entry.  Normally, we can simply substract
  769.  * the number of bytes we are replacing (dbt->dlen) from the
  770.  * number of bytes we are inserting (dbt->size).  However, if
  771.  * we are doing a partial put off the end of a record, then this
  772.  * formula doesn't work, because we are essentially adding
  773.  * new bytes.
  774.  */
  775. change = dbt->size - dbt->dlen;
  776. hk = H_PAIRDATA(dbp, hcp->page, hcp->indx);
  777. is_big = HPAGE_PTYPE(hk) == H_OFFPAGE;
  778. if (is_big)
  779. memcpy(&len, HOFFPAGE_TLEN(hk), sizeof(u_int32_t));
  780. else
  781. len = LEN_HKEYDATA(dbp, hcp->page,
  782.     dbp->pgsize, H_DATAINDEX(hcp->indx));
  783. beyond_eor = dbt->doff + dbt->dlen > len;
  784. if (beyond_eor)
  785. change += dbt->doff + dbt->dlen - len;
  786. if (change > (int32_t)P_FREESPACE(dbp, hcp->page) ||
  787.     beyond_eor || is_big) {
  788. /*
  789.  * Case 3 -- two subcases.
  790.  * A. This is not really a partial operation, but an overwrite.
  791.  *    Simple del and add works.
  792.  * B. This is a partial and we need to construct the data that
  793.  *    we are really inserting (yuck).
  794.  * In both cases, we need to grab the key off the page (in
  795.  * some cases we could do this outside of this routine; for
  796.  * cleanliness we do it here.  If you happen to be on a big
  797.  * key, this could be a performance hit).
  798.  */
  799. memset(&tmp, 0, sizeof(tmp));
  800. if ((ret =
  801.     __db_ret(dbp, hcp->page, H_KEYINDEX(hcp->indx),
  802.     &tmp, &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
  803. return (ret);
  804. /* Preserve duplicate info. */
  805. dup_flag = F_ISSET(hcp, H_ISDUP);
  806. if (dbt->doff == 0 && dbt->dlen == len) {
  807. ret = __ham_del_pair(dbc, 0);
  808. if (ret == 0)
  809.     ret = __ham_add_el(dbc,
  810. &tmp, dbt, dup_flag ? H_DUPLICATE : H_KEYDATA);
  811. } else { /* Case B */
  812. type = HPAGE_PTYPE(hk) != H_OFFPAGE ?
  813.     HPAGE_PTYPE(hk) : H_KEYDATA;
  814. memset(&tdata, 0, sizeof(tdata));
  815. memp = NULL;
  816. memsize = 0;
  817. if ((ret = __db_ret(dbp, hcp->page,
  818.     H_DATAINDEX(hcp->indx), &tdata, &memp, &memsize))
  819.     != 0)
  820. goto err;
  821. /* Now we can delete the item. */
  822. if ((ret = __ham_del_pair(dbc, 0)) != 0) {
  823. __os_free(dbenv, memp);
  824. goto err;
  825. }
  826. /* Now shift old data around to make room for new. */
  827. if (change > 0) {
  828. if ((ret = __os_realloc(dbenv,
  829.     tdata.size + change, &tdata.data)) != 0)
  830. return (ret);
  831. memp = tdata.data;
  832. memsize = tdata.size + change;
  833. memset((u_int8_t *)tdata.data + tdata.size,
  834.     0, change);
  835. }
  836. end = (u_int8_t *)tdata.data + tdata.size;
  837. src = (u_int8_t *)tdata.data + dbt->doff + dbt->dlen;
  838. if (src < end && tdata.size > dbt->doff + dbt->dlen) {
  839. len = tdata.size - dbt->doff - dbt->dlen;
  840. dest = src + change;
  841. memmove(dest, src, len);
  842. }
  843. memcpy((u_int8_t *)tdata.data + dbt->doff,
  844.     dbt->data, dbt->size);
  845. tdata.size += change;
  846. /* Now add the pair. */
  847. ret = __ham_add_el(dbc, &tmp, &tdata, type);
  848. __os_free(dbenv, memp);
  849. }
  850. F_SET(hcp, dup_flag);
  851. err: return (ret);
  852. }
  853. /*
  854.  * Set up pointer into existing data. Do it before the log
  855.  * message so we can use it inside of the log setup.
  856.  */
  857. beg = HKEYDATA_DATA(H_PAIRDATA(dbp, hcp->page, hcp->indx));
  858. beg += dbt->doff;
  859. /*
  860.  * If we are going to have to move bytes at all, figure out
  861.  * all the parameters here.  Then log the call before moving
  862.  * anything around.
  863.  */
  864. if (DBC_LOGGING(dbc)) {
  865. old_dbt.data = beg;
  866. old_dbt.size = dbt->dlen;
  867. if ((ret = __ham_replace_log(dbp,
  868.     dbc->txn, &new_lsn, 0, PGNO(hcp->page),
  869.     (u_int32_t)H_DATAINDEX(hcp->indx), &LSN(hcp->page),
  870.     (u_int32_t)dbt->doff, &old_dbt, dbt, make_dup)) != 0)
  871. return (ret);
  872. } else
  873. LSN_NOT_LOGGED(new_lsn);
  874. LSN(hcp->page) = new_lsn; /* Structure assignment. */
  875. __ham_onpage_replace(dbp, hcp->page, (u_int32_t)H_DATAINDEX(hcp->indx),
  876.     (int32_t)dbt->doff, change, dbt);
  877. return (0);
  878. }
  879. /*
  880.  * Replace data on a page with new data, possibly growing or shrinking what's
  881.  * there.  This is called on two different occasions. On one (from replpair)
  882.  * we are interested in changing only the data.  On the other (from recovery)
  883.  * we are replacing the entire data (header and all) with a new element.  In
  884.  * the latter case, the off argument is negative.
  885.  * pagep: the page that we're changing
  886.  * ndx: page index of the element that is growing/shrinking.
  887.  * off: Offset at which we are beginning the replacement.
  888.  * change: the number of bytes (+ or -) that the element is growing/shrinking.
  889.  * dbt: the new data that gets written at beg.
  890.  *
  891.  * PUBLIC: void __ham_onpage_replace __P((DB *, PAGE *, u_int32_t,
  892.  * PUBLIC:     int32_t, int32_t,  DBT *));
  893.  */
  894. void
  895. __ham_onpage_replace(dbp, pagep, ndx, off, change, dbt)
  896. DB *dbp;
  897. PAGE *pagep;
  898. u_int32_t ndx;
  899. int32_t off;
  900. int32_t change;
  901. DBT *dbt;
  902. {
  903. db_indx_t i, *inp;
  904. int32_t len;
  905. size_t pgsize;
  906. u_int8_t *src, *dest;
  907. int zero_me;
  908. pgsize = dbp->pgsize;
  909. inp = P_INP(dbp, pagep);
  910. if (change != 0) {
  911. zero_me = 0;
  912. src = (u_int8_t *)(pagep) + HOFFSET(pagep);
  913. if (off < 0)
  914. len = inp[ndx] - HOFFSET(pagep);
  915. else if ((u_int32_t)off >=
  916.     LEN_HKEYDATA(dbp, pagep, pgsize, ndx)) {
  917. len = (int32_t)(HKEYDATA_DATA(P_ENTRY(dbp, pagep, ndx))
  918.     + LEN_HKEYDATA(dbp, pagep, pgsize, ndx) - src);
  919. zero_me = 1;
  920. } else
  921. len = (int32_t)(
  922.     (HKEYDATA_DATA(P_ENTRY(dbp, pagep, ndx)) + off) -
  923.     src);
  924. dest = src - change;
  925. memmove(dest, src, len);
  926. if (zero_me)
  927. memset(dest + len, 0, change);
  928. /* Now update the indices. */
  929. for (i = ndx; i < NUM_ENT(pagep); i++)
  930. inp[i] -= change;
  931. HOFFSET(pagep) -= change;
  932. }
  933. if (off >= 0)
  934. memcpy(HKEYDATA_DATA(P_ENTRY(dbp, pagep, ndx)) + off,
  935.     dbt->data, dbt->size);
  936. else
  937. memcpy(P_ENTRY(dbp, pagep, ndx), dbt->data, dbt->size);
  938. }
  939. /*
  940.  * PUBLIC: int __ham_split_page __P((DBC *, u_int32_t, u_int32_t));
  941.  */
  942. int
  943. __ham_split_page(dbc, obucket, nbucket)
  944. DBC *dbc;
  945. u_int32_t obucket, nbucket;
  946. {
  947. DB *dbp;
  948. DBC **carray;
  949. DBT key, page_dbt;
  950. DB_ENV *dbenv;
  951. DB_LOCK block;
  952. DB_LSN new_lsn;
  953. DB_MPOOLFILE *mpf;
  954. HASH_CURSOR *hcp, *cp;
  955. PAGE **pp, *old_pagep, *temp_pagep, *new_pagep;
  956. db_indx_t n;
  957. db_pgno_t bucket_pgno, npgno, next_pgno;
  958. u_int32_t big_len, len;
  959. int found, i, ret, t_ret;
  960. void *big_buf;
  961. dbp = dbc->dbp;
  962. dbenv = dbp->dbenv;
  963. mpf = dbp->mpf;
  964. hcp = (HASH_CURSOR *)dbc->internal;
  965. temp_pagep = old_pagep = new_pagep = NULL;
  966. carray = NULL;
  967. LOCK_INIT(block);
  968. bucket_pgno = BUCKET_TO_PAGE(hcp, obucket);
  969. if ((ret = __db_lget(dbc,
  970.     0, bucket_pgno, DB_LOCK_WRITE, 0, &block)) != 0)
  971. goto err;
  972. if ((ret = mpf->get(mpf,
  973.     &bucket_pgno, DB_MPOOL_CREATE, &old_pagep)) != 0)
  974. goto err;
  975. /* Properly initialize the new bucket page. */
  976. npgno = BUCKET_TO_PAGE(hcp, nbucket);
  977. if ((ret = mpf->get(mpf, &npgno, DB_MPOOL_CREATE, &new_pagep)) != 0)
  978. goto err;
  979. P_INIT(new_pagep,
  980.     dbp->pgsize, npgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
  981. temp_pagep = hcp->split_buf;
  982. memcpy(temp_pagep, old_pagep, dbp->pgsize);
  983. if (DBC_LOGGING(dbc)) {
  984. page_dbt.size = dbp->pgsize;
  985. page_dbt.data = old_pagep;
  986. if ((ret = __ham_splitdata_log(dbp,
  987.     dbc->txn, &new_lsn, 0, SPLITOLD,
  988.     PGNO(old_pagep), &page_dbt, &LSN(old_pagep))) != 0)
  989. goto err;
  990. } else
  991. LSN_NOT_LOGGED(new_lsn);
  992. LSN(old_pagep) = new_lsn; /* Structure assignment. */
  993. P_INIT(old_pagep, dbp->pgsize, PGNO(old_pagep), PGNO_INVALID,
  994.     PGNO_INVALID, 0, P_HASH);
  995. big_len = 0;
  996. big_buf = NULL;
  997. key.flags = 0;
  998. while (temp_pagep != NULL) {
  999. if ((ret = __ham_get_clist(dbp,
  1000.     PGNO(temp_pagep), NDX_INVALID, &carray)) != 0)
  1001. goto err;
  1002. for (n = 0; n < (db_indx_t)NUM_ENT(temp_pagep); n += 2) {
  1003. if ((ret = __db_ret(dbp, temp_pagep,
  1004.     H_KEYINDEX(n), &key, &big_buf, &big_len)) != 0)
  1005. goto err;
  1006. if (__ham_call_hash(dbc, key.data, key.size) == obucket)
  1007. pp = &old_pagep;
  1008. else
  1009. pp = &new_pagep;
  1010. /*
  1011.  * Figure out how many bytes we need on the new
  1012.  * page to store the key/data pair.
  1013.  */
  1014. len = LEN_HITEM(dbp, temp_pagep, dbp->pgsize,
  1015.     H_DATAINDEX(n)) +
  1016.     LEN_HITEM(dbp, temp_pagep, dbp->pgsize,
  1017.     H_KEYINDEX(n)) +
  1018.     2 * sizeof(db_indx_t);
  1019. if (P_FREESPACE(dbp, *pp) < len) {
  1020. if (DBC_LOGGING(dbc)) {
  1021. page_dbt.size = dbp->pgsize;
  1022. page_dbt.data = *pp;
  1023. if ((ret = __ham_splitdata_log(dbp,
  1024.     dbc->txn, &new_lsn, 0,
  1025.     SPLITNEW, PGNO(*pp), &page_dbt,
  1026.     &LSN(*pp))) != 0)
  1027. goto err;
  1028. } else
  1029. LSN_NOT_LOGGED(new_lsn);
  1030. LSN(*pp) = new_lsn;
  1031. if ((ret =
  1032.     __ham_add_ovflpage(dbc, *pp, 1, pp)) != 0)
  1033. goto err;
  1034. }
  1035. /* Check if we need to update a cursor. */
  1036. if (carray != NULL) {
  1037. found = 0;
  1038. for (i = 0; carray[i] != NULL; i++) {
  1039. cp =
  1040.     (HASH_CURSOR *)carray[i]->internal;
  1041. if (cp->pgno == PGNO(temp_pagep) &&
  1042.     cp->indx == n) {
  1043. cp->pgno = PGNO(*pp);
  1044. cp->indx = NUM_ENT(*pp);
  1045. found = 1;
  1046. }
  1047. }
  1048. if (found && DBC_LOGGING(dbc) &&
  1049.     IS_SUBTRANSACTION(dbc->txn)) {
  1050. if ((ret =
  1051.     __ham_chgpg_log(dbp,
  1052.     dbc->txn, &new_lsn, 0,
  1053.     DB_HAM_SPLIT, PGNO(temp_pagep),
  1054.     PGNO(*pp), n, NUM_ENT(*pp))) != 0)
  1055. goto err;
  1056. }
  1057. }
  1058. __ham_copy_item(dbp, temp_pagep, H_KEYINDEX(n), *pp);
  1059. __ham_copy_item(dbp, temp_pagep, H_DATAINDEX(n), *pp);
  1060. }
  1061. next_pgno = NEXT_PGNO(temp_pagep);
  1062. /* Clear temp_page; if it's a link overflow page, free it. */
  1063. if (PGNO(temp_pagep) != bucket_pgno && (ret =
  1064.     __db_free(dbc, temp_pagep)) != 0) {
  1065. temp_pagep = NULL;
  1066. goto err;
  1067. }
  1068. if (next_pgno == PGNO_INVALID)
  1069. temp_pagep = NULL;
  1070. else if ((ret = mpf->get(
  1071.     mpf, &next_pgno, DB_MPOOL_CREATE, &temp_pagep)) != 0)
  1072. goto err;
  1073. if (temp_pagep != NULL) {
  1074. if (DBC_LOGGING(dbc)) {
  1075. page_dbt.size = dbp->pgsize;
  1076. page_dbt.data = temp_pagep;
  1077. if ((ret = __ham_splitdata_log(dbp,
  1078.     dbc->txn, &new_lsn, 0,
  1079.     SPLITOLD, PGNO(temp_pagep),
  1080.     &page_dbt, &LSN(temp_pagep))) != 0)
  1081. goto err;
  1082. } else
  1083. LSN_NOT_LOGGED(new_lsn);
  1084. LSN(temp_pagep) = new_lsn;
  1085. }
  1086. if (carray != NULL) /* We never knew its size. */
  1087. __os_free(dbenv, carray);
  1088. carray = NULL;
  1089. }
  1090. if (big_buf != NULL)
  1091. __os_free(dbenv, big_buf);
  1092. /*
  1093.  * If the original bucket spanned multiple pages, then we've got
  1094.  * a pointer to a page that used to be on the bucket chain.  It
  1095.  * should be deleted.
  1096.  */
  1097. if (temp_pagep != NULL && PGNO(temp_pagep) != bucket_pgno &&
  1098.     (ret = __db_free(dbc, temp_pagep)) != 0) {
  1099. temp_pagep = NULL;
  1100. goto err;
  1101. }
  1102. /*
  1103.  * Write new buckets out.
  1104.  */
  1105. if (DBC_LOGGING(dbc)) {
  1106. page_dbt.size = dbp->pgsize;
  1107. page_dbt.data = old_pagep;
  1108. if ((ret = __ham_splitdata_log(dbp, dbc->txn,
  1109.     &new_lsn, 0, SPLITNEW, PGNO(old_pagep), &page_dbt,
  1110.     &LSN(old_pagep))) != 0)
  1111. goto err;
  1112. LSN(old_pagep) = new_lsn;
  1113. page_dbt.data = new_pagep;
  1114. if ((ret = __ham_splitdata_log(dbp, dbc->txn, &new_lsn, 0,
  1115.     SPLITNEW, PGNO(new_pagep), &page_dbt,
  1116.     &LSN(new_pagep))) != 0)
  1117. goto err;
  1118. LSN(new_pagep) = new_lsn;
  1119. } else {
  1120. LSN_NOT_LOGGED(LSN(old_pagep));
  1121. LSN_NOT_LOGGED(LSN(new_pagep));
  1122. }
  1123. ret = mpf->put(mpf, old_pagep, DB_MPOOL_DIRTY);
  1124. if ((t_ret =
  1125.     mpf->put(mpf, new_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
  1126. ret = t_ret;
  1127. if (0) {
  1128. err: if (old_pagep != NULL)
  1129. (void)mpf->put(mpf, old_pagep, DB_MPOOL_DIRTY);
  1130. if (new_pagep != NULL)
  1131. (void)mpf->put(mpf, new_pagep, DB_MPOOL_DIRTY);
  1132. if (temp_pagep != NULL && PGNO(temp_pagep) != bucket_pgno)
  1133. (void)mpf->put(mpf, temp_pagep, DB_MPOOL_DIRTY);
  1134. }
  1135. if (LOCK_ISSET(block))
  1136. __TLPUT(dbc, block);
  1137. if (carray != NULL) /* We never knew its size. */
  1138. __os_free(dbenv, carray);
  1139. return (ret);
  1140. }
  1141. /*
  1142.  * Add the given pair to the page.  The page in question may already be
  1143.  * held (i.e. it was already gotten).  If it is, then the page is passed
  1144.  * in via the pagep parameter.  On return, pagep will contain the page
  1145.  * to which we just added something.  This allows us to link overflow
  1146.  * pages and return the new page having correctly put the last page.
  1147.  *
  1148.  * PUBLIC: int __ham_add_el __P((DBC *, const DBT *, const DBT *, int));
  1149.  */
  1150. int
  1151. __ham_add_el(dbc, key, val, type)
  1152. DBC *dbc;
  1153. const DBT *key, *val;
  1154. int type;
  1155. {
  1156. const DBT *pkey, *pdata;
  1157. DB *dbp;
  1158. DBT key_dbt, data_dbt;
  1159. DB_LSN new_lsn;
  1160. DB_MPOOLFILE *mpf;
  1161. HASH_CURSOR *hcp;
  1162. HOFFPAGE doff, koff;
  1163. db_pgno_t next_pgno, pgno;
  1164. u_int32_t data_size, key_size, pairsize, rectype;
  1165. int do_expand, is_keybig, is_databig, ret;
  1166. int key_type, data_type;
  1167. dbp = dbc->dbp;
  1168. mpf = dbp->mpf;
  1169. hcp = (HASH_CURSOR *)dbc->internal;
  1170. do_expand = 0;
  1171. pgno = hcp->seek_found_page != PGNO_INVALID ?
  1172.     hcp->seek_found_page : hcp->pgno;
  1173. if (hcp->page == NULL &&
  1174.     (ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
  1175. return (ret);
  1176. key_size = HKEYDATA_PSIZE(key->size);
  1177. data_size = HKEYDATA_PSIZE(val->size);
  1178. is_keybig = ISBIG(hcp, key->size);
  1179. is_databig = ISBIG(hcp, val->size);
  1180. if (is_keybig)
  1181. key_size = HOFFPAGE_PSIZE;
  1182. if (is_databig)
  1183. data_size = HOFFPAGE_PSIZE;
  1184. pairsize = key_size + data_size;
  1185. /* Advance to first page in chain with room for item. */
  1186. while (H_NUMPAIRS(hcp->page) && NEXT_PGNO(hcp->page) != PGNO_INVALID) {
  1187. /*
  1188.  * This may not be the end of the chain, but the pair may fit
  1189.  * anyway.  Check if it's a bigpair that fits or a regular
  1190.  * pair that fits.
  1191.  */
  1192. if (P_FREESPACE(dbp, hcp->page) >= pairsize)
  1193. break;
  1194. next_pgno = NEXT_PGNO(hcp->page);
  1195. if ((ret = __ham_next_cpage(dbc, next_pgno, 0)) != 0)
  1196. return (ret);
  1197. }
  1198. /*
  1199.  * Check if we need to allocate a new page.
  1200.  */
  1201. if (P_FREESPACE(dbp, hcp->page) < pairsize) {
  1202. do_expand = 1;
  1203. if ((ret = __ham_add_ovflpage(dbc,
  1204.     (PAGE *)hcp->page, 1, (PAGE **)&hcp->page)) != 0)
  1205. return (ret);
  1206. hcp->pgno = PGNO(hcp->page);
  1207. }
  1208. /*
  1209.  * Update cursor.
  1210.  */
  1211. hcp->indx = NUM_ENT(hcp->page);
  1212. F_CLR(hcp, H_DELETED);
  1213. if (is_keybig) {
  1214. koff.type = H_OFFPAGE;
  1215. UMRW_SET(koff.unused[0]);
  1216. UMRW_SET(koff.unused[1]);
  1217. UMRW_SET(koff.unused[2]);
  1218. if ((ret = __db_poff(dbc, key, &koff.pgno)) != 0)
  1219. return (ret);
  1220. koff.tlen = key->size;
  1221. key_dbt.data = &koff;
  1222. key_dbt.size = sizeof(koff);
  1223. pkey = &key_dbt;
  1224. key_type = H_OFFPAGE;
  1225. } else {
  1226. pkey = key;
  1227. key_type = H_KEYDATA;
  1228. }
  1229. if (is_databig) {
  1230. doff.type = H_OFFPAGE;
  1231. UMRW_SET(doff.unused[0]);
  1232. UMRW_SET(doff.unused[1]);
  1233. UMRW_SET(doff.unused[2]);
  1234. if ((ret = __db_poff(dbc, val, &doff.pgno)) != 0)
  1235. return (ret);
  1236. doff.tlen = val->size;
  1237. data_dbt.data = &doff;
  1238. data_dbt.size = sizeof(doff);
  1239. pdata = &data_dbt;
  1240. data_type = H_OFFPAGE;
  1241. } else {
  1242. pdata = val;
  1243. data_type = type;
  1244. }
  1245. if (DBC_LOGGING(dbc)) {
  1246. rectype = PUTPAIR;
  1247. if (is_databig)
  1248. rectype |= PAIR_DATAMASK;
  1249. if (is_keybig)
  1250. rectype |= PAIR_KEYMASK;
  1251. if (type == H_DUPLICATE)
  1252. rectype |= PAIR_DUPMASK;
  1253. if ((ret = __ham_insdel_log(dbp, dbc->txn, &new_lsn, 0,
  1254.     rectype, PGNO(hcp->page), (u_int32_t)NUM_ENT(hcp->page),
  1255.     &LSN(hcp->page), pkey, pdata)) != 0)
  1256. return (ret);
  1257. } else
  1258. LSN_NOT_LOGGED(new_lsn);
  1259. /* Move lsn onto page. */
  1260. LSN(hcp->page) = new_lsn; /* Structure assignment. */
  1261. __ham_putitem(dbp, hcp->page, pkey, key_type);
  1262. __ham_putitem(dbp, hcp->page, pdata, data_type);
  1263. /*
  1264.  * For splits, we are going to update item_info's page number
  1265.  * field, so that we can easily return to the same page the
  1266.  * next time we come in here.  For other operations, this shouldn't
  1267.  * matter, since odds are this is the last thing that happens before
  1268.  * we return to the user program.
  1269.  */
  1270. hcp->pgno = PGNO(hcp->page);
  1271. /*
  1272.  * XXX
  1273.  * Maybe keep incremental numbers here.
  1274.  */
  1275. if (!STD_LOCKING(dbc)) {
  1276. hcp->hdr->nelem++;
  1277. if ((ret = __ham_dirty_meta(dbc)) != 0)
  1278. return (ret);
  1279. }
  1280. if (do_expand || (hcp->hdr->ffactor != 0 &&
  1281.     (u_int32_t)H_NUMPAIRS(hcp->page) > hcp->hdr->ffactor))
  1282. F_SET(hcp, H_EXPAND);
  1283. return (0);
  1284. }
  1285. /*
  1286.  * Special __putitem call used in splitting -- copies one entry to
  1287.  * another.  Works for all types of hash entries (H_OFFPAGE, H_KEYDATA,
  1288.  * H_DUPLICATE, H_OFFDUP).  Since we log splits at a high level, we
  1289.  * do not need to do any logging here.
  1290.  *
  1291.  * PUBLIC: void __ham_copy_item __P((DB *, PAGE *, u_int32_t, PAGE *));
  1292.  */
  1293. void
  1294. __ham_copy_item(dbp, src_page, src_ndx, dest_page)
  1295. DB *dbp;
  1296. PAGE *src_page;
  1297. u_int32_t src_ndx;
  1298. PAGE *dest_page;
  1299. {
  1300. u_int32_t len;
  1301. size_t pgsize;
  1302. void *src, *dest;
  1303. db_indx_t *inp;
  1304. pgsize = dbp->pgsize;
  1305. inp = P_INP(dbp, dest_page);
  1306. /*
  1307.  * Copy the key and data entries onto this new page.
  1308.  */
  1309. src = P_ENTRY(dbp, src_page, src_ndx);
  1310. /* Set up space on dest. */
  1311. len = (u_int32_t)LEN_HITEM(dbp, src_page, pgsize, src_ndx);
  1312. HOFFSET(dest_page) -= len;
  1313. inp[NUM_ENT(dest_page)] = HOFFSET(dest_page);
  1314. dest = P_ENTRY(dbp, dest_page, NUM_ENT(dest_page));
  1315. NUM_ENT(dest_page)++;
  1316. memcpy(dest, src, len);
  1317. }
  1318. /*
  1319.  *
  1320.  * Returns:
  1321.  * pointer on success
  1322.  * NULL on error
  1323.  *
  1324.  * PUBLIC: int __ham_add_ovflpage __P((DBC *, PAGE *, int, PAGE **));
  1325.  */
  1326. int
  1327. __ham_add_ovflpage(dbc, pagep, release, pp)
  1328. DBC *dbc;
  1329. PAGE *pagep;
  1330. int release;
  1331. PAGE **pp;
  1332. {
  1333. DB *dbp;
  1334. DB_LSN new_lsn;
  1335. DB_MPOOLFILE *mpf;
  1336. PAGE *new_pagep;
  1337. int ret;
  1338. dbp = dbc->dbp;
  1339. mpf = dbp->mpf;
  1340. if ((ret = __db_new(dbc, P_HASH, &new_pagep)) != 0)
  1341. return (ret);
  1342. if (DBC_LOGGING(dbc)) {
  1343. if ((ret = __ham_newpage_log(dbp, dbc->txn, &new_lsn, 0,
  1344.     PUTOVFL, PGNO(pagep), &LSN(pagep),
  1345.     PGNO(new_pagep), &LSN(new_pagep), PGNO_INVALID, NULL)) != 0)
  1346. return (ret);
  1347. } else
  1348. LSN_NOT_LOGGED(new_lsn);
  1349. /* Move lsn onto page. */
  1350. LSN(pagep) = LSN(new_pagep) = new_lsn;
  1351. NEXT_PGNO(pagep) = PGNO(new_pagep);
  1352. PREV_PGNO(new_pagep) = PGNO(pagep);
  1353. if (release)
  1354. ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY);
  1355. *pp = new_pagep;
  1356. return (ret);
  1357. }
  1358. /*
  1359.  * PUBLIC: int __ham_get_cpage __P((DBC *, db_lockmode_t));
  1360.  */
  1361. int
  1362. __ham_get_cpage(dbc, mode)
  1363. DBC *dbc;
  1364. db_lockmode_t mode;
  1365. {
  1366. DB *dbp;
  1367. DB_LOCK tmp_lock;
  1368. DB_MPOOLFILE *mpf;
  1369. HASH_CURSOR *hcp;
  1370. int ret;
  1371. dbp = dbc->dbp;
  1372. mpf = dbp->mpf;
  1373. hcp = (HASH_CURSOR *)dbc->internal;
  1374. ret = 0;
  1375. /*
  1376.  * There are four cases with respect to buckets and locks.
  1377.  * 1. If there is no lock held, then if we are locking, we should
  1378.  *    get the lock.
  1379.  * 2. If there is a lock held, it's for the current bucket, and it's
  1380.  *    for the right mode, we don't need to do anything.
  1381.  * 3. If there is a lock held for the current bucket but it's not
  1382.  *    strong enough, we need to upgrade.
  1383.  * 4. If there is a lock, but it's for a different bucket, then we need
  1384.  *    to release the existing lock and get a new lock.
  1385.  */
  1386. LOCK_INIT(tmp_lock);
  1387. if (STD_LOCKING(dbc)) {
  1388. if (hcp->lbucket != hcp->bucket && /* Case 4 */
  1389.     (ret = __TLPUT(dbc, hcp->lock)) != 0)
  1390. return (ret);
  1391. if ((LOCK_ISSET(hcp->lock) &&
  1392.     (hcp->lock_mode == DB_LOCK_READ &&
  1393.     mode == DB_LOCK_WRITE))) {
  1394. /* Case 3. */
  1395. tmp_lock = hcp->lock;
  1396. LOCK_INIT(hcp->lock);
  1397. }
  1398. /* Acquire the lock. */
  1399. if (!LOCK_ISSET(hcp->lock))
  1400. /* Cases 1, 3, and 4. */
  1401. if ((ret = __ham_lock_bucket(dbc, mode)) != 0)
  1402. return (ret);
  1403. if (ret == 0) {
  1404. hcp->lock_mode = mode;
  1405. hcp->lbucket = hcp->bucket;
  1406. if (LOCK_ISSET(tmp_lock))
  1407. /* Case 3: release the original lock. */
  1408. ret =
  1409.     dbp->dbenv->lock_put(dbp->dbenv, &tmp_lock);
  1410. } else if (LOCK_ISSET(tmp_lock))
  1411. hcp->lock = tmp_lock;
  1412. }
  1413. if (ret == 0 && hcp->page == NULL) {
  1414. if (hcp->pgno == PGNO_INVALID)
  1415. hcp->pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
  1416. if ((ret = mpf->get(mpf,
  1417.     &hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
  1418. return (ret);
  1419. }
  1420. return (0);
  1421. }
  1422. /*
  1423.  * Get a new page at the cursor, putting the last page if necessary.
  1424.  * If the flag is set to H_ISDUP, then we are talking about the
  1425.  * duplicate page, not the main page.
  1426.  *
  1427.  * PUBLIC: int __ham_next_cpage __P((DBC *, db_pgno_t, int));
  1428.  */
  1429. int
  1430. __ham_next_cpage(dbc, pgno, dirty)
  1431. DBC *dbc;
  1432. db_pgno_t pgno;
  1433. int dirty;
  1434. {
  1435. DB *dbp;
  1436. DB_MPOOLFILE *mpf;
  1437. HASH_CURSOR *hcp;
  1438. PAGE *p;
  1439. int ret;
  1440. dbp = dbc->dbp;
  1441. mpf = dbp->mpf;
  1442. hcp = (HASH_CURSOR *)dbc->internal;
  1443. if (hcp->page != NULL &&
  1444.     (ret = mpf->put(mpf, hcp->page, dirty ? DB_MPOOL_DIRTY : 0)) != 0)
  1445. return (ret);
  1446. hcp->page = NULL;
  1447. if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &p)) != 0)
  1448. return (ret);
  1449. hcp->page = p;
  1450. hcp->pgno = pgno;
  1451. hcp->indx = 0;
  1452. return (0);
  1453. }
  1454. /*
  1455.  * __ham_lock_bucket --
  1456.  * Get the lock on a particular bucket.
  1457.  *
  1458.  * PUBLIC: int __ham_lock_bucket __P((DBC *, db_lockmode_t));
  1459.  */
  1460. int
  1461. __ham_lock_bucket(dbc, mode)
  1462. DBC *dbc;
  1463. db_lockmode_t mode;
  1464. {
  1465. HASH_CURSOR *hcp;
  1466. db_pgno_t pgno;
  1467. int gotmeta, ret;
  1468. hcp = (HASH_CURSOR *)dbc->internal;
  1469. gotmeta = hcp->hdr == NULL ? 1 : 0;
  1470. if (gotmeta)
  1471. if ((ret = __ham_get_meta(dbc)) != 0)
  1472. return (ret);
  1473. pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
  1474. if (gotmeta)
  1475. if ((ret = __ham_release_meta(dbc)) != 0)
  1476. return (ret);
  1477. ret = __db_lget(dbc, 0, pgno, mode, 0, &hcp->lock);
  1478. hcp->lock_mode = mode;
  1479. return (ret);
  1480. }
  1481. /*
  1482.  * __ham_dpair --
  1483.  * Delete a pair on a page, paying no attention to what the pair
  1484.  * represents.  The caller is responsible for freeing up duplicates
  1485.  * or offpage entries that might be referenced by this pair.
  1486.  *
  1487.  * Recovery assumes that this may be called without the metadata
  1488.  * page pinned.
  1489.  *
  1490.  * PUBLIC: void __ham_dpair __P((DB *, PAGE *, u_int32_t));
  1491.  */
  1492. void
  1493. __ham_dpair(dbp, p, indx)
  1494. DB *dbp;
  1495. PAGE *p;
  1496. u_int32_t indx;
  1497. {
  1498. db_indx_t delta, n, *inp;
  1499. u_int8_t *dest, *src;
  1500. inp = P_INP(dbp, p);
  1501. /*
  1502.  * Compute "delta", the amount we have to shift all of the
  1503.  * offsets.  To find the delta, we just need to calculate
  1504.  * the size of the pair of elements we are removing.
  1505.  */
  1506. delta = H_PAIRSIZE(dbp, p, dbp->pgsize, indx);
  1507. /*
  1508.  * The hard case: we want to remove something other than
  1509.  * the last item on the page.  We need to shift data and
  1510.  * offsets down.
  1511.  */
  1512. if ((db_indx_t)indx != NUM_ENT(p) - 2) {
  1513. /*
  1514.  * Move the data: src is the first occupied byte on
  1515.  * the page. (Length is delta.)
  1516.  */
  1517. src = (u_int8_t *)p + HOFFSET(p);
  1518. /*
  1519.  * Destination is delta bytes beyond src.  This might
  1520.  * be an overlapping copy, so we have to use memmove.
  1521.  */
  1522. dest = src + delta;
  1523. memmove(dest, src, inp[H_DATAINDEX(indx)] - HOFFSET(p));
  1524. }
  1525. /* Adjust page metadata. */
  1526. HOFFSET(p) = HOFFSET(p) + delta;
  1527. NUM_ENT(p) = NUM_ENT(p) - 2;
  1528. /* Adjust the offsets. */
  1529. for (n = (db_indx_t)indx; n < (db_indx_t)(NUM_ENT(p)); n++)
  1530. inp[n] = inp[n + 2] + delta;
  1531. }
  1532. /*
  1533.  * __ham_c_delpg --
  1534.  *
  1535.  * Adjust the cursors after we've emptied a page in a bucket, taking
  1536.  * care that when we move cursors pointing to deleted items, their
  1537.  * orders don't collide with the orders of cursors on the page we move
  1538.  * them to (since after this function is called, cursors with the same
  1539.  * index on the two pages will be otherwise indistinguishable--they'll
  1540.  * all have pgno new_pgno).  There are three cases:
  1541.  *
  1542.  * 1) The emptied page is the first page in the bucket.  In this
  1543.  * case, we've copied all the items from the second page into the
  1544.  * first page, so the first page is new_pgno and the second page is
  1545.  * old_pgno.  new_pgno is empty, but can have deleted cursors
  1546.  * pointing at indx 0, so we need to be careful of the orders
  1547.  * there.  This is DB_HAM_DELFIRSTPG.
  1548.  *
  1549.  * 2) The page is somewhere in the middle of a bucket.  Our caller
  1550.  * can just delete such a page, so it's old_pgno.  old_pgno is
  1551.  * empty, but may have deleted cursors pointing at indx 0, so we
  1552.  * need to be careful of indx 0 when we move those cursors to
  1553.  * new_pgno.  This is DB_HAM_DELMIDPG.
  1554.  *
  1555.  * 3) The page is the last in a bucket.  Again the empty page is
  1556.  * old_pgno, and again it should only have cursors that are deleted
  1557.  * and at indx == 0.  This time, though, there's no next page to
  1558.  * move them to, so we set them to indx == num_ent on the previous
  1559.  * page--and indx == num_ent is the index whose cursors we need to
  1560.  * be careful of.  This is DB_HAM_DELLASTPG.
  1561.  */
  1562. static int
  1563. __ham_c_delpg(dbc, old_pgno, new_pgno, num_ent, op, orderp)
  1564. DBC *dbc;
  1565. db_pgno_t old_pgno, new_pgno;
  1566. u_int32_t num_ent;
  1567. db_ham_mode op;
  1568. u_int32_t *orderp;
  1569. {
  1570. DB *dbp, *ldbp;
  1571. DB_ENV *dbenv;
  1572. DB_LSN lsn;
  1573. DB_TXN *my_txn;
  1574. DBC *cp;
  1575. HASH_CURSOR *hcp;
  1576. int found, ret;
  1577. db_indx_t indx;
  1578. u_int32_t order;
  1579. /* Which is the worrisome index? */
  1580. indx = (op == DB_HAM_DELLASTPG) ? num_ent : 0;
  1581. dbp = dbc->dbp;
  1582. dbenv = dbp->dbenv;
  1583. my_txn = IS_SUBTRANSACTION(dbc->txn) ? dbc->txn : NULL;
  1584. found = 0;
  1585. MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
  1586. /*
  1587.  * Find the highest order of any cursor our movement
  1588.  * may collide with.
  1589.  */
  1590. order = 1;
  1591. for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
  1592.     ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
  1593.     ldbp = LIST_NEXT(ldbp, dblistlinks)) {
  1594. MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
  1595. for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
  1596.     cp = TAILQ_NEXT(cp, links)) {
  1597. if (cp == dbc || cp->dbtype != DB_HASH)
  1598. continue;
  1599. hcp = (HASH_CURSOR *)cp->internal;
  1600. if (hcp->pgno == new_pgno) {
  1601. if (hcp->indx == indx &&
  1602.     F_ISSET(hcp, H_DELETED) &&
  1603.     hcp->order >= order)
  1604. order = hcp->order + 1;
  1605. DB_ASSERT(op != DB_HAM_DELFIRSTPG ||
  1606.     hcp->indx == NDX_INVALID ||
  1607.     (hcp->indx == 0 &&
  1608.     F_ISSET(hcp, H_DELETED)));
  1609. }
  1610. }
  1611. MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
  1612. }
  1613. for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
  1614.     ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
  1615.     ldbp = LIST_NEXT(ldbp, dblistlinks)) {
  1616. MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
  1617. for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
  1618.     cp = TAILQ_NEXT(cp, links)) {
  1619. if (cp == dbc || cp->dbtype != DB_HASH)
  1620. continue;
  1621. hcp = (HASH_CURSOR *)cp->internal;
  1622. if (hcp->pgno == old_pgno) {
  1623. switch (op) {
  1624. case DB_HAM_DELFIRSTPG:
  1625. /*
  1626.  * We're moving all items,
  1627.  * regardless of index.
  1628.  */
  1629. hcp->pgno = new_pgno;
  1630. /*
  1631.  * But we have to be careful of
  1632.  * the order values.
  1633.  */
  1634. if (hcp->indx == indx)
  1635. hcp->order += order;
  1636. break;
  1637. case DB_HAM_DELMIDPG:
  1638. hcp->pgno = new_pgno;
  1639. DB_ASSERT(hcp->indx == 0 &&
  1640.     F_ISSET(hcp, H_DELETED));
  1641. hcp->order += order;
  1642. break;
  1643. case DB_HAM_DELLASTPG:
  1644. hcp->pgno = new_pgno;
  1645. DB_ASSERT(hcp->indx == 0 &&
  1646.     F_ISSET(hcp, H_DELETED));
  1647. hcp->indx = indx;
  1648. hcp->order += order;
  1649. break;
  1650. default:
  1651. DB_ASSERT(0);
  1652. return (__db_panic(dbenv, EINVAL));
  1653. }
  1654. if (my_txn != NULL && cp->txn != my_txn)
  1655. found = 1;
  1656. }
  1657. }
  1658. MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
  1659. }
  1660. MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
  1661. if (found != 0 && DBC_LOGGING(dbc)) {
  1662. if ((ret = __ham_chgpg_log(dbp, my_txn, &lsn, 0, op,
  1663.     old_pgno, new_pgno, indx, order)) != 0)
  1664. return (ret);
  1665. }
  1666. *orderp = order;
  1667. return (0);
  1668. }