mdb_cursor_put(): Factor out code. Kill a label.

vmware
Hallvard Furuseth 11 years ago
parent 550bbe3788
commit 25d370cb2e
  1. 110
      libraries/liblmdb/mdb.c

@ -5603,9 +5603,9 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
unsigned int flags) unsigned int flags)
{ {
enum { MDB_NO_ROOT = MDB_LAST_ERRCODE+10 }; /* internal code */ enum { MDB_NO_ROOT = MDB_LAST_ERRCODE+10 }; /* internal code */
MDB_env *env = mc->mc_txn->mt_env;
MDB_node *leaf = NULL; MDB_node *leaf = NULL;
MDB_val xdata, *rdata, dkey; MDB_val xdata, *rdata, dkey;
MDB_page *fp;
MDB_db dummy; MDB_db dummy;
int do_sub = 0, insert = 0; int do_sub = 0, insert = 0;
unsigned int mcount = 0, dcount = 0, nospill; unsigned int mcount = 0, dcount = 0, nospill;
@ -5725,6 +5725,9 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
/* The key already exists */ /* The key already exists */
if (rc == MDB_SUCCESS) { if (rc == MDB_SUCCESS) {
MDB_page *fp, *mp;
MDB_val olddata;
/* there's only a key anyway, so this is a no-op */ /* there's only a key anyway, so this is a no-op */
if (IS_LEAF2(mc->mc_pg[mc->mc_top])) { if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
unsigned int ksize = mc->mc_db->md_pad; unsigned int ksize = mc->mc_db->md_pad;
@ -5737,19 +5740,23 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
return MDB_SUCCESS; return MDB_SUCCESS;
} }
more:
leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]); leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
olddata.mv_size = NODEDSZ(leaf);
olddata.mv_data = NODEDATA(leaf);
/* DB has dups? */ /* DB has dups? */
if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSORT)) { if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSORT)) {
mp = fp = xdata.mv_data = &pbuf;
mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno;
/* Was a single item before, must convert now */ /* Was a single item before, must convert now */
more:
if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) { if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
/* Just overwrite the current item */ /* Just overwrite the current item */
if (flags == MDB_CURRENT) if (flags == MDB_CURRENT)
goto current; goto current;
dkey.mv_size = NODEDSZ(leaf); dkey = olddata;
dkey.mv_data = NODEDATA(leaf);
#if UINT_MAX < SIZE_MAX #if UINT_MAX < SIZE_MAX
if (mc->mc_dbx->md_dcmp == mdb_cmp_int && dkey.mv_size == sizeof(size_t)) if (mc->mc_dbx->md_dcmp == mdb_cmp_int && dkey.mv_size == sizeof(size_t))
#ifdef MISALIGNED_OK #ifdef MISALIGNED_OK
@ -5772,8 +5779,6 @@ more:
/* create a fake page for the dup items */ /* create a fake page for the dup items */
memcpy(dbuf, dkey.mv_data, dkey.mv_size); memcpy(dbuf, dkey.mv_data, dkey.mv_size);
dkey.mv_data = dbuf; dkey.mv_data = dbuf;
fp = (MDB_page *)&pbuf;
fp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno;
fp->mp_flags = P_LEAF|P_DIRTY|P_SUBP; fp->mp_flags = P_LEAF|P_DIRTY|P_SUBP;
fp->mp_lower = PAGEHDRSZ; fp->mp_lower = PAGEHDRSZ;
fp->mp_upper = PAGEHDRSZ + dkey.mv_size + data->mv_size; fp->mp_upper = PAGEHDRSZ + dkey.mv_size + data->mv_size;
@ -5785,42 +5790,42 @@ more:
fp->mp_upper += 2 * sizeof(indx_t) + 2 * NODESIZE + fp->mp_upper += 2 * sizeof(indx_t) + 2 * NODESIZE +
(dkey.mv_size & 1) + (data->mv_size & 1); (dkey.mv_size & 1) + (data->mv_size & 1);
} }
mdb_node_del(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], 0);
do_sub = 1;
rdata = &xdata;
xdata.mv_size = fp->mp_upper; xdata.mv_size = fp->mp_upper;
xdata.mv_data = fp; } else if (leaf->mn_flags & F_SUBDATA) {
flags |= F_DUPDATA; /* Data is on sub-DB, just store it */
goto new_sub; flags |= F_DUPDATA|F_SUBDATA;
} goto put_sub;
if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) { } else {
/* See if we need to convert from fake page to subDB */ /* See if we need to convert from fake page to subDB */
MDB_page *mp;
unsigned int offset; unsigned int offset;
unsigned int i; unsigned int i;
uint16_t fp_flags; uint16_t fp_flags;
fp = NODEDATA(leaf); fp = olddata.mv_data;
if (flags == MDB_CURRENT) { switch (flags) {
reuse: default:
if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
offset = NODESIZE + sizeof(indx_t) + data->mv_size;
offset += offset & 1;
break;
}
offset = fp->mp_pad;
if (SIZELEFT(fp) < offset) {
offset *= 4; /* space for 4 more */
break;
}
/* FALLTHRU: Big enough MDB_DUPFIXED sub-page */
case MDB_CURRENT:
fp->mp_flags |= P_DIRTY; fp->mp_flags |= P_DIRTY;
COPY_PGNO(fp->mp_pgno, mc->mc_pg[mc->mc_top]->mp_pgno); COPY_PGNO(fp->mp_pgno, mp->mp_pgno);
mc->mc_xcursor->mx_cursor.mc_pg[0] = fp; mc->mc_xcursor->mx_cursor.mc_pg[0] = fp;
flags |= F_DUPDATA; flags |= F_DUPDATA;
goto put_sub; goto put_sub;
} }
if (mc->mc_db->md_flags & MDB_DUPFIXED) {
offset = fp->mp_pad;
if (SIZELEFT(fp) >= offset)
goto reuse;
offset *= 4; /* space for 4 more */
} else {
offset = NODESIZE + sizeof(indx_t) + data->mv_size;
}
offset += offset & 1;
fp_flags = fp->mp_flags; fp_flags = fp->mp_flags;
if (NODESIZE + sizeof(indx_t) + NODEKSZ(leaf) + NODEDSZ(leaf) + xdata.mv_size = olddata.mv_size + offset;
offset >= mc->mc_txn->mt_env->me_nodemax) { if (NODESIZE + sizeof(indx_t) + NODEKSZ(leaf) + xdata.mv_size
>= env->me_nodemax) {
/* yes, convert it */ /* yes, convert it */
dummy.md_flags = 0; dummy.md_flags = 0;
if (mc->mc_db->md_flags & MDB_DUPFIXED) { if (mc->mc_db->md_flags & MDB_DUPFIXED) {
@ -5834,23 +5839,14 @@ reuse:
dummy.md_leaf_pages = 1; dummy.md_leaf_pages = 1;
dummy.md_overflow_pages = 0; dummy.md_overflow_pages = 0;
dummy.md_entries = NUMKEYS(fp); dummy.md_entries = NUMKEYS(fp);
rdata = &xdata;
xdata.mv_size = sizeof(MDB_db); xdata.mv_size = sizeof(MDB_db);
xdata.mv_data = &dummy; xdata.mv_data = &dummy;
if ((rc = mdb_page_alloc(mc, 1, &mp))) if ((rc = mdb_page_alloc(mc, 1, &mp)))
return rc; return rc;
offset = mc->mc_txn->mt_env->me_psize - NODEDSZ(leaf); offset = env->me_psize - olddata.mv_size;
flags |= F_DUPDATA|F_SUBDATA; flags |= F_DUPDATA|F_SUBDATA;
dummy.md_root = mp->mp_pgno; dummy.md_root = mp->mp_pgno;
fp_flags &= ~P_SUBP; fp_flags &= ~P_SUBP;
} else {
/* no, just grow it */
rdata = &xdata;
xdata.mv_size = NODEDSZ(leaf) + offset;
xdata.mv_data = &pbuf;
mp = (MDB_page *)&pbuf;
mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno;
flags |= F_DUPDATA;
} }
mp->mp_flags = fp_flags | P_DIRTY; mp->mp_flags = fp_flags | P_DIRTY;
mp->mp_pad = fp->mp_pad; mp->mp_pad = fp->mp_pad;
@ -5859,28 +5855,27 @@ reuse:
if (IS_LEAF2(fp)) { if (IS_LEAF2(fp)) {
memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad); memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad);
} else { } else {
nsize = NODEDSZ(leaf) - fp->mp_upper; memcpy((char *)mp + mp->mp_upper, (char *)fp + fp->mp_upper,
memcpy((char *)mp + mp->mp_upper, (char *)fp + fp->mp_upper, nsize); olddata.mv_size - fp->mp_upper);
for (i=0; i<NUMKEYS(fp); i++) for (i=0; i<NUMKEYS(fp); i++)
mp->mp_ptrs[i] = fp->mp_ptrs[i] + offset; mp->mp_ptrs[i] = fp->mp_ptrs[i] + offset;
} }
mdb_node_del(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], 0);
do_sub = 1;
goto new_sub;
} }
/* data is on sub-DB, just store it */
flags |= F_DUPDATA|F_SUBDATA; rdata = &xdata;
goto put_sub; flags |= F_DUPDATA;
do_sub = 1;
mdb_node_del(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top], 0);
goto new_sub;
} }
current: current:
/* overflow page overwrites need special handling */ /* overflow page overwrites need special handling */
if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { if (F_ISSET(leaf->mn_flags, F_BIGDATA)) {
MDB_page *omp; MDB_page *omp;
pgno_t pg; pgno_t pg;
unsigned psize = mc->mc_txn->mt_env->me_psize; int level, ovpages, dpages = OVPAGES(data->mv_size, env->me_psize);
int level, ovpages, dpages = OVPAGES(data->mv_size, psize);
memcpy(&pg, NODEDATA(leaf), sizeof(pg)); memcpy(&pg, olddata.mv_data, sizeof(pg));
if ((rc2 = mdb_page_get(mc->mc_txn, pg, &omp, &level)) != 0) if ((rc2 = mdb_page_get(mc->mc_txn, pg, &omp, &level)) != 0)
return rc2; return rc2;
ovpages = omp->mp_pages; ovpages = omp->mp_pages;
@ -5888,7 +5883,7 @@ current:
/* Is the ov page large enough? */ /* Is the ov page large enough? */
if (ovpages >= dpages) { if (ovpages >= dpages) {
if (!(omp->mp_flags & P_DIRTY) && if (!(omp->mp_flags & P_DIRTY) &&
(level || (mc->mc_txn->mt_env->me_flags & MDB_WRITEMAP))) (level || (env->me_flags & MDB_WRITEMAP)))
{ {
rc = mdb_page_unspill(mc->mc_txn, omp, &omp); rc = mdb_page_unspill(mc->mc_txn, omp, &omp);
if (rc) if (rc)
@ -5903,7 +5898,7 @@ current:
*/ */
if (level > 1) { if (level > 1) {
/* It is writable only in a parent txn */ /* It is writable only in a parent txn */
size_t sz = (size_t) psize * ovpages, off; size_t sz = (size_t) env->me_psize * ovpages, off;
MDB_page *np = mdb_page_malloc(mc->mc_txn, ovpages); MDB_page *np = mdb_page_malloc(mc->mc_txn, ovpages);
MDB_ID2 id2; MDB_ID2 id2;
if (!np) if (!np)
@ -5933,15 +5928,15 @@ current:
} }
if ((rc2 = mdb_ovpage_free(mc, omp)) != MDB_SUCCESS) if ((rc2 = mdb_ovpage_free(mc, omp)) != MDB_SUCCESS)
return rc2; return rc2;
} else if (NODEDSZ(leaf) == data->mv_size) { } else if (data->mv_size == olddata.mv_size) {
/* same size, just replace it. Note that we could /* same size, just replace it. Note that we could
* also reuse this node if the new data is smaller, * also reuse this node if the new data is smaller,
* but instead we opt to shrink the node in that case. * but instead we opt to shrink the node in that case.
*/ */
if (F_ISSET(flags, MDB_RESERVE)) if (F_ISSET(flags, MDB_RESERVE))
data->mv_data = NODEDATA(leaf); data->mv_data = olddata.mv_data;
else if (data->mv_size) else if (data->mv_size)
memcpy(NODEDATA(leaf), data->mv_data, data->mv_size); memcpy(olddata.mv_data, data->mv_data, data->mv_size);
else else
memcpy(NODEKEY(leaf), key->mv_data, key->mv_size); memcpy(NODEKEY(leaf), key->mv_data, key->mv_size);
goto done; goto done;
@ -5957,7 +5952,7 @@ current:
new_sub: new_sub:
nflags = flags & NODE_ADD_FLAGS; nflags = flags & NODE_ADD_FLAGS;
nsize = IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : mdb_leaf_size(mc->mc_txn->mt_env, key, rdata); nsize = IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : mdb_leaf_size(env, key, rdata);
if (SIZELEFT(mc->mc_pg[mc->mc_top]) < nsize) { if (SIZELEFT(mc->mc_pg[mc->mc_top]) < nsize) {
if (( flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA ) if (( flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA )
nflags &= ~MDB_APPEND; nflags &= ~MDB_APPEND;
@ -6051,7 +6046,6 @@ next_mult:
data[1].mv_size = mcount; data[1].mv_size = mcount;
if (mcount < dcount) { if (mcount < dcount) {
data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size; data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size;
leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
goto more; goto more;
} }
} }

Loading…
Cancel
Save