# else
# define MDB_USE_ROBUST 1
/* glibc < 2.12 only provided _np API */
-# if defined(__GLIBC__) && GLIBC_VER < 0x02000c
+# if (defined(__GLIBC__) && GLIBC_VER < 0x02000c) || \
+ (defined(PTHREAD_MUTEX_ROBUST_NP) && !defined(PTHREAD_MUTEX_ROBUST))
# define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP
# define pthread_mutexattr_setrobust(attr, flag) pthread_mutexattr_setrobust_np(attr, flag)
# define pthread_mutex_consistent(mutex) pthread_mutex_consistent_np(mutex)
#else /* MDB_USE_POSIX_MUTEX: */
pthread_mutexattr_t mattr;
- if ((rc = pthread_mutexattr_init(&mattr))
- || (rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED))
+ /* Solaris needs this before initing a robust mutex. Otherwise
+ * it may skip the init and return EBUSY "seems someone already
+ * inited" or EINVAL "it was inited differently".
+ */
+ memset(env->me_txns->mti_rmutex, 0, sizeof(*env->me_txns->mti_rmutex));
+ memset(env->me_txns->mti_wmutex, 0, sizeof(*env->me_txns->mti_wmutex));
+
+ if ((rc = pthread_mutexattr_init(&mattr)))
+ goto fail;
+
+ rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
#ifdef MDB_ROBUST_SUPPORTED
- || (rc = pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST))
+ if (!rc) rc = pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST);
#endif
- || (rc = pthread_mutex_init(env->me_txns->mti_rmutex, &mattr))
- || (rc = pthread_mutex_init(env->me_txns->mti_wmutex, &mattr)))
- goto fail;
+ if (!rc) rc = pthread_mutex_init(env->me_txns->mti_rmutex, &mattr);
+ if (!rc) rc = pthread_mutex_init(env->me_txns->mti_wmutex, &mattr);
pthread_mutexattr_destroy(&mattr);
+ if (rc)
+ goto fail;
#endif /* _WIN32 || MDB_USE_POSIX_SEM */
env->me_txns->mti_magic = MDB_MAGIC;
MDB_node *leaf;
int rc;
- if (mc->mc_flags & C_EOF) {
+ if ((mc->mc_flags & C_EOF) ||
+ ((mc->mc_flags & C_DEL) && op == MDB_NEXT_DUP)) {
return MDB_NOTFOUND;
}
-
- mdb_cassert(mc, mc->mc_flags & C_INITIALIZED);
+ if (!(mc->mc_flags & C_INITIALIZED))
+ return mdb_cursor_first(mc, key, data);
mp = mc->mc_pg[mc->mc_top];
MDB_node *leaf;
int rc;
- mdb_cassert(mc, mc->mc_flags & C_INITIALIZED);
+ if (!(mc->mc_flags & C_INITIALIZED)) {
+ rc = mdb_cursor_last(mc, key, data);
+ if (rc)
+ return rc;
+ mc->mc_ki[mc->mc_top]++;
+ }
mp = mc->mc_pg[mc->mc_top];
rc = MDB_INCOMPATIBLE;
break;
}
- if (!(mc->mc_flags & C_INITIALIZED))
- rc = mdb_cursor_first(mc, key, data);
- else
- rc = mdb_cursor_next(mc, key, data, MDB_NEXT_DUP);
+ rc = mdb_cursor_next(mc, key, data, MDB_NEXT_DUP);
if (rc == MDB_SUCCESS) {
if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) {
MDB_cursor *mx;
case MDB_NEXT:
case MDB_NEXT_DUP:
case MDB_NEXT_NODUP:
- if (!(mc->mc_flags & C_INITIALIZED))
- rc = mdb_cursor_first(mc, key, data);
- else
- rc = mdb_cursor_next(mc, key, data, op);
+ rc = mdb_cursor_next(mc, key, data, op);
break;
case MDB_PREV:
case MDB_PREV_DUP:
case MDB_PREV_NODUP:
- if (!(mc->mc_flags & C_INITIALIZED)) {
- rc = mdb_cursor_last(mc, key, data);
- if (rc)
- break;
- mc->mc_flags |= C_INITIALIZED;
- mc->mc_ki[mc->mc_top]++;
- }
rc = mdb_cursor_prev(mc, key, data, op);
break;
case MDB_FIRST:
/* 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);
+ /* Currently we make the page look as with put() in the
+ * parent txn, in case the user peeks at MDB_RESERVEd
+ * or unused parts. Some users treat ovpages specially.
+ */
if (!(flags & MDB_RESERVE)) {
- /* Copy end of page, adjusting alignment so
+ /* Skip the part where LMDB will put *data.
+ * Copy end of page, adjusting alignment so
* compiler may copy words instead of bytes.
*/
off = (PAGEHDRSZ + data->mv_size) & -sizeof(size_t);
if (m3->mc_pg[mc->mc_top] == mp) {
if (m3->mc_ki[mc->mc_top] == ki) {
m3->mc_flags |= C_DEL;
- if (mc->mc_db->md_flags & MDB_DUPSORT)
- m3->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
} else if (m3->mc_ki[mc->mc_top] > ki) {
m3->mc_ki[mc->mc_top]--;
}
continue;
if (m3->mc_pg[mc->mc_top] == mp) {
/* if m3 points past last node in page, find next sibling */
- if (m3->mc_ki[mc->mc_top] >= nkeys) {
- rc = mdb_cursor_sibling(m3, 1);
- if (rc == MDB_NOTFOUND) {
- m3->mc_flags |= C_EOF;
- rc = MDB_SUCCESS;
+ if (m3->mc_ki[mc->mc_top] >= mc->mc_ki[mc->mc_top]) {
+ if (m3->mc_ki[mc->mc_top] >= nkeys) {
+ rc = mdb_cursor_sibling(m3, 1);
+ if (rc == MDB_NOTFOUND) {
+ m3->mc_flags |= C_EOF;
+ rc = MDB_SUCCESS;
+ continue;
+ }
+ }
+ if (mc->mc_db->md_flags & MDB_DUPSORT) {
+ MDB_node *node = NODEPTR(m3->mc_pg[m3->mc_top], m3->mc_ki[m3->mc_top]);
+ if (node->mn_flags & F_DUPDATA) {
+ mdb_xcursor_init1(m3, node);
+ m3->mc_xcursor->mx_cursor.mc_flags |= C_DEL;
+ }
}
}
}
static int ESECT
mdb_env_cwalk(mdb_copy *my, pgno_t *pg, int flags)
{
- MDB_cursor mc;
+ MDB_cursor mc = {0};
MDB_txn *txn = my->mc_txn;
MDB_node *ni;
MDB_page *mo, *mp, *leaf;
return MDB_SUCCESS;
mc.mc_snum = 1;
- mc.mc_top = 0;
mc.mc_txn = txn;
rc = mdb_page_get(my->mc_txn, *pg, &mc.mc_pg[0], NULL);