示例#1
0
/*
 * __REC_GET -- Get a record from the btree.
 *
 * Parameters:
 *	dbp:	pointer to access method
 *	key:	key to find
 *	data:	data to return
 *	flag:	currently unused
 *
 * Returns:
 *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
 */
int
__rec_get(const DB *dbp, const DBT *key, DBT *data, unsigned int flags)
{
	BTREE *t;
	EPG *e;
	recno_t nrec;
	int status;

	t = dbp->internal;

	/* Toss any page pinned across calls. */
	if (t->bt_pinned != NULL) {
		mpool_put(t->bt_mp, t->bt_pinned, 0);
		t->bt_pinned = NULL;
	}

	/* Get currently doesn't take any flags, and keys of 0 are illegal. */
	if (flags || (nrec = *(recno_t *)key->data) == 0) {
		errno = EINVAL;
		return (RET_ERROR);
	}

	/*
	 * If we haven't seen this record yet, try to find it in the
	 * original file.
	 */
	if (nrec > t->bt_nrecs) {
		if (F_ISSET(t, R_EOF | R_INMEM))
			return (RET_SPECIAL);
		if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
			return (status);
	}

	--nrec;
	if ((e = __rec_search(t, nrec, SEARCH)) == NULL)
		return (RET_ERROR);

	status = __rec_ret(t, e, 0, NULL, data);
	if (F_ISSET(t, B_DB_LOCK))
		mpool_put(t->bt_mp, e->page, 0);
	else
		t->bt_pinned = e->page;
	return (status);
}
示例#2
0
/*
 * REC_RDELETE -- Delete the data matching the specified key.
 *
 * Parameters:
 *	tree:	tree
 *	nrec:	record to delete
 *
 * Returns:
 *	RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
 */
static int
rec_rdelete(BTREE *t, recno_t nrec)
{
	EPG *e;
	PAGE *h;
	int status;

	/* Find the record; __rec_search pins the page. */
	if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
		return (RET_ERROR);

	/* Delete the record. */
	h = e->page;
	status = __rec_dleaf(t, h, e->index);
	if (status != RET_SUCCESS) {
		mpool_put(t->bt_mp, h, 0);
		return (status);
	}
	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
	return (RET_SUCCESS);
}
示例#3
0
文件: rec_seq.c 项目: aharri/obase
/*
 * __REC_SEQ -- Recno sequential scan interface.
 *
 * Parameters:
 *	dbp:	pointer to access method
 *	key:	key for positioning and return value
 *	data:	data return value
 *	flags:	R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
 *
 * Returns:
 *	RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
 */
int
__rec_seq(const DB *dbp, DBT *key, DBT *data, u_int flags)
{
	BTREE *t;
	EPG *e;
	recno_t nrec;
	int status;

	t = dbp->internal;

	/* Toss any page pinned across calls. */
	if (t->bt_pinned != NULL) {
		mpool_put(t->bt_mp, t->bt_pinned, 0);
		t->bt_pinned = NULL;
	}

	switch(flags) {
	case R_CURSOR:
		if ((nrec = *(recno_t *)key->data) == 0)
			goto einval;
		break;
	case R_NEXT:
		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
			nrec = t->bt_cursor.rcursor + 1;
			break;
		}
		/* FALLTHROUGH */
	case R_FIRST:
		nrec = 1;
		break;
	case R_PREV:
		if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
			if ((nrec = t->bt_cursor.rcursor - 1) == 0)
				return (RET_SPECIAL);
			break;
		}
		/* FALLTHROUGH */
	case R_LAST:
		if (!F_ISSET(t, R_EOF | R_INMEM) &&
		    t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
			return (RET_ERROR);
		nrec = t->bt_nrecs;
		break;
	default:
einval:		errno = EINVAL;
		return (RET_ERROR);
	}
	
	if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
		if (!F_ISSET(t, R_EOF | R_INMEM) &&
		    (status = t->bt_irec(t, nrec)) != RET_SUCCESS)
			return (status);
		if (t->bt_nrecs == 0 || nrec > t->bt_nrecs)
			return (RET_SPECIAL);
	}

	if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL)
		return (RET_ERROR);

	F_SET(&t->bt_cursor, CURS_INIT);
	t->bt_cursor.rcursor = nrec;

	status = __rec_ret(t, e, nrec, key, data);
	if (F_ISSET(t, B_DB_LOCK))
		mpool_put(t->bt_mp, e->page, 0);
	else
		t->bt_pinned = e->page;
	return (status);
}
示例#4
0
/*
 * __REC_IPUT -- Add a recno item to the tree.
 *
 * Parameters:
 *	t:	tree
 *	nrec:	record number
 *	data:	data
 *
 * Returns:
 *	RET_ERROR, RET_SUCCESS
 */
int
__rec_iput(BTREE *t, recno_t nrec, const DBT *data, u_int flags)
{
    DBT tdata;
    EPG *e;
    PAGE *h;
    indx_t idx, nxtindex;
    pgno_t pg;
    uint32_t nbytes;
    int dflags, status;
    char *dest, db[NOVFLSIZE];

    /*
     * If the data won't fit on a page, store it on indirect pages.
     *
     * XXX
     * If the insert fails later on, these pages aren't recovered.
     */
    if (data->size > t->bt_ovflsize) {
        if (__ovfl_put(t, data, &pg) == RET_ERROR)
            return (RET_ERROR);
        tdata.data = db;
        tdata.size = NOVFLSIZE;
        *(pgno_t *)(void *)db = pg;
        _DBFIT(data->size, uint32_t);
        *(uint32_t *)(void *)(db + sizeof(pgno_t)) =
            (uint32_t)data->size;
        dflags = P_BIGDATA;
        data = &tdata;
    } else
        dflags = 0;

    /* __rec_search pins the returned page. */
    if ((e = __rec_search(t, nrec,
                          nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ?
                          SINSERT : SEARCH)) == NULL)
        return (RET_ERROR);

    h = e->page;
    idx = e->index;

    /*
     * Add the specified key/data pair to the tree.  The R_IAFTER and
     * R_IBEFORE flags insert the key after/before the specified key.
     *
     * Pages are split as required.
     */
    switch (flags) {
    case R_IAFTER:
        ++idx;
        break;
    case R_IBEFORE:
        break;
    default:
        if (nrec < t->bt_nrecs &&
                __rec_dleaf(t, h, (uint32_t)idx) == RET_ERROR) {
            mpool_put(t->bt_mp, h, 0);
            return (RET_ERROR);
        }
        break;
    }

    /*
     * If not enough room, split the page.  The split code will insert
     * the key and data and unpin the current page.  If inserting into
     * the offset array, shift the pointers up.
     */
    nbytes = NRLEAFDBT(data->size);
    if ((uint32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) {
        status = __bt_split(t, h, NULL, data, dflags, nbytes,
                            (uint32_t)idx);
        if (status == RET_SUCCESS)
            ++t->bt_nrecs;
        return (status);
    }

    if (idx < (nxtindex = NEXTINDEX(h)))
        memmove(h->linp + idx + 1, h->linp + idx,
                (nxtindex - idx) * sizeof(indx_t));
    h->lower += sizeof(indx_t);

    h->linp[idx] = h->upper -= nbytes;
    dest = (char *)(void *)h + h->upper;
    WR_RLEAF(dest, data, dflags);

    ++t->bt_nrecs;
    F_SET(t, B_MODIFIED);
    mpool_put(t->bt_mp, h, MPOOL_DIRTY);

    return (RET_SUCCESS);
}