mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-18 11:05:48 +08:00
Merge remote-tracking branch 'origin/mdb.RE/0.9'
This commit is contained in:
commit
1ebc6faf87
@ -17,6 +17,11 @@ LMDB 0.9.17 Release Engineering
|
||||
Fix ITS#7971 mdb_txn_renew0() new reader slots
|
||||
Fix ITS#7969 use __sync_synchronize on non-x86
|
||||
Fix ITS#8311 page_split from update_key
|
||||
Fix ITS#8312 loose pages in nested txn
|
||||
Fix ITS#8313 mdb_rebalance dummy cursor
|
||||
Fix ITS#8315 dirty_room in nested txn
|
||||
Fix ITS#8316 page_merge cursor tracking
|
||||
Fix ITS#8321 cursor tracking
|
||||
Added mdb_txn_id() (ITS#7994)
|
||||
Added robust mutex support
|
||||
Miscellaneous cleanup/simplification
|
||||
|
@ -1161,7 +1161,6 @@ struct MDB_cursor {
|
||||
#define C_EOF 0x02 /**< No more data */
|
||||
#define C_SUB 0x04 /**< Cursor is a sub-cursor */
|
||||
#define C_DEL 0x08 /**< last op was a cursor_del */
|
||||
#define C_SPLITTING 0x20 /**< Cursor is in page_split */
|
||||
#define C_UNTRACK 0x40 /**< Un-track cursor when closing */
|
||||
/** @} */
|
||||
unsigned int mc_flags; /**< @ref mdb_cursor */
|
||||
@ -1327,7 +1326,7 @@ static int mdb_node_add(MDB_cursor *mc, indx_t indx,
|
||||
MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags);
|
||||
static void mdb_node_del(MDB_cursor *mc, int ksize);
|
||||
static void mdb_node_shrink(MDB_page *mp, indx_t indx);
|
||||
static int mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst);
|
||||
static int mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft);
|
||||
static int mdb_node_read(MDB_txn *txn, MDB_node *leaf, MDB_val *data);
|
||||
static size_t mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data);
|
||||
static size_t mdb_branch_size(MDB_env *env, MDB_val *key);
|
||||
@ -1372,6 +1371,8 @@ static MDB_cmp_func mdb_cmp_memn, mdb_cmp_memnr, mdb_cmp_int, mdb_cmp_cint, mdb_
|
||||
static SECURITY_DESCRIPTOR mdb_null_sd;
|
||||
static SECURITY_ATTRIBUTES mdb_all_sa;
|
||||
static int mdb_sec_inited;
|
||||
|
||||
static int utf8_to_utf16(const char *src, int srcsize, wchar_t **dst, int *dstsize);
|
||||
#endif
|
||||
|
||||
/** Return the library version info. */
|
||||
@ -1603,7 +1604,7 @@ mdb_cursor_chk(MDB_cursor *mc)
|
||||
MDB_node *node;
|
||||
MDB_page *mp;
|
||||
|
||||
if (!mc->mc_snum && !(mc->mc_flags & C_INITIALIZED)) return;
|
||||
if (!mc->mc_snum || !(mc->mc_flags & C_INITIALIZED)) return;
|
||||
for (i=0; i<mc->mc_top; i++) {
|
||||
mp = mc->mc_pg[i];
|
||||
node = NODEPTR(mp, mc->mc_ki[i]);
|
||||
@ -2488,14 +2489,15 @@ mdb_cursor_shadow(MDB_txn *src, MDB_txn *dst)
|
||||
*bk = *mc;
|
||||
mc->mc_backup = bk;
|
||||
mc->mc_db = &dst->mt_dbs[i];
|
||||
/* Kill pointers into src - and dst to reduce abuse: The
|
||||
* user may not use mc until dst ends. Otherwise we'd...
|
||||
/* Kill pointers into src to reduce abuse: The
|
||||
* user may not use mc until dst ends. But we need a valid
|
||||
* txn pointer here for cursor fixups to keep working.
|
||||
*/
|
||||
mc->mc_txn = NULL; /* ...set this to dst */
|
||||
mc->mc_dbflag = NULL; /* ...and &dst->mt_dbflags[i] */
|
||||
mc->mc_txn = dst;
|
||||
mc->mc_dbflag = &dst->mt_dbflags[i];
|
||||
if ((mx = mc->mc_xcursor) != NULL) {
|
||||
*(MDB_xcursor *)(bk+1) = *mx;
|
||||
mx->mx_cursor.mc_txn = NULL; /* ...and dst. */
|
||||
mx->mx_cursor.mc_txn = dst;
|
||||
}
|
||||
mc->mc_next = dst->mt_cursors[i];
|
||||
dst->mt_cursors[i] = mc;
|
||||
@ -3474,7 +3476,7 @@ mdb_txn_commit(MDB_txn *txn)
|
||||
}
|
||||
|
||||
/* Append our loose page list to parent's */
|
||||
for (lp = &parent->mt_loose_pgs; *lp; lp = &NEXT_LOOSE_PAGE(lp))
|
||||
for (lp = &parent->mt_loose_pgs; *lp; lp = &NEXT_LOOSE_PAGE(*lp))
|
||||
;
|
||||
*lp = txn->mt_loose_pgs;
|
||||
parent->mt_loose_count += txn->mt_loose_count;
|
||||
@ -4440,9 +4442,12 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl)
|
||||
off_t size, rsize;
|
||||
|
||||
#ifdef _WIN32
|
||||
env->me_lfd = CreateFileA(lpath, GENERIC_READ|GENERIC_WRITE,
|
||||
wchar_t *wlpath;
|
||||
utf8_to_utf16(lpath, -1, &wlpath, NULL);
|
||||
env->me_lfd = CreateFileW(wlpath, GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
free(wlpath);
|
||||
#else
|
||||
env->me_lfd = open(lpath, O_RDWR|O_CREAT|MDB_CLOEXEC, mode);
|
||||
#endif
|
||||
@ -4660,6 +4665,9 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
|
||||
{
|
||||
int oflags, rc, len, excl = -1;
|
||||
char *lpath, *dpath;
|
||||
#ifdef _WIN32
|
||||
wchar_t *wpath;
|
||||
#endif
|
||||
|
||||
if (env->me_fd!=INVALID_HANDLE_VALUE || (flags & ~(CHANGEABLE|CHANGELESS)))
|
||||
return EINVAL;
|
||||
@ -4723,8 +4731,10 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
|
||||
len = OPEN_ALWAYS;
|
||||
}
|
||||
mode = FILE_ATTRIBUTE_NORMAL;
|
||||
env->me_fd = CreateFileA(dpath, oflags, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
utf8_to_utf16(dpath, -1, &wpath, NULL);
|
||||
env->me_fd = CreateFileW(wpath, oflags, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
NULL, len, mode, NULL);
|
||||
free(wpath);
|
||||
#else
|
||||
if (F_ISSET(flags, MDB_RDONLY))
|
||||
oflags = O_RDONLY;
|
||||
@ -4753,9 +4763,11 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
len = OPEN_EXISTING;
|
||||
env->me_mfd = CreateFileA(dpath, oflags,
|
||||
utf8_to_utf16(dpath, -1, &wpath, NULL);
|
||||
env->me_mfd = CreateFileW(wpath, oflags,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, len,
|
||||
mode | FILE_FLAG_WRITE_THROUGH, NULL);
|
||||
free(wpath);
|
||||
#else
|
||||
oflags &= ~O_CREAT;
|
||||
env->me_mfd = open(dpath, oflags | MDB_DSYNC, mode);
|
||||
@ -5449,6 +5461,7 @@ mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
|
||||
return MDB_CORRUPTED;
|
||||
}
|
||||
}
|
||||
txn->mt_dirty_room++;
|
||||
if (!(env->me_flags & MDB_WRITEMAP))
|
||||
mdb_dpage_free(env, mp);
|
||||
release:
|
||||
@ -6583,6 +6596,7 @@ current:
|
||||
return ENOMEM;
|
||||
id2.mid = pg;
|
||||
id2.mptr = np;
|
||||
/* Note - this page is already counted in parent's dirty_room */
|
||||
rc2 = mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2);
|
||||
mdb_cassert(mc, rc2 == 0);
|
||||
if (!(flags & MDB_RESERVE)) {
|
||||
@ -6696,6 +6710,7 @@ put_sub:
|
||||
MDB_xcursor *mx = mc->mc_xcursor;
|
||||
unsigned i = mc->mc_top;
|
||||
MDB_page *mp = mc->mc_pg[i];
|
||||
int nkeys = NUMKEYS(mp);
|
||||
|
||||
for (m2 = mc->mc_txn->mt_cursors[mc->mc_dbi]; m2; m2=m2->mc_next) {
|
||||
if (m2 == mc || m2->mc_snum < mc->mc_snum) continue;
|
||||
@ -6703,9 +6718,9 @@ put_sub:
|
||||
if (m2->mc_pg[i] == mp) {
|
||||
if (m2->mc_ki[i] == mc->mc_ki[i]) {
|
||||
mdb_xcursor_init2(m2, mx, new_dupdata);
|
||||
} else if (!insert_key) {
|
||||
} else if (!insert_key && m2->mc_ki[i] < nkeys) {
|
||||
MDB_node *n2 = NODEPTR(mp, m2->mc_ki[i]);
|
||||
if (!(n2->mn_flags & F_SUBDATA))
|
||||
if ((n2->mn_flags & (F_SUBDATA|F_DUPDATA)) == F_DUPDATA)
|
||||
m2->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(n2);
|
||||
}
|
||||
}
|
||||
@ -7509,10 +7524,26 @@ mdb_update_key(MDB_cursor *mc, MDB_val *key)
|
||||
static void
|
||||
mdb_cursor_copy(const MDB_cursor *csrc, MDB_cursor *cdst);
|
||||
|
||||
/** Track a temporary cursor */
|
||||
#define CURSOR_TMP_TRACK(mc, mn, dummy, tracked) \
|
||||
if (mc->mc_flags & C_SUB) { \
|
||||
dummy.mc_flags = C_INITIALIZED; \
|
||||
dummy.mc_xcursor = (MDB_xcursor *)&mn; \
|
||||
tracked = &dummy; \
|
||||
} else { \
|
||||
tracked = &mn; \
|
||||
} \
|
||||
tracked->mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi]; \
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = tracked
|
||||
|
||||
/** Stop tracking a temporary cursor */
|
||||
#define CURSOR_TMP_UNTRACK(mc, tracked) \
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = tracked->mc_next
|
||||
|
||||
/** Move a node from csrc to cdst.
|
||||
*/
|
||||
static int
|
||||
mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst, int fromleft)
|
||||
{
|
||||
MDB_node *srcnode;
|
||||
MDB_val key, data;
|
||||
@ -7614,13 +7645,15 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
|
||||
mps = csrc->mc_pg[csrc->mc_top];
|
||||
/* If we're adding on the left, bump others up */
|
||||
if (!cdst->mc_ki[csrc->mc_top]) {
|
||||
if (fromleft) {
|
||||
mpd = cdst->mc_pg[csrc->mc_top];
|
||||
for (m2 = csrc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
|
||||
if (csrc->mc_flags & C_SUB)
|
||||
m3 = &m2->mc_xcursor->mx_cursor;
|
||||
else
|
||||
m3 = m2;
|
||||
if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top)
|
||||
continue;
|
||||
if (m3 != cdst &&
|
||||
m3->mc_pg[csrc->mc_top] == mpd &&
|
||||
m3->mc_ki[csrc->mc_top] >= cdst->mc_ki[csrc->mc_top]) {
|
||||
@ -7643,6 +7676,8 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
else
|
||||
m3 = m2;
|
||||
if (m3 == csrc) continue;
|
||||
if (!(m3->mc_flags & C_INITIALIZED) || m3->mc_top < csrc->mc_top)
|
||||
continue;
|
||||
if (m3->mc_pg[csrc->mc_top] == mps) {
|
||||
if (!m3->mc_ki[csrc->mc_top]) {
|
||||
m3->mc_pg[csrc->mc_top] = cdst->mc_pg[cdst->mc_top];
|
||||
@ -7660,6 +7695,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
*/
|
||||
if (csrc->mc_ki[csrc->mc_top] == 0) {
|
||||
if (csrc->mc_ki[csrc->mc_top-1] != 0) {
|
||||
MDB_cursor dummy, *tracked;
|
||||
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
|
||||
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
|
||||
} else {
|
||||
@ -7672,7 +7708,11 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
mdb_cursor_copy(csrc, &mn);
|
||||
mn.mc_snum--;
|
||||
mn.mc_top--;
|
||||
if ((rc = mdb_update_key(&mn, &key)) != MDB_SUCCESS)
|
||||
/* We want mdb_rebalance to find mn when doing fixups */
|
||||
CURSOR_TMP_TRACK(csrc, mn, dummy, tracked);
|
||||
rc = mdb_update_key(&mn, &key);
|
||||
CURSOR_TMP_UNTRACK(csrc, tracked);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
if (IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
|
||||
@ -7688,6 +7728,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
|
||||
if (cdst->mc_ki[cdst->mc_top] == 0) {
|
||||
if (cdst->mc_ki[cdst->mc_top-1] != 0) {
|
||||
MDB_cursor dummy, *tracked;
|
||||
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
|
||||
key.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, key.mv_size);
|
||||
} else {
|
||||
@ -7700,7 +7741,11 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
mdb_cursor_copy(cdst, &mn);
|
||||
mn.mc_snum--;
|
||||
mn.mc_top--;
|
||||
if ((rc = mdb_update_key(&mn, &key)) != MDB_SUCCESS)
|
||||
/* We want mdb_rebalance to find mn when doing fixups */
|
||||
CURSOR_TMP_TRACK(cdst, mn, dummy, tracked);
|
||||
rc = mdb_update_key(&mn, &key);
|
||||
CURSOR_TMP_UNTRACK(cdst, tracked);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
if (IS_BRANCH(cdst->mc_pg[cdst->mc_top])) {
|
||||
@ -7840,6 +7885,9 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
||||
m3->mc_pg[top] = pdst;
|
||||
m3->mc_ki[top] += nkeys;
|
||||
m3->mc_ki[top-1] = cdst->mc_ki[top-1];
|
||||
} else if (m3->mc_pg[top-1] == csrc->mc_pg[top-1] &&
|
||||
m3->mc_ki[top-1] > csrc->mc_ki[top-1]) {
|
||||
m3->mc_ki[top-1]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7889,7 +7937,7 @@ static int
|
||||
mdb_rebalance(MDB_cursor *mc)
|
||||
{
|
||||
MDB_node *node;
|
||||
int rc;
|
||||
int rc, fromleft;
|
||||
unsigned int ptop, minkeys, thresh;
|
||||
MDB_cursor mn;
|
||||
indx_t oldki;
|
||||
@ -7940,7 +7988,8 @@ mdb_rebalance(MDB_cursor *mc)
|
||||
m3 = &m2->mc_xcursor->mx_cursor;
|
||||
else
|
||||
m3 = m2;
|
||||
if (m3->mc_snum < mc->mc_snum) continue;
|
||||
if (!(m3->mc_flags & C_INITIALIZED) || (m3->mc_snum < mc->mc_snum))
|
||||
continue;
|
||||
if (m3->mc_pg[0] == mp) {
|
||||
m3->mc_snum = 0;
|
||||
m3->mc_top = 0;
|
||||
@ -7976,6 +8025,8 @@ mdb_rebalance(MDB_cursor *mc)
|
||||
else
|
||||
m3 = m2;
|
||||
if (m3 == mc) continue;
|
||||
if (!(m3->mc_flags & C_INITIALIZED))
|
||||
continue;
|
||||
if (m3->mc_pg[0] == mp) {
|
||||
for (i=0; i<mc->mc_db->md_depth; i++) {
|
||||
m3->mc_pg[i] = m3->mc_pg[i+1];
|
||||
@ -8019,6 +8070,7 @@ mdb_rebalance(MDB_cursor *mc)
|
||||
return rc;
|
||||
mn.mc_ki[mn.mc_top] = 0;
|
||||
mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]);
|
||||
fromleft = 0;
|
||||
} else {
|
||||
/* There is at least one neighbor to the left.
|
||||
*/
|
||||
@ -8030,6 +8082,7 @@ mdb_rebalance(MDB_cursor *mc)
|
||||
return rc;
|
||||
mn.mc_ki[mn.mc_top] = NUMKEYS(mn.mc_pg[mn.mc_top]) - 1;
|
||||
mc->mc_ki[mc->mc_top] = 0;
|
||||
fromleft = 1;
|
||||
}
|
||||
|
||||
DPRINTF(("found neighbor page %"Z"u (%u keys, %.1f%% full)",
|
||||
@ -8041,32 +8094,22 @@ mdb_rebalance(MDB_cursor *mc)
|
||||
* (A branch page must never have less than 2 keys.)
|
||||
*/
|
||||
if (PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) >= thresh && NUMKEYS(mn.mc_pg[mn.mc_top]) > minkeys) {
|
||||
rc = mdb_node_move(&mn, mc);
|
||||
if (!mc->mc_ki[mc->mc_top]) {
|
||||
rc = mdb_node_move(&mn, mc, fromleft);
|
||||
if (fromleft) {
|
||||
/* if we inserted on left, bump position up */
|
||||
oldki++;
|
||||
}
|
||||
} else {
|
||||
if (mc->mc_ki[ptop] == 0) {
|
||||
if (!fromleft) {
|
||||
rc = mdb_page_merge(&mn, mc);
|
||||
} else {
|
||||
MDB_cursor dummy;
|
||||
MDB_cursor dummy, *tracked;
|
||||
oldki += NUMKEYS(mn.mc_pg[mn.mc_top]);
|
||||
mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1;
|
||||
/* We want mdb_rebalance to find mn when doing fixups */
|
||||
if (mc->mc_flags & C_SUB) {
|
||||
dummy.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi];
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = &dummy;
|
||||
dummy.mc_xcursor = (MDB_xcursor *)&mn;
|
||||
} else {
|
||||
mn.mc_next = mc->mc_txn->mt_cursors[mc->mc_dbi];
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = &mn;
|
||||
}
|
||||
CURSOR_TMP_TRACK(mc, mn, dummy, tracked);
|
||||
rc = mdb_page_merge(mc, &mn);
|
||||
if (mc->mc_flags & C_SUB)
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = dummy.mc_next;
|
||||
else
|
||||
mc->mc_txn->mt_cursors[mc->mc_dbi] = mn.mc_next;
|
||||
CURSOR_TMP_UNTRACK(mc, tracked);
|
||||
mdb_cursor_copy(&mn, mc);
|
||||
}
|
||||
mc->mc_flags &= ~C_EOF;
|
||||
@ -8104,7 +8147,7 @@ mdb_cursor_del0(MDB_cursor *mc)
|
||||
if (m3->mc_ki[mc->mc_top] > ki)
|
||||
m3->mc_ki[mc->mc_top]--;
|
||||
else if (mc->mc_db->md_flags & MDB_DUPSORT)
|
||||
m3->mc_xcursor->mx_cursor.mc_flags |= C_EOF;
|
||||
m3->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8287,7 +8330,6 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
||||
DPRINTF(("parent branch page is %"Z"u", mc->mc_pg[ptop]->mp_pgno));
|
||||
}
|
||||
|
||||
mc->mc_flags |= C_SPLITTING;
|
||||
mdb_cursor_copy(mc, &mn);
|
||||
mn.mc_pg[mn.mc_top] = rp;
|
||||
mn.mc_ki[ptop] = mc->mc_ki[ptop]+1;
|
||||
@ -8338,8 +8380,6 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
||||
rp->mp_lower += sizeof(indx_t);
|
||||
rp->mp_upper -= ksize - sizeof(indx_t);
|
||||
mc->mc_ki[mc->mc_top] = x;
|
||||
mc->mc_pg[mc->mc_top] = rp;
|
||||
mc->mc_ki[ptop]++;
|
||||
}
|
||||
} else {
|
||||
int psize, nsize, k;
|
||||
@ -8432,21 +8472,20 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
||||
/* Copy separator key to the parent.
|
||||
*/
|
||||
if (SIZELEFT(mn.mc_pg[ptop]) < mdb_branch_size(env, &sepkey)) {
|
||||
int snum = mc->mc_snum;
|
||||
MDB_cursor dummy, *tracked;
|
||||
mn.mc_snum--;
|
||||
mn.mc_top--;
|
||||
did_split = 1;
|
||||
/* We want other splits to find mn when doing fixups */
|
||||
CURSOR_TMP_TRACK(mc, mn, dummy, tracked);
|
||||
rc = mdb_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0);
|
||||
CURSOR_TMP_UNTRACK(mc, tracked);
|
||||
if (rc)
|
||||
goto done;
|
||||
|
||||
/* root split? */
|
||||
if (mn.mc_snum == mc->mc_snum) {
|
||||
mc->mc_pg[mc->mc_snum] = mc->mc_pg[mc->mc_top];
|
||||
mc->mc_ki[mc->mc_snum] = mc->mc_ki[mc->mc_top];
|
||||
mc->mc_pg[mc->mc_top] = mc->mc_pg[ptop];
|
||||
mc->mc_ki[mc->mc_top] = mc->mc_ki[ptop];
|
||||
mc->mc_snum++;
|
||||
mc->mc_top++;
|
||||
if (mc->mc_snum > snum) {
|
||||
ptop++;
|
||||
}
|
||||
/* Right page might now have changed parent.
|
||||
@ -8472,7 +8511,6 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
||||
rc = mdb_node_add(&mn, mn.mc_ki[ptop], &sepkey, NULL, rp->mp_pgno, 0);
|
||||
mn.mc_top++;
|
||||
}
|
||||
mc->mc_flags ^= C_SPLITTING;
|
||||
if (rc != MDB_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
@ -8542,11 +8580,6 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
||||
/* reset back to original page */
|
||||
if (newindx < split_indx) {
|
||||
mc->mc_pg[mc->mc_top] = mp;
|
||||
if (nflags & MDB_RESERVE) {
|
||||
node = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
|
||||
if (!(node->mn_flags & F_BIGDATA))
|
||||
newdata->mv_data = NODEDATA(node);
|
||||
}
|
||||
} else {
|
||||
mc->mc_pg[mc->mc_top] = rp;
|
||||
mc->mc_ki[ptop]++;
|
||||
@ -8560,13 +8593,32 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nflags & MDB_RESERVE) {
|
||||
node = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
|
||||
if (!(node->mn_flags & F_BIGDATA))
|
||||
newdata->mv_data = NODEDATA(node);
|
||||
}
|
||||
} else {
|
||||
if (newindx >= split_indx) {
|
||||
mc->mc_pg[mc->mc_top] = rp;
|
||||
mc->mc_ki[ptop]++;
|
||||
/* Make sure mc_ki is still valid.
|
||||
*/
|
||||
if (mn.mc_pg[ptop] != mc->mc_pg[ptop] &&
|
||||
mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) {
|
||||
for (i=0; i<=ptop; i++) {
|
||||
mc->mc_pg[i] = mn.mc_pg[i];
|
||||
mc->mc_ki[i] = mn.mc_ki[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* Adjust other cursors pointing to mp */
|
||||
MDB_cursor *m2, *m3;
|
||||
MDB_dbi dbi = mc->mc_dbi;
|
||||
int fixup = NUMKEYS(mp);
|
||||
nkeys = NUMKEYS(mp);
|
||||
|
||||
for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
|
||||
if (mc->mc_flags & C_SUB)
|
||||
@ -8577,16 +8629,17 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
||||
continue;
|
||||
if (!(m2->mc_flags & m3->mc_flags & C_INITIALIZED))
|
||||
continue;
|
||||
if (m3->mc_flags & C_SPLITTING)
|
||||
continue;
|
||||
if (new_root) {
|
||||
int k;
|
||||
/* sub cursors may be on different DB */
|
||||
if (m3->mc_pg[0] != mp)
|
||||
continue;
|
||||
/* root split */
|
||||
for (k=new_root; k>=0; k--) {
|
||||
m3->mc_ki[k+1] = m3->mc_ki[k];
|
||||
m3->mc_pg[k+1] = m3->mc_pg[k];
|
||||
}
|
||||
if (m3->mc_ki[0] >= split_indx) {
|
||||
if (m3->mc_ki[0] > nkeys) {
|
||||
m3->mc_ki[0] = 1;
|
||||
} else {
|
||||
m3->mc_ki[0] = 0;
|
||||
@ -8598,10 +8651,13 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
||||
if (m3->mc_top >= mc->mc_top && m3->mc_pg[mc->mc_top] == mp) {
|
||||
if (m3->mc_ki[mc->mc_top] >= newindx && !(nflags & MDB_SPLIT_REPLACE))
|
||||
m3->mc_ki[mc->mc_top]++;
|
||||
if (m3->mc_ki[mc->mc_top] >= fixup) {
|
||||
if (m3->mc_ki[mc->mc_top] >= nkeys) {
|
||||
m3->mc_pg[mc->mc_top] = rp;
|
||||
m3->mc_ki[mc->mc_top] -= fixup;
|
||||
m3->mc_ki[ptop] = mn.mc_ki[ptop];
|
||||
m3->mc_ki[mc->mc_top] -= nkeys;
|
||||
for (i=0; i<mc->mc_top; i++) {
|
||||
m3->mc_ki[i] = mn.mc_ki[i];
|
||||
m3->mc_pg[i] = mn.mc_pg[i];
|
||||
}
|
||||
}
|
||||
} else if (!did_split && m3->mc_top >= ptop && m3->mc_pg[ptop] == mc->mc_pg[ptop] &&
|
||||
m3->mc_ki[ptop] >= mc->mc_ki[ptop]) {
|
||||
@ -9139,6 +9195,9 @@ mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags)
|
||||
int rc, len;
|
||||
char *lpath;
|
||||
HANDLE newfd = INVALID_HANDLE_VALUE;
|
||||
#ifdef _WIN32
|
||||
wchar_t *wpath;
|
||||
#endif
|
||||
|
||||
if (env->me_flags & MDB_NOSUBDIR) {
|
||||
lpath = (char *)path;
|
||||
@ -9156,8 +9215,10 @@ mdb_env_copy2(MDB_env *env, const char *path, unsigned int flags)
|
||||
* already in the OS cache.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
newfd = CreateFileA(lpath, GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||
utf8_to_utf16(lpath, -1, &wpath, NULL);
|
||||
newfd = CreateFileW(wpath, GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||
FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, NULL);
|
||||
free(wpath);
|
||||
#else
|
||||
newfd = open(lpath, O_WRONLY|O_CREAT|O_EXCL, 0666);
|
||||
#endif
|
||||
@ -9862,3 +9923,22 @@ mdb_mutex_failed(MDB_env *env, mdb_mutexref_t mutex, int rc)
|
||||
}
|
||||
#endif /* MDB_ROBUST_SUPPORTED */
|
||||
/** @} */
|
||||
|
||||
#if defined(_WIN32)
|
||||
static int utf8_to_utf16(const char *src, int srcsize, wchar_t **dst, int *dstsize)
|
||||
{
|
||||
int need;
|
||||
wchar_t *result;
|
||||
need = MultiByteToWideChar(CP_UTF8, 0, src, srcsize, NULL, 0);
|
||||
if (need == 0xFFFD)
|
||||
return EILSEQ;
|
||||
if (need == 0)
|
||||
return EINVAL;
|
||||
result = malloc(sizeof(wchar_t) * need);
|
||||
MultiByteToWideChar(CP_UTF8, 0, src, srcsize, result, need);
|
||||
if (dstsize)
|
||||
*dstsize = need;
|
||||
*dst = result;
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(_WIN32) */
|
||||
|
Loading…
Reference in New Issue
Block a user