F_SET(cursorp, H_DELETED);
__ham_del_pair(hashp, cursorp, reclaim_page)	HTAB *hashp;	HASH_CURSOR *cursorp;	int reclaim_page;{	DBT data_dbt, key_dbt;	DB_ENV *dbenv;	DB_LSN new_lsn, *n_lsn, tmp_lsn;	PAGE *p;	db_indx_t ndx;	db_pgno_t chg_pgno, pgno;	int ret, tret;	dbenv = hashp->dbp->dbenv;	ndx = cursorp->bndx;	if (cursorp->pagep == NULL && (ret =	    __ham_get_page(hashp->dbp, cursorp->pgno, &cursorp->pagep)) != 0)		return (ret);	p = cursorp->pagep;	/*	 * We optimize for the normal case which is when neither the key nor	 * the data are large.  In this case, we write a single log record	 * and do the delete.  If either is large, we'll call __big_delete	 * to remove the big item and then update the page to remove the	 * entry referring to the big item.	 */	ret = 0;	if (HPAGE_PTYPE(H_PAIRKEY(p, ndx)) == H_OFFPAGE) {		memcpy(&pgno, HOFFPAGE_PGNO(P_ENTRY(p, H_KEYINDEX(ndx))),		    sizeof(db_pgno_t));		ret = __db_doff(hashp->dbp, pgno, __ham_del_page);	}	if (ret == 0)		switch (HPAGE_PTYPE(H_PAIRDATA(p, ndx))) {		case H_OFFPAGE:			memcpy(&pgno,			    HOFFPAGE_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))),			    sizeof(db_pgno_t));			ret = __db_doff(hashp->dbp, pgno, __ham_del_page);			break;		case H_OFFDUP:			memcpy(&pgno,			    HOFFDUP_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))),			    sizeof(db_pgno_t));			ret = __db_ddup(hashp->dbp, pgno, __ham_del_page);			F_CLR(cursorp, H_ISDUP);			break;		case H_DUPLICATE:			/*			 * If we delete a pair that is/was a duplicate, then			 * we had better clear the flag so that we update the			 * cursor appropriately.			 */			F_CLR(cursorp, H_ISDUP);			break;		}	if (ret)		return (ret);	/* Now log the delete off this page. */	if (DB_LOGGING(hashp->dbp)) {		key_dbt.data = P_ENTRY(p, H_KEYINDEX(ndx));		key_dbt.size =		    LEN_HITEM(p, hashp->hdr->pagesize, H_KEYINDEX(ndx));		data_dbt.data = P_ENTRY(p, H_DATAINDEX(ndx));		data_dbt.size =		    LEN_HITEM(p, hashp->hdr->pagesize, H_DATAINDEX(ndx));		if ((ret = __ham_insdel_log(dbenv->lg_info,		    (DB_TXN *)hashp->dbp->txn, &new_lsn, 0, DELPAIR,		    hashp->dbp->log_fileid, PGNO(p), (u_int32_t)ndx,		    &LSN(p), &key_dbt, &data_dbt)) != 0)			return (ret);		/* Move lsn onto page. */		LSN(p) = new_lsn;	}	__ham_dpair(hashp->dbp, p, ndx);	/*	 * If we are locking, we will not maintain this.	 * XXXX perhaps we can retain incremental numbers and apply them	 * later.	 */	if (!F_ISSET(hashp->dbp, DB_AM_LOCKING))		--hashp->hdr->nelem;	/*	 * If we need to reclaim the page, then check if the page is empty.	 * There are two cases.  If it's empty and it's not the first page	 * in the bucket (i.e., the bucket page) then we can simply remove	 * it. If it is the first chain in the bucket, then we need to copy	 * the second page into it and remove the second page.	 */	if (reclaim_page && NUM_ENT(p) == 0 && PREV_PGNO(p) == PGNO_INVALID &&	    NEXT_PGNO(p) != PGNO_INVALID) {		PAGE *n_pagep, *nn_pagep;		db_pgno_t tmp_pgno;		/*		 * First page in chain is empty and we know that there		 * are more pages in the chain.		 */		if ((ret =		    __ham_get_page(hashp->dbp, NEXT_PGNO(p), &n_pagep)) != 0)			return (ret);		if (NEXT_PGNO(n_pagep) != PGNO_INVALID) {			if ((ret =			    __ham_get_page(hashp->dbp, NEXT_PGNO(n_pagep),			    &nn_pagep)) != 0) {				(void) __ham_put_page(hashp->dbp, n_pagep, 0);				return (ret);			}		}		if (DB_LOGGING(hashp->dbp)) {			key_dbt.data = n_pagep;			key_dbt.size = hashp->hdr->pagesize;			if ((ret = __ham_copypage_log(dbenv->lg_info,			    (DB_TXN *)hashp->dbp->txn, &new_lsn, 0,			    hashp->dbp->log_fileid, PGNO(p), &LSN(p),			    PGNO(n_pagep), &LSN(n_pagep), NEXT_PGNO(n_pagep),			    NEXT_PGNO(n_pagep) == PGNO_INVALID ? NULL :			    &LSN(nn_pagep), &key_dbt)) != 0)				return (ret);			/* Move lsn onto page. */			LSN(p) = new_lsn;	/* Structure assignment. */			LSN(n_pagep) = new_lsn;			if (NEXT_PGNO(n_pagep) != PGNO_INVALID)				LSN(nn_pagep) = new_lsn;		}		if (NEXT_PGNO(n_pagep) != PGNO_INVALID) {			PREV_PGNO(nn_pagep) = PGNO(p);			(void)__ham_put_page(hashp->dbp, nn_pagep, 1);		}		tmp_pgno = PGNO(p);		tmp_lsn = LSN(p);		memcpy(p, n_pagep, hashp->hdr->pagesize);		PGNO(p) = tmp_pgno;		LSN(p) = tmp_lsn;		PREV_PGNO(p) = PGNO_INVALID;		/*		 * Cursor is advanced to the beginning of the next page.		 */		cursorp->bndx = NDX_INVALID;		cursorp->pgno = PGNO(p);		chg_pgno = PGNO(p);		if ((ret = __ham_dirty_page(hashp, p)) != 0 ||		    (ret = __ham_del_page(hashp->dbp, n_pagep)) != 0)			return (ret);	} else if (reclaim_page &&	    NUM_ENT(p) == 0 && PREV_PGNO(p) != PGNO_INVALID) {		PAGE *n_pagep, *p_pagep;		if ((ret =		    __ham_get_page(hashp->dbp, PREV_PGNO(p), &p_pagep)) != 0)			return (ret);		if (NEXT_PGNO(p) != PGNO_INVALID) {			if ((ret = __ham_get_page(hashp->dbp,			    NEXT_PGNO(p), &n_pagep)) != 0) {				(void)__ham_put_page(hashp->dbp, p_pagep, 0);				return (ret);			}			n_lsn = &LSN(n_pagep);		} else {			n_pagep = NULL;			n_lsn = NULL;		}		NEXT_PGNO(p_pagep) = NEXT_PGNO(p);		if (n_pagep != NULL)			PREV_PGNO(n_pagep) = PGNO(p_pagep);		if (DB_LOGGING(hashp->dbp)) {			if ((ret = __ham_newpage_log(dbenv->lg_info,			    (DB_TXN *)hashp->dbp->txn, &new_lsn, 0, DELOVFL,			    hashp->dbp->log_fileid, PREV_PGNO(p), &LSN(p_pagep),			    PGNO(p), &LSN(p), NEXT_PGNO(p), n_lsn)) != 0)				return (ret);			/* Move lsn onto page. */			LSN(p_pagep) = new_lsn;	/* Structure assignment. */			if (n_pagep)				LSN(n_pagep) = new_lsn;			LSN(p) = new_lsn;		}		cursorp->pgno = NEXT_PGNO(p);		cursorp->bndx = 0;		/*		 * Since we are about to delete the cursor page and we have		 * just moved the cursor, we need to make sure that the		 * old page pointer isn't left hanging around in the cursor.		 */		cursorp->pagep = NULL;		chg_pgno = PGNO(p);		ret = __ham_del_page(hashp->dbp, p);		if ((tret = __ham_put_page(hashp->dbp, p_pagep, 1)) != 0 &&		    ret == 0)			ret = tret;		if (n_pagep != NULL &&		    (tret = __ham_put_page(hashp->dbp, n_pagep, 1)) != 0 &&		    ret == 0)			ret = tret;		if (ret != 0)			return (ret);	} else {		/*		 * Mark item deleted so that we don't try to return it, and		 * so that we update the cursor correctly on the next call		 * to next.		 */		F_SET(cursorp, H_DELETED);		chg_pgno = cursorp->pgno;		ret = __ham_dirty_page(hashp, p);	}	__ham_c_update(cursorp, chg_pgno, 0, 0, 0);	/*	 * Since we just deleted a pair from the master page, anything	 * in cursorp->dpgno should be cleared.	 */	cursorp->dpgno = PGNO_INVALID;	F_CLR(cursorp, H_OK);	return (ret);}