Re: (ITS#9037) observing crash in mdb_cursor_put()
by myk@mykzilla.org
myk(a)mykzilla.org wrote on 2019-06-20 23:39:
> myk(a)mykzilla.org wrote on 2019-06-20 23:35:
>> I'm unsure if it's related, but with this change to mdb.c, the following
>> test program (which resembles Firefox's usage) asserts in
>> mdb_cursor_init because rc is MDB_NOTFOUND.
> Erm, here's the program without the errant characters:
My apologies, I'm unsure why the characters appeared the second time as
well. (I tested first by manually removing them, sending the message to
myself, and then confirming they didn't appear.) I've saved the program
to this GitHub gist:
https://gist.github.com/mykmelez/ac75a7ab0a0d09a7d709be63806d01d7
-myk
4 years, 5 months
Re: (ITS#9037) observing crash in mdb_cursor_put()
by myk@mykzilla.org
myk(a)mykzilla.org wrote on 2019-06-20 23:35:
> I'm unsure if it's related, but with this change to mdb.c, the following
> test program (which resembles Firefox's usage) asserts in
> mdb_cursor_init because rc is MDB_NOTFOUND.
Erm, here's the program without the errant characters:
#include <stdio.h>
#include <stdlib.h>
#include "lmdb.h"
#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)),
abort()))
int main(int argc,char * argv[])
{
int rc;
MDB_env *env;
MDB_dbi dbi;
MDB_val key, data;
MDB_txn *txn;
char sval[] = "foo";
char dval[] = "bar";
E(mdb_env_create(&env));
E(mdb_env_set_maxdbs(env, 2));
E(mdb_env_open(env, "./mytestdb", 0, 0664));
E(mdb_txn_begin(env, NULL, 0, &txn));
E(mdb_dbi_open(txn, "subdb", MDB_CREATE, &dbi));
E(mdb_txn_commit(txn));
key.mv_size = 3;
key.mv_data = sval;
data.mv_size = 3;
data.mv_data = dval;
E(mdb_txn_begin(env, NULL, 0, &txn));
E(mdb_put(txn, dbi, &key, &data, 0));
E(mdb_txn_commit(txn));
mdb_dbi_close(env, dbi);
mdb_env_close(env);
return 0;
}
4 years, 5 months
Re: (ITS#9037) observing crash in mdb_cursor_put()
by myk@mykzilla.org
hyc(a)symas.com wrote on 2019-06-19 09:55:
> Maybe. For testing purposes you could try something like this
> diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c
> index 692feaa38b..e41f3bc36a 100644
> --- a/libraries/liblmdb/mdb.c
> +++ b/libraries/liblmdb/mdb.c
> @@ -7620,7 +7620,8 @@ mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
> mc->mc_xcursor = NULL;
> }
> if (*mc->mc_dbflag & DB_STALE) {
> - mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
> + int rc = mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
> + mdb_cassert(mc, !rc);
> }
> }
I'm unsure if it's related, but with this change to mdb.c, the following
test program (which resembles Firefox's usage) asserts in
mdb_cursor_init because rc is MDB_NOTFOUND.
#include <stdio.h>
#include <stdlib.h>
#include "lmdb.h"
#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)),
abort()))
int main(int argc,char * argv[])
{
int rc;
MDB_env *env;
MDB_dbi dbi;
MDB_val key, data;
MDB_txn *txn;
char sval[] = "foo";
char dval[] = "bar";
E(mdb_env_create(&env));
E(mdb_env_set_maxdbs(env, 2));
E(mdb_env_open(env, "./mytestdb", 0, 0664));
E(mdb_txn_begin(env, NULL, 0, &txn));
E(mdb_dbi_open(txn, "subdb", MDB_CREATE, &dbi));
E(mdb_txn_commit(txn));
key.mv_size = 3;
key.mv_data = sval;
data.mv_size = 3;
data.mv_data = dval;
E(mdb_txn_begin(env, NULL, 0, &txn));
E(mdb_put(txn, dbi, &key, &data, 0));
E(mdb_txn_commit(txn));
mdb_dbi_close(env, dbi);
mdb_env_close(env);
return 0;
}
Without the change to mdb.c, however, the program appears to work correctly.
-myk
4 years, 5 months
Re: (ITS#9039) key corruption using mdb_put and differing data
by hyc@symas.com
lmdb(a)pluckeye.net wrote:
> Full_Name: Jonny Wilkes
> Version: 2.4.2
> OS: Linux
> URL: ftp://ftp.openldap.org/incoming/
> Submission from: (NULL) (67.160.82.31)
>
>
> The following code shows key corruption.
Yes, because you've misused the API.
>
> I am probably using the API wrong, but I don't see how. I apologize in advance
> for not having a clue.
Read the Note http://www.lmdb.tech/doc/group__mdb.html#ga8bf10cd91d3f3a83a34d04ce6b07992d
Further comments below.
> And now, on to the test. It can be compiled and run like so:
>
> gcc t1.c -llmdb && ./a.out
>
> --------- t1.c starts here ---------
> /*
>
> The output of this program using liblmdb0 v0.9.21-1 on Ubuntu is:
>
> --- dump ---
> key12345
> key67890
> --- dump ---
> key12345
> y12345
>
> Why? What happened to key67890?
>
> */
>
> #include <lmdb.h>
> #if USE_SOURCE
> #include "midl.c"
> #include "mdb.c"
> #endif
> #include <stdio.h>
> #include <string.h>
> #include <unistd.h>
>
> #define P(K) printf("%s\n", (char *)K.mv_data)
>
> #define X(x) do { int _x = x; if (_x) fprintf(stderr, "%d %s\n", _x,
> mdb_strerror(_x)); } while (0)
>
> const char *path = "/tmp/lmdb-why.tmp";
> MDB_env *env;
>
> /*
> * setup creates /tmp/lmdb-why.tmp with 2 keys with the data "hey":
> *
> * 1. key12345 : hey
> * 2. key67890 : hey
> */
> int
> setup(void)
> {
> unlink(path);
> if (!env) {
> X(mdb_env_create(&env));
> X(mdb_env_open(env, path, MDB_NOSUBDIR, 0664));
> }
>
> MDB_txn *txn; X(mdb_txn_begin(env, NULL, 0, &txn));
> MDB_dbi dbi; X(mdb_dbi_open(txn, NULL, 0, &dbi));
>
> const char *keys[] = {
> "key12345",
> "key67890"
> };
> for (unsigned i = 0; i < 2; ++i) {
> MDB_val key, data;
> key.mv_data = (void *)keys[i];
> key.mv_size = strlen(keys[i])+1;
> data.mv_data = "hey";
> data.mv_size = 4;
> X(mdb_put(txn, dbi, &key, &data, 0));
> }
> X(mdb_txn_commit(txn));
> return 0;
> }
>
> int
> dump(void)
> {
> printf("--- dump ---\n");
>
> MDB_txn *txn; X(mdb_txn_begin(env, NULL, 0, &txn));
> MDB_dbi dbi; X(mdb_dbi_open(txn, NULL, 0, &dbi));
> MDB_cursor *cursor; X(mdb_cursor_open(txn, dbi, &cursor));
>
> MDB_val key;
> int rc;
> while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT)) == 0) {
> P(key);
> }
>
> mdb_cursor_close(cursor);
> if (MDB_NOTFOUND != rc)
> return rc;
> mdb_txn_abort(txn);
> return 0;
> }
>
> /*
> * change_data change the data for each key to "there" using mdb_put.
> * After it completes, the keys are corrupt.
> */
> int
> change_data(void)
> {
> MDB_txn *txn; X(mdb_txn_begin(env, NULL, 0, &txn));
> MDB_dbi dbi; X(mdb_dbi_open(txn, NULL, 0, &dbi));
> MDB_cursor *cursor; X(mdb_cursor_open(txn, dbi, &cursor));
>
> MDB_val key;
> int rc;
> while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT)) == 0) {
> MDB_val data;
> data.mv_data = (void *)"there";
> data.mv_size = 6; /* ! */
> X(mdb_put(txn, dbi, &key, &data, 0));
As documented, the key returned by mdb_cursor_get is only valid until the next update operation.
Since you've called mdb_put here, the key is altered while the put is executing, and so you get
your corruption. You have to copy the key if you want this particular code to work. But even so,
you're not using the API optimally. Since you have a cursor already, you should be using
mdb_cursor_put instead.
> }
> mdb_cursor_close(cursor);
> if (MDB_NOTFOUND != rc)
> return rc;
>
> X(mdb_txn_commit(txn));
> return 0;
> }
>
> int main(void)
> {
> X(setup());
> X(dump());
> X(change_data());
> X(dump());
> return 0;
> }
Closing this ITS.
--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/
4 years, 5 months
(ITS#9039) key corruption using mdb_put and differing data
by lmdb@pluckeye.net
Full_Name: Jonny Wilkes
Version: 2.4.2
OS: Linux
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (67.160.82.31)
The following code shows key corruption.
I am probably using the API wrong, but I don't see how. I apologize in advance
for not having a clue.
And now, on to the test. It can be compiled and run like so:
gcc t1.c -llmdb && ./a.out
--------- t1.c starts here ---------
/*
The output of this program using liblmdb0 v0.9.21-1 on Ubuntu is:
--- dump ---
key12345
key67890
--- dump ---
key12345
y12345
Why? What happened to key67890?
*/
#include <lmdb.h>
#if USE_SOURCE
#include "midl.c"
#include "mdb.c"
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define P(K) printf("%s\n", (char *)K.mv_data)
#define X(x) do { int _x = x; if (_x) fprintf(stderr, "%d %s\n", _x,
mdb_strerror(_x)); } while (0)
const char *path = "/tmp/lmdb-why.tmp";
MDB_env *env;
/*
* setup creates /tmp/lmdb-why.tmp with 2 keys with the data "hey":
*
* 1. key12345 : hey
* 2. key67890 : hey
*/
int
setup(void)
{
unlink(path);
if (!env) {
X(mdb_env_create(&env));
X(mdb_env_open(env, path, MDB_NOSUBDIR, 0664));
}
MDB_txn *txn; X(mdb_txn_begin(env, NULL, 0, &txn));
MDB_dbi dbi; X(mdb_dbi_open(txn, NULL, 0, &dbi));
const char *keys[] = {
"key12345",
"key67890"
};
for (unsigned i = 0; i < 2; ++i) {
MDB_val key, data;
key.mv_data = (void *)keys[i];
key.mv_size = strlen(keys[i])+1;
data.mv_data = "hey";
data.mv_size = 4;
X(mdb_put(txn, dbi, &key, &data, 0));
}
X(mdb_txn_commit(txn));
return 0;
}
int
dump(void)
{
printf("--- dump ---\n");
MDB_txn *txn; X(mdb_txn_begin(env, NULL, 0, &txn));
MDB_dbi dbi; X(mdb_dbi_open(txn, NULL, 0, &dbi));
MDB_cursor *cursor; X(mdb_cursor_open(txn, dbi, &cursor));
MDB_val key;
int rc;
while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT)) == 0) {
P(key);
}
mdb_cursor_close(cursor);
if (MDB_NOTFOUND != rc)
return rc;
mdb_txn_abort(txn);
return 0;
}
/*
* change_data change the data for each key to "there" using mdb_put.
* After it completes, the keys are corrupt.
*/
int
change_data(void)
{
MDB_txn *txn; X(mdb_txn_begin(env, NULL, 0, &txn));
MDB_dbi dbi; X(mdb_dbi_open(txn, NULL, 0, &dbi));
MDB_cursor *cursor; X(mdb_cursor_open(txn, dbi, &cursor));
MDB_val key;
int rc;
while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT)) == 0) {
MDB_val data;
data.mv_data = (void *)"there";
data.mv_size = 6; /* ! */
X(mdb_put(txn, dbi, &key, &data, 0));
}
mdb_cursor_close(cursor);
if (MDB_NOTFOUND != rc)
return rc;
X(mdb_txn_commit(txn));
return 0;
}
int main(void)
{
X(setup());
X(dump());
X(change_data());
X(dump());
return 0;
}
4 years, 5 months
Re: (ITS#9037) observing crash in mdb_cursor_put()
by hyc@symas.com
myk(a)mykzilla.org wrote:
> hyc(a)symas.com wrote on 2019-06-18 01:30:
>> There is no issue with mdb_cursor_put then. The question is why didn't mdb_page_search find the DBI's root node?
> Would it be useful for mdb_cursor_init to return the result code of
> mdb_page_search, and for mdb_put to then return that code if it isn't
> MDB_SUCCESS?
Maybe. For testing purposes you could try something like this
diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c
index 692feaa38b..e41f3bc36a 100644
--- a/libraries/liblmdb/mdb.c
+++ b/libraries/liblmdb/mdb.c
@@ -7620,7 +7620,8 @@ mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
mc->mc_xcursor = NULL;
}
if (*mc->mc_dbflag & DB_STALE) {
- mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
+ int rc = mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
+ mdb_cassert(mc, !rc);
}
}
I suspect the problem will simply be that you've used an invalid DBI.
>
> That wouldn't resolve the problem, but it might avoid the crash and
> provide some insight into the failure (if mdb_page_search is actually
> returning a failure code when it doesn't find the DBI's root node).
>
> -myk
>
>
>
>
>
--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/
4 years, 5 months
Re: (ITS#9037) observing crash in mdb_cursor_put()
by myk@mykzilla.org
hyc(a)symas.com wrote on 2019-06-18 01:30:
> There is no issue with mdb_cursor_put then. The question is why didn't mdb_page_search find the DBI's root node?
Would it be useful for mdb_cursor_init to return the result code of
mdb_page_search, and for mdb_put to then return that code if it isn't
MDB_SUCCESS?
That wouldn't resolve the problem, but it might avoid the crash and
provide some insight into the failure (if mdb_page_search is actually
returning a failure code when it doesn't find the DBI's root node).
-myk
4 years, 5 months
Re: (ITS#9037) observing crash in mdb_cursor_put()
by grobins@pulsesecure.net
--_000_MN2PR06MB55017A7261FA27380778753BAFEA0MN2PR06MB5501namp_
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
<repost since the previous message came as 64 encoded, apologies>
Hello Howard,
we are not able to reproduce the issue consistently so test code is not ava=
ilable at this time, and I do believe this issue will be present in the lat=
est code as well since Myk also reported the same.. Attaching analysis fro=
m our side, hope it helps.
The call stack what we have seen is,
#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe52d18, key=3D0xffe52e74, dat=
a=3D0xffe52e6c, flags=3D0) at mdb.c:6688
#1 0x0011c8ec in mdb_put (txn=3D0xdc13f008, dbi=3D2, key=3D0xffe52e74, =
data=3D0xffe52e6c, flags=3D0) at mdb.c:8771
#2 0x00b792b8 in LMDB::LMDBContext::createSession (this=3D0x80ca418, si=
d=3D0x8297be4 "sidebf3708f0fd9fcb8e062529da47adf51402dfc4600000000+") at lm=
dbint.cc:460
#3 0x08053564 in updateLMDB (request=3D..., forward=3D@0xffe5315f) at s=
essionserver.cc:1075
#4 processRequestWithoutResponse (request=3D..., forward=3D@0xffe5315f)=
at sessionserver.cc:1160
#5 0x08056a80 in processRequest (this=3D0x80b2ac0, fd=3D33) at sessions=
erver.cc:1189
#6 readFromSock (this=3D0x80b2ac0, fd=3D33) at sessionserver.cc:1342
#7 SockHandler::ioReady (this=3D0x80b2ac0, fd=3D33) at sessionserver.cc=
:1455
#8 0x00ba2592 in runCoreDispatcher (default_t=3D<value optimized out>, =
flags=3D-1) at fds.cc:889
#9 0x00ba2ff7 in DSEvntFds::runDispatcher () at fds.cc:945
#10 0x080559c6 in main () at sessionserver.cc:1739
Here it is helpful to examine frames #0 and #1 in detail in relation to the=
relevant source code /libraries/liblmdb/mdb.c.
Frame #1
#1 0x0011c8ec in mdb_put (txn=3D0xdc13f008, dbi=3D2, key=3D0xffe52e74, dat=
a=3D0xffe52e6c, flags=3D0) at mdb.c:8771
mc =3D {mc_next =3D 0x0, mc_backup =3D 0x0, mc_xcursor =3D 0x0, mc_=
txn =3D 0xdc13f008, mc_dbi =3D 2, mc_db =3D 0xdc13f088, mc_dbx =3D 0xe12150=
38, mc_dbflag =3D 0xdc1cf09a "\033", '\032' <repeats 51 times>, mc_snum =3D=
0, mc_top =3D 0, mc_flags =3D 0, mc_pg =3D {0x0, 0x80b2ac0, 0xffe52d68, 0x=
28afce, 0xdc13f008, 0x80ce9b0, 0xffe52dc8, 0x4c5ff4, 0x2b, 0x80b2ac0, 0xffe=
52d98, 0x49209a, 0x2b, 0x4c5ff4, 0x2121cb, 0x21576c, 0x8297d34, 0x3497af, 0=
x21576c, 0x21316a, 0x8297d34, 0x80ac7b0, 0x1e, 0x46eed6, 0x2b, 0x0, 0x80ce9=
b0, 0x4c5ff4, 0x80ac7b0, 0x8297d34, 0xffe52df8, 0x46fb96}, mc_ki =3D {0, 20=
89, 51120, 2058, 30, 0, 16796, 17, 11760, 65509, 3, 0, 32040, 2089, 30, 0, =
0, 0, 0, 0, 3, 0, 24564, 76, 51120, 2058, 10944, 2059, 11800, 65509, 64758,=
70}} <--------
mx =3D {mx_cursor =3D {mc_next =3D 0x38, mc_backup =3D 0x3, mc_xcur=
sor =3D 0x0, mc_txn =3D 0x0, mc_dbi =3D 0, mc_db =3D 0x28, mc_dbx =3D 0x0, =
mc_dbflag =3D 0x0, mc_snum =3D 3, mc_top =3D 0, mc_flags =3D 17, mc_pg =3D =
{0x3a93d8, 0x10, 0x0, 0x18, 0x3a93a0, 0x0, 0x3a93d0, 0x289abe, 0x3a93a0, 0x=
ffe52d3f, 0xffe52c68, 0x28afce, 0xffe52dbc, 0xffe52db4, 0x3, 0x4c5ff4, 0x11=
, 0x36c99b, 0x6e, 0x77, 0x7c, 0x5b, 0x38, 0x289abe, 0x0, 0x0, 0x0, 0x28, 0x=
0, 0x0, 0x3, 0x10}, mc_ki =3D {37848, 58, 51611, 54, 110, 0, 119, 0, 124, 0=
, 91, 0, 58, 0, 39614, 40, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 2, 0, 18, 0, 136=
, 0}}, mx_db =3D {md_pad =3D 3838936, md_flags =3D 51611, md_depth =3D 54, =
md_branch_pages =3D 110, md_leaf_pages =3D 119, md_overflow_pages =3D 124, =
md_entries =3D 91, md_root =3D 56}, mx_dbx =3D {md_name =3D {mv_size =3D 6,=
mv_data =3D 0x0}, md_cmp =3D 0, md_dcmp =3D 0, md_rel =3D 0x40, md_relctx =
=3D 0x0}, mx_dbflag =3D 0 '\000'}
rc =3D 0
And source code for mdb_put() is from mdb.c
int
mdb_put(MDB_txn *txn, MDB_dbi dbi,
MDB_val *key, MDB_val *data, unsigned int flags) {
MDB_cursor mc;
MDB_xcursor mx;
int rc;
if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
return EINVAL;
if (flags & ~(MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB=
_APPEND|MDB_APPENDDUP))
return EINVAL;
if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
return (txn->mt_flags & MDB_TXN_RDONLY) ? E=
ACCES : MDB_BAD_TXN;
mdb_cursor_init(&mc, txn, dbi, &mx); <-------- see source c=
ode below
mc.mc_next =3D txn->mt_cursors[dbi];
txn->mt_cursors[dbi] =3D &mc;
rc =3D mdb_cursor_put(&mc, key, data, flags); <-------- see=
Frame #0
txn->mt_cursors[dbi] =3D mc.mc_next;
return rc;
}
Source Code For mdb_cursor_init() From mdb.c
/** Initialize a cursor for a given transaction and database. */ static voi=
d mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *m=
x) {
mc->mc_next =3D NULL;
mc->mc_backup =3D NULL;
mc->mc_dbi =3D dbi;
mc->mc_txn =3D txn;
mc->mc_db =3D &txn->mt_dbs[dbi];
mc->mc_dbx =3D &txn->mt_dbxs[dbi];
mc->mc_dbflag =3D &txn->mt_dbflags[dbi];
mc->mc_snum =3D 0; <--------
mc->mc_top =3D 0; <--------
mc->mc_pg[0] =3D 0; <--------
mc->mc_ki[0] =3D 0;
mc->mc_flags =3D 0;
if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
mdb_tassert(txn, mx !=3D NULL);
mc->mc_xcursor =3D mx;
mdb_xcursor_init0(mc);
} else {
mc->mc_xcursor =3D NULL;
}
if (*mc->mc_dbflag & DB_STALE) { <-------- false *mc->mc_db=
flag =3D 27, DB_STALE =3D 0x02 /**< Named-DB record is old=
er than txnID */
mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
}
}
>From this we know that when mdb_cursor_put() is called, the following value=
s remain assigned:
mc->mc_snum =3D 0; <--------
mc->mc_top =3D 0; <--------
mc->mc_pg[0] =3D 0; <--------
and its noted these two values still have their initial values at the time =
of the segmentation fault.
(gdb) fr 0
#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe52d18, key=3D0xffe52e74, data=3D=
0xffe52e6c, flags=3D0) at mdb.c:6688
6688 in mdb.c
(gdb) p mc->mc_top
$1 =3D 0
(gdb) p mc->mc_pg[mc->mc_top]
$19 =3D (MDB_page *) 0x0
Let us consider how the path taken through mdb_cursor_put() could account f=
or these null variable values which result in a segmentation fault.
Frame #0
#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe52d18, key=3D0xffe52e74, data=
=3D0xffe52e6c, flags=3D0) at mdb.c:6688 <-------- flags =3D 0
env =3D 0x80ce9b0
leaf =3D <value optimized out>
fp =3D <value optimized out>
mp =3D 0x38
sub_root =3D 0x0
fp_flags =3D <value optimized out>
xdata =3D {mv_size =3D 3838880, mv_data =3D 0xdc1cf09a}
rdata =3D 0xffe52e6c
dkey =3D {mv_size =3D 0, mv_data =3D 0x3a93cc}
olddata =3D {mv_size =3D 22, mv_data =3D 0x36c820}
dummy =3D {md_pad =3D 22, md_flags =3D 11128, md_depth =3D 65509, m=
d_branch_pages =3D 16, md_leaf_pages =3D 1507329, md_overflow_pages =3D 0, =
md_entries =3D 3838928, md_root =3D 3833844}
do_sub =3D 0
insert_key =3D -30798 <-------- #define MDB_NOTFOUND (-307=
98)
insert_data =3D -30798 <-------- #define MDB_NOTFOUND (-3079=
8)
mcount =3D 0
dcount =3D 0
nospill =3D 0 <--------
nsize =3D <value optimized out>
rc =3D 0
rc2 =3D <value optimized out>
nflags =3D 0 <--------
__func__ =3D "mdb_cursor_put"
We know that mc->mc_top and mc->mc_pg[0] were initialized to 0 in mdb_curso=
r_init(). As my annotations of the source code below suggest, careful analy=
sis reveals that the paths actually taken through mdb_cursor_put() do not m=
odify these assignments.
Excerpted Source Code For mdb_cursor_put() From mdb.c
int
mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
unsigned int flags)
{
MDB_env *env;
MDB_node *leaf =3D NULL;
MDB_page *fp, *mp, *sub_root =3D NULL;
uint16_t fp_flags;
MDB_val xdata, *rdata, dkey, o=
lddata;
MDB_db dummy;
int do_sub =3D 0, insert_key, insert_data;
unsigned int mcount =3D 0, dcount =3D 0, nospill;
size_t nsize;
int rc, rc2;
unsigned int nflags;
DKBUF;
if (mc =3D=3D NULL || key =3D=3D NULL)
return EINVAL;
env =3D mc->mc_txn->mt_env;
/* Check this first so counter will always be zero on any
* early failures.
*/
if (flags & MDB_MULTIPLE) {
dcount =3D data[1].mv_size;
data[1].mv_size =3D 0;
if (!F_ISSET(mc->mc_db->md_flags, MDB_DUPFI=
XED))
return MDB_INCOMPATIBLE;
}
nospill =3D flags & MDB_NOSPILL;
flags &=3D ~MDB_NOSPILL;
if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED)=
)
return (mc->mc_txn->mt_flags & MDB_TXN_RDON=
LY) ? EACCES : MDB_BAD_TXN;
if (key->mv_size-1 >=3D ENV_MAXKEY(env))
return MDB_BAD_VALSIZE;
#if SIZE_MAX > MAXDATASIZE
if (data->mv_size > ((mc->mc_db->md_flags & MDB_DUPSORT) ? =
ENV_MAXKEY(env) : MAXDATASIZE))
return MDB_BAD_VALSIZE;
#else
if ((mc->mc_db->md_flags & MDB_DUPSORT) && data->mv_size > =
ENV_MAXKEY(env))
return MDB_BAD_VALSIZE;
#endif
DPRINTF(("=3D=3D> put db %d key [%s], size %"Z"u, data size=
%"Z"u",
DDBI(mc), DKEY(key), key ? key->mv_size : 0=
, data->mv_size));
dkey.mv_size =3D 0;
if (flags =3D=3D MDB_CURRENT) { <-------- false flags =3D 0
if (!(mc->mc_flags & C_INITIALIZED))
return EINVAL;
rc =3D MDB_SUCCESS;
} else if (mc->mc_db->md_root =3D=3D P_INVALID) { <--------=
false, mc->mc_db->md_root =3D 68
/* new database, cursor has nothing to poin=
t to */
mc->mc_snum =3D 0;
mc->mc_top =3D 0;
mc->mc_flags &=3D ~C_INITIALIZED;
rc =3D MDB_NO_ROOT;
} else { <-------- executed
int exact =3D 0;
MDB_val d2;
if (flags & MDB_APPEND) { <-------- false f=
lags =3D 0
MDB_val k2;
rc =3D mdb_cursor_last(mc, =
&k2, &d2);
if (rc =3D=3D 0) {
rc =3D mc->=
mc_dbx->md_cmp(key, &k2);
if (rc > 0)=
{
=
rc =3D MDB_NOTFOUND;
=
mc->mc_ki[mc->mc_top]++;
} else {
=
/* new key is <=3D last key */
=
rc =3D MDB_KEYEXIST;
}
}
} else {<-------- executed
rc =3D mdb_cursor_set(mc, k=
ey, &d2, MDB_SET, &exact); <-------- returns -30798 which is MDB_NOTFOUND
}<-------- executed
if ((flags & MDB_NOOVERWRITE) && rc =3D=3D =
0) { <-------- false flags =3D 0
DPRINTF(("duplicate key [%s=
]", DKEY(key)));
*data =3D d2;
return MDB_KEYEXIST;
}
if (rc && rc !=3D MDB_NOTFOUND) <-------- f=
alse rc =3D MDB_NOTFOUND
return rc;
}<-------- executed
if (mc->mc_flags & C_DEL)
mc->mc_flags ^=3D C_DEL;
/* Cursor is positioned, check for room in the dirty list *=
/
if (!nospill) { <-------- true
if (flags & MDB_MULTIPLE) {
rdata =3D &xdata;
xdata.mv_size =3D data->mv_=
size * dcount;
} else {
rdata =3D data; <-------- e=
xecuted
}
if ((rc2 =3D mdb_page_spill(mc, key, rdata)=
)) <-------- returned 0 or would have returned
return rc2;
}<-------- executed
if (rc =3D=3D MDB_NO_ROOT) { <-------- false
MDB_page *np;
/* new database, write a root leaf page */
DPUTS("allocating new root leaf page");
if ((rc2 =3D mdb_page_new(mc, P_LEAF, 1, &n=
p))) {
return rc2;
}
mdb_cursor_push(mc, np);
mc->mc_db->md_root =3D np->mp_pgno;
mc->mc_db->md_depth++;
*mc->mc_dbflag |=3D DB_DIRTY;
if ((mc->mc_db->md_flags & (MDB_DUPSORT|MDB=
_DUPFIXED))
=3D=3D MDB_DUPFIXED)
np->mp_flags |=3D P_LEAF2;
mc->mc_flags |=3D C_INITIALIZED;
} else {
/* make sure all cursor pages are writable =
*/
rc2 =3D mdb_cursor_touch(mc); <-------- is =
this called and returns 0 because it does not return
if (rc2)
return rc2;
} <-------- executed
insert_key =3D insert_data =3D rc; <-------- rc =3D -30798 =
or MDB_NOTFOUND!
if (insert_key) { <-------- true
/* The key does not exist */
DPRINTF(("inserting key at index %i", mc->m=
c_ki[mc->mc_top]));
if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
LEAFSIZE(key, data) > env->=
me_nodemax) <-------- false since mc->mc_db->md_flags =3D 0
{
/* Too big for a node, inse=
rt in sub-DB. Set up an empty
* "old sub-page" for prep_s=
ubDB to expand to a full page.
*/
fp_flags =3D P_LEAF|P_DIRTY=
;
fp =3D env->me_pbuf;
fp->mp_pad =3D data->mv_siz=
e; /* used if MDB_DUPFIXED */
fp->mp_lower =3D fp->mp_upp=
er =3D (PAGEHDRSZ-PAGEBASE);
olddata.mv_size =3D PAGEHDR=
SZ;
goto prep_subDB;
} <-------- this was not executed, and the =
very long external else contingency below should be skipped!
} else {
/* there's only a key anyway, so this is a =
no-op */
if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
char *ptr;
unsigned int ksize =3D mc->=
mc_db->md_pad;
if (key->mv_size !=3D ksize=
)
return MDB_=
BAD_VALSIZE;
ptr =3D LEAF2KEY(mc->mc_pg[=
mc->mc_top], mc->mc_ki[mc->mc_top], ksize);
memcpy(ptr, key->mv_data, k=
size);
fix_parent:
/* if overwriting slot 0 of=
leaf, need to
* update branch key if ther=
e is a parent page
*/
if (mc->mc_top && !mc->mc_k=
i[mc->mc_top]) {
unsigned sh=
ort dtop =3D 1;
mc->mc_top-=
-;
/* slot 0 i=
s always an empty key, find real slot */
while (mc->=
mc_top && !mc->mc_ki[mc->mc_top]) {
=
mc->mc_top--;
=
dtop++;
}
if (mc->mc_=
ki[mc->mc_top])
=
rc2 =3D mdb_update_key(mc, key);
else
=
rc2 =3D MDB_SUCCESS;
mc->mc_top =
+=3D dtop;
if (rc2)
=
return rc2;
}
return MDB_SUCCESS;
}
more:
leaf =3D NODEPTR(mc->mc_pg[mc->mc_top], mc-=
>mc_ki[mc->mc_top]);
olddata.mv_size =3D NODEDSZ(leaf);
olddata.mv_data =3D NODEDATA(leaf);
/* DB has dups? */
if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSOR=
T)) {
/* Prepare (sub-)page/sub-D=
B to accept the new item,
* if needed. fp: old sub-p=
age or a header faking
* it. mp: new (sub-)page. =
offset: growth in page
* size. xdata: node data w=
ith new page or DB.
*/
unsigned i, off=
set =3D 0;
mp =3D fp =3D xdata.mv_data=
=3D env->me_pbuf;
mp->mp_pgno =3D mc->mc_pg[m=
c->mc_top]->mp_pgno;
/* Was a single item before=
, must convert now */
if (!F_ISSET(leaf->mn_flags=
, F_DUPDATA)) {
MDB_cmp_fun=
c *dcmp;
/* Just ove=
rwrite the current item */
if (flags =
=3D=3D MDB_CURRENT)
=
goto current;
dcmp =3D mc=
->mc_dbx->md_dcmp;
#if UINT_MAX < SIZE_MAX
if (dcmp =
=3D=3D mdb_cmp_int && olddata.mv_size =3D=3D sizeof(size_t))
=
dcmp =3D mdb_cmp_clong;
#endif
/* does dat=
a match? */
if (!dcmp(d=
ata, &olddata)) {
=
if (flags & (MDB_NODUPDATA|MDB_APPENDDUP))
=
return MDB_KEYEXIST;
=
/* overwrite it */
=
goto current;
}
/* Back up =
original data item */
dkey.mv_siz=
e =3D olddata.mv_size;
dkey.mv_dat=
a =3D memcpy(fp+1, olddata.mv_data, olddata.mv_size);
/* Make sub=
-page header for the dup items, with dummy body */
fp->mp_flag=
s =3D P_LEAF|P_DIRTY|P_SUBP;
fp->mp_lowe=
r =3D (PAGEHDRSZ-PAGEBASE);
xdata.mv_si=
ze =3D PAGEHDRSZ + dkey.mv_size + data->mv_size;
if (mc->mc_=
db->md_flags & MDB_DUPFIXED) {
=
fp->mp_flags |=3D P_LEAF2;
=
fp->mp_pad =3D data->mv_size;
=
xdata.mv_size +=3D 2 * data->mv_size; /* leave space for 2 more *=
/
} else {
=
xdata.mv_size +=3D 2 * (sizeof(indx_t) + NODESIZE) +
=
(dkey.mv_size & 1) + (data->mv_size & 1);
}
fp->mp_uppe=
r =3D xdata.mv_size - PAGEBASE;
olddata.mv_=
size =3D xdata.mv_size; /* pretend olddata is fp */
} else if (leaf->mn_flags &=
F_SUBDATA) {
/* Data is =
on sub-DB, just store it */
flags |=3D =
F_DUPDATA|F_SUBDATA;
goto put_su=
b;
} else {
/* Data is =
on sub-page */
fp =3D oldd=
ata.mv_data;
switch (fla=
gs) {
default:
=
if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
=
offset =3D EVEN(NODESIZE + sizeof(indx_t) +
=
data->mv_size);
=
break;
=
}
=
offset =3D fp->mp_pad;
=
if (SIZELEFT(fp) < offset) {
=
offset *=3D 4; /* space for 4 more */
=
break;
=
}
=
/* FALLTHRU: Big enough MDB_DUPFIXED sub-page */
case MDB_CU=
RRENT:
=
fp->mp_flags |=3D P_DIRTY;
=
COPY_PGNO(fp->mp_pgno, mp->mp_pgno);
=
mc->mc_xcursor->mx_cursor.mc_pg[0] =3D fp;
=
flags |=3D F_DUPDATA;
=
goto put_sub;
}
xdata.mv_si=
ze =3D olddata.mv_size + offset;
}
fp_flags =3D fp->mp_flags;
if (NODESIZE + NODEKSZ(leaf=
) + xdata.mv_size > env->me_nodemax) {
=
/* Too big for a sub-page, convert to sub-DB */
=
fp_flags &=3D ~P_SUBP;
prep_subDB:
=
if (mc->mc_db->md_flags & MDB_DUPFIXED) {
=
fp_flags |=3D P_LEAF2;
=
dummy.md_pad =3D fp->mp_pad;
=
dummy.md_flags =3D MDB_DUPFIXED;
=
if (mc->mc_db->md_flags & MDB_INTEGERDUP)
=
dummy.md_flags |=3D MDB_INTEGERKEY;
=
} else {
=
dummy.md_pad =3D 0;
=
dummy.md_flags =3D 0;
=
}
=
dummy.md_depth =3D 1;
=
dummy.md_branch_pages =3D 0;
=
dummy.md_leaf_pages =3D 1;
=
dummy.md_overflow_pages =3D 0;
=
dummy.md_entries =3D NUMKEYS(fp);
=
xdata.mv_size =3D sizeof(MDB_db);
=
xdata.mv_data =3D &dummy;
=
if ((rc =3D mdb_page_alloc(mc, 1, &mp)))
=
return rc;
=
offset =3D env->me_psize - olddata.mv_size;
=
flags |=3D F_DUPDATA|F_SUBDATA;
=
dummy.md_root =3D mp->mp_pgno;
=
sub_root =3D mp;
}
if (mp !=3D fp) {
mp->mp_flag=
s =3D fp_flags | P_DIRTY;
mp->mp_pad =
=3D fp->mp_pad;
mp->mp_lowe=
r =3D fp->mp_lower;
mp->mp_uppe=
r =3D fp->mp_upper + offset;
if (fp_flag=
s & P_LEAF2) {
=
memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad);
} else {
=
memcpy((char *)mp + mp->mp_upper + PAGEBASE, (char *)fp + fp->mp_upper=
+ PAGEBASE,
=
olddata.mv_size - fp->mp_upper - PAGEBASE);
=
for (i=3D0; i<NUMKEYS(fp); i++)
=
mp->mp_ptrs[i] =3D fp->mp_ptrs[i] + offset;
}
}
rdata =3D &xdata;
flags |=3D F_DUPDATA;
do_sub =3D 1;
if (!insert_key)
mdb_node_de=
l(mc, 0);
goto new_sub;
}
current:
/* LMDB passes F_SUBDATA in 'flags' to writ=
e a DB record */
if ((leaf->mn_flags ^ flags) & F_SUBDATA)
return MDB_INCOMPATIBLE;
/* overflow page overwrites need special ha=
ndling */
if (F_ISSET(leaf->mn_flags, F_BIGDATA)) { <=
-------- is this taken?
MDB_page *omp;
pgno_t pg;
int level, ovpages, dpages =
=3D OVPAGES(data->mv_size, env->me_psize);
memcpy(&pg, olddata.mv_data=
, sizeof(pg));
if ((rc2 =3D mdb_page_get(m=
c->mc_txn, pg, &omp, &level)) !=3D 0)
return rc2;
ovpages =3D omp->mp_pages;
/* Is the ov page large eno=
ugh? */
if (ovpages >=3D dpages) {
if (!(omp->mp_flags & P_D=
IRTY) &&
(level ||=
(env->me_flags & MDB_WRITEMAP)))
{
rc =3D mdb_=
page_unspill(mc->mc_txn, omp, &omp); <-------- is this taken?
if (rc)
=
return rc;
level =3D 0=
; /* dirty in this txn or clean */
}
/* Is it dirty? */
if (omp->mp_flags & P_DIR=
TY) {
/* yes, ove=
rwrite it. Note in this case we don't
* bother to=
try shrinking the page if the new data
* is smalle=
r than the overflow threshold.
*/
if (level >=
1) {
=
/* It is writable only in a parent txn */
=
size_t sz =3D (size_t) env->me_psize * ovpages, off;
=
MDB_page *np =3D mdb_page_malloc(mc->mc_txn, ovpages);
=
MDB_ID2 id2;
=
if (!np)
=
return ENOMEM;
=
id2.mid =3D pg;
=
id2.mptr =3D np;
=
/* Note - this page is already counted in parent's dirty_room */
=
rc2 =3D mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2);
=
mdb_cassert(mc, rc2 =3D=3D 0);
=
if (!(flags & MDB_RESERVE)) {
=
/* Copy end of page, adjusting alignment so
=
* compiler may copy words instead of bytes.
=
*/
=
off =3D (PAGEHDRSZ + data->mv_size) & -sizeof(size_t);
=
memcpy((size_t *)((char *)np + off),
=
(size_t *)((char *)omp + off), sz - of=
f);
=
sz =3D PAGEHDRSZ;
=
}
=
memcpy(np, omp, sz); /* Copy beginning of page */
=
omp =3D np;
}
SETDSZ(leaf=
, data->mv_size);
if (F_ISSET=
(flags, MDB_RESERVE))
=
data->mv_data =3D METADATA(omp);
else
=
memcpy(METADATA(omp), data->mv_data, data->mv_size);
return MDB_=
SUCCESS;
}
}
if ((rc2 =3D mdb_ovpage_fre=
e(mc, omp)) !=3D MDB_SUCCESS)
return rc2;
} else if (data->mv_size =3D=3D olddata.mv_=
size) {
/* same size, just replace =
it. Note that we could
* also reuse this node if t=
he new data is smaller,
* but instead we opt to shr=
ink the node in that case.
*/
if (F_ISSET(flags, MDB_RESE=
RVE))
data->mv_da=
ta =3D olddata.mv_data;
else if (!(mc->mc_flags & C=
_SUB))
memcpy(oldd=
ata.mv_data, data->mv_data, data->mv_size);
else {
memcpy(NODE=
KEY(leaf), key->mv_data, key->mv_size);
goto fix_pa=
rent;
}
return MDB_SUCCESS;
}
mdb_node_del(mc, 0);
} <-------- This entire else contingency was likely skipped=
!!
rdata =3D data;
new_sub:
nflags =3D flags & NODE_ADD_FLAGS;
nsize =3D IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : =
mdb_leaf_size(env, key, rdata); <-------- SEGV
...
This may be an identifiable bug in mdb_cursor_put() as It does not safely h=
andle the case when the noted call to mdb_cursor_set() returns MDB_NOTFOUND=
(-30798)!
It explicitly fails to preemptively exit by returning an error in this case=
.
The value of -30798 is in turn assigned to insert_key, which is therefore n=
on-null in the condition of the subsequent if statement.
insert_key =3D insert_data =3D rc; <-------- insert_key =3D=
-30798 or MDB_NOTFOUND!
if (insert_key) { <-------- true
/* The key does not exist */
DPRINTF(("inserting key at index %i", mc->m=
c_ki[mc->mc_top]));
if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
LEAFSIZE(key, data) > env->=
me_nodemax) <-------- false since mc->mc_db->md_flags =3D 0
{
/* Too big for a node, inse=
rt in sub-DB. Set up an empty
* "old sub-page" for prep_s=
ubDB to expand to a full page.
*/
fp_flags =3D P_LEAF|P_DIRTY=
;
fp =3D env->me_pbuf;
fp->mp_pad =3D data->mv_siz=
e; /* used if MDB_DUPFIXED */
fp->mp_lower =3D fp->mp_upp=
er =3D (PAGEHDRSZ-PAGEBASE);
olddata.mv_size =3D PAGEHDR=
SZ;
goto prep_subDB;
} <-------- this was not executed, and the =
very long else contingency below is skipped!
} else {
Since mc->mc_db->md_flags =3D 0, the contingency in the embedded if stateme=
nt fails.
The segmentation fault occurs due to the call of IS_LEAF2 on the null point=
er mc->mc_pg[0].
rdata =3D data;
new_sub:
nflags =3D flags & NODE_ADD_FLAGS;
nsize =3D IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : =
mdb_leaf_size(env, key, rdata); <-------- SEGV
Regards,
Robins.
--_000_MN2PR06MB55017A7261FA27380778753BAFEA0MN2PR06MB5501namp_
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:=
//www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dus-ascii"=
>
<meta name=3D"Generator" content=3D"Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
{mso-style-priority:99;
mso-style-link:"Plain Text Char";
margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
span.EmailStyle17
{mso-style-type:personal-compose;
font-family:"Calibri",sans-serif;
color:windowtext;}
span.PlainTextChar
{mso-style-name:"Plain Text Char";
mso-style-priority:99;
mso-style-link:"Plain Text";
font-family:"Calibri",sans-serif;}
.MsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri",sans-serif;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=3D"EN-US" link=3D"#0563C1" vlink=3D"#954F72">
<div class=3D"WordSection1">
<p class=3D"MsoPlainText"><repost since the previous message came as 64 =
encoded, apologies><o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Hello Howard,<o:p></o:p></p>
<p class=3D"MsoPlainText">we are not able to reproduce the issue consistent=
ly so test code is not available at this time, and I do believe this issue =
will be present in the latest code as well since Myk also reported the same=
.. Attaching analysis from our side,
hope it helps.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">The call stack what we have seen is,<o:p></o:p></=
p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> #0 0x0011b62e in mdb_cursor_pu=
t (mc=3D0xffe52d18, key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at mdb.=
c:6688<o:p></o:p></p>
<p class=3D"MsoPlainText"> #1 0x0011c8ec in mdb_put (txn=
=3D0xdc13f008, dbi=3D2, key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at =
mdb.c:8771<o:p></o:p></p>
<p class=3D"MsoPlainText"> #2 0x00b792b8 in LMDB::LMDBCon=
text::createSession (this=3D0x80ca418, sid=3D0x8297be4 "sidebf3708f0fd=
9fcb8e062529da47adf51402dfc4600000000+") at lmdbint.cc:460<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> #3 0x08053564 in updateLMDB (r=
equest=3D..., forward=3D@0xffe5315f) at sessionserver.cc:1075<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> #4 processRequestWithoutRespon=
se (request=3D..., forward=3D@0xffe5315f) at sessionserver.cc:1160<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> #5 0x08056a80 in processReques=
t (this=3D0x80b2ac0, fd=3D33) at sessionserver.cc:1189<o:p></o:p></p>
<p class=3D"MsoPlainText"> #6 readFromSock (this=3D0x80b2=
ac0, fd=3D33) at sessionserver.cc:1342<o:p></o:p></p>
<p class=3D"MsoPlainText"> #7 SockHandler::ioReady (this=
=3D0x80b2ac0, fd=3D33) at sessionserver.cc:1455<o:p></o:p></p>
<p class=3D"MsoPlainText"> #8 0x00ba2592 in runCoreDispat=
cher (default_t=3D<value optimized out>, flags=3D-1) at fds.cc:889<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> #9 0x00ba2ff7 in DSEvntFds::ru=
nDispatcher () at fds.cc:945<o:p></o:p></p>
<p class=3D"MsoPlainText"> #10 0x080559c6 in main () at s=
essionserver.cc:1739<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Here it is helpful to examine frames #0 and #1 in=
detail in relation to the relevant source code /libraries/liblmdb/mdb.c.<o=
:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Frame #1<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">#1 0x0011c8ec in mdb_put (txn=3D0xdc13f008,=
dbi=3D2, key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at mdb.c:8771<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> mc =3D=
{mc_next =3D 0x0, mc_backup =3D 0x0, mc_xcursor =3D 0x0, mc_txn =3D 0xdc13=
f008, mc_dbi =3D 2, mc_db =3D 0xdc13f088, mc_dbx =3D 0xe1215038, mc_dbflag =
=3D 0xdc1cf09a "\033", '\032' <repeats 51 times>, mc_snum =
=3D 0, mc_top =3D 0, mc_flags =3D 0,
mc_pg =3D {0x0, 0x80b2ac0, 0xffe52d68, 0x28afce, 0xdc13f008, 0x80ce9b0, 0x=
ffe52dc8, 0x4c5ff4, 0x2b, 0x80b2ac0, 0xffe52d98, 0x49209a, 0x2b, 0x4c5ff4, =
0x2121cb, 0x21576c, 0x8297d34, 0x3497af, 0x21576c, 0x21316a, 0x8297d34, 0x8=
0ac7b0, 0x1e, 0x46eed6, 0x2b, 0x0,
0x80ce9b0, 0x4c5ff4, 0x80ac7b0, 0x8297d34, 0xffe52df8, 0x46fb96}, mc_ki =
=3D {0, 2089, 51120, 2058, 30, 0, 16796, 17, 11760, 65509, 3, 0, 32040, 208=
9, 30, 0, 0, 0, 0, 0, 3, 0, 24564, 76, 51120, 2058, 10944, 2059, 11800, 655=
09, 64758, 70}} <--------<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; <o:p></o:p></p>
<p class=3D"MsoPlainText"> mx =3D=
{mx_cursor =3D {mc_next =3D 0x38, mc_backup =3D 0x3, mc_xcursor =3D 0x0, m=
c_txn =3D 0x0, mc_dbi =3D 0, mc_db =3D 0x28, mc_dbx =3D 0x0, mc_dbflag =3D =
0x0, mc_snum =3D 3, mc_top =3D 0, mc_flags =3D 17, mc_pg =3D {0x3a93d8, 0x1=
0, 0x0, 0x18, 0x3a93a0,
0x0, 0x3a93d0, 0x289abe, 0x3a93a0, 0xffe52d3f, 0xffe52c68, 0x28afce, 0xffe=
52dbc, 0xffe52db4, 0x3, 0x4c5ff4, 0x11, 0x36c99b, 0x6e, 0x77, 0x7c, 0x5b, 0=
x38, 0x289abe, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x3, 0x10}, mc_ki =3D {37848,=
58, 51611, 54, 110, 0, 119, 0, 124,
0, 91, 0, 58, 0, 39614, 40, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 2, 0, 18, 0, 1=
36, 0}}, mx_db =3D {md_pad =3D 3838936, md_flags =3D 51611, md_depth =3D 54=
, md_branch_pages =3D 110, md_leaf_pages =3D 119, md_overflow_pages =3D 124=
, md_entries =3D 91, md_root =3D 56}, mx_dbx =3D {md_name
=3D {mv_size =3D 6, mv_data =3D 0x0}, md_cmp =3D 0, md_dcmp =3D 0, md_rel =
=3D 0x40, md_relctx =3D 0x0}, mx_dbflag =3D 0 '\000'}<o:p></o:p></p>
<p class=3D"MsoPlainText"> rc =3D=
0 <o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">And source code for mdb_put() is from mdb.c<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">int<o:p></o:p></p>
<p class=3D"MsoPlainText">mdb_put(MDB_txn *txn, MDB_dbi dbi,<o:p></o:p></p>
<p class=3D"MsoPlainText"> MDB_val *key, MDB_val *data, u=
nsigned int flags) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_cursor mc;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_xcursor mx;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; int rc;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (!key || !data || !TXN_DBI_EXI=
ST(txn, dbi, DB_USRVALID))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return EINVA=
L;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (flags & ~(MDB_NOOVERWRITE=
|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return EINVA=
L;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (txn->mt_flags & (MDB_T=
XN_RDONLY|MDB_TXN_BLOCKED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return (txn-=
>mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mdb_cursor_init(&mc, txn, dbi=
, &mx); <-------- see source code below<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc.mc_next =3D txn->mt_cursors=
[dbi];<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; txn->mt_cursors[dbi] =3D &=
mc;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; rc =3D mdb_cursor_put(&mc, ke=
y, data, flags); <-------- see Frame #0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; txn->mt_cursors[dbi] =3D mc.mc=
_next;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; return rc;<o:p></o:p></p>
<p class=3D"MsoPlainText">}<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Source Code For mdb_cursor_init() From mdb.c<o:p>=
</o:p></p>
<p class=3D"MsoPlainText">/** Initialize a cursor for a given transaction a=
nd database. */ static void mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, M=
DB_dbi dbi, MDB_xcursor *mx) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_next =3D NULL;<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_backup =3D NULL;<o:p></=
o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_dbi =3D dbi;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_txn =3D txn;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_db =3D &txn->mt_=
dbs[dbi];<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_dbx =3D &txn->mt=
_dbxs[dbi];<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_dbflag =3D &txn->=
;mt_dbflags[dbi];<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_snum =3D 0; <-------=
- <o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_top =3D 0; <--------=
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_pg[0] =3D 0; <------=
-- <o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_ki[0] =3D 0;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_flags =3D 0;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; if (txn->mt_dbs[dbi].md_flags =
& MDB_DUPSORT) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_tassert(=
txn, mx !=3D NULL);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_xc=
ursor =3D mx;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_xcursor_=
init0(mc);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_xc=
ursor =3D NULL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (*mc->mc_dbflag & DB_ST=
ALE) { <-------- false *mc->mc_dbflag =3D 27, DB_STALE =3D 0x02 =
&nb=
sp; /**< Named-DB record is older than txnID */<o:p></=
o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_page_sea=
rch(mc, NULL, MDB_PS_ROOTONLY);
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText">}<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">From this we know that when mdb_cursor_put() is c=
alled, the following values remain assigned:<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_snum =3D 0; <--------<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_top =3D 0; <--------=
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; mc->mc_pg[0] =3D 0; <------=
-- <o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">and its noted these two values still have their i=
nitial values at the time of the segmentation fault.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">(gdb) fr 0<o:p></o:p></p>
<p class=3D"MsoPlainText">#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe52d18,=
key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at mdb.c:6688<o:p></o:p></=
p>
<p class=3D"MsoPlainText">6688 in mdb.c<o:p></o:p></p>
<p class=3D"MsoPlainText">(gdb) p mc->mc_top<o:p></o:p></p>
<p class=3D"MsoPlainText">$1 =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText">(gdb) p mc->mc_pg[mc->mc_top]<o:p></o:p></p=
>
<p class=3D"MsoPlainText">$19 =3D (MDB_page *) 0x0<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Let us consider how the path taken through mdb_cu=
rsor_put() could account for these null variable values which result in a s=
egmentation fault.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Frame #0<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">#0 0x0011b62e in mdb_cursor_put (mc=3D0xffe=
52d18, key=3D0xffe52e74, data=3D0xffe52e6c, flags=3D0) at mdb.c:6688 <--=
------ flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> env =
=3D 0x80ce9b0<o:p></o:p></p>
<p class=3D"MsoPlainText"> leaf =
=3D <value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> fp =3D=
<value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> mp =3D=
0x38<o:p></o:p></p>
<p class=3D"MsoPlainText"> sub_ro=
ot =3D 0x0 <o:p></o:p></p>
<p class=3D"MsoPlainText"> f=
p_flags =3D <value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> xdata =
=3D {mv_size =3D 3838880, mv_data =3D 0xdc1cf09a}<o:p></o:p></p>
<p class=3D"MsoPlainText"> rdata =
=3D 0xffe52e6c<o:p></o:p></p>
<p class=3D"MsoPlainText"> dkey =
=3D {mv_size =3D 0, mv_data =3D 0x3a93cc}<o:p></o:p></p>
<p class=3D"MsoPlainText"> olddat=
a =3D {mv_size =3D 22, mv_data =3D 0x36c820}<o:p></o:p></p>
<p class=3D"MsoPlainText"> dummy =
=3D {md_pad =3D 22, md_flags =3D 11128, md_depth =3D 65509, md_branch_pages=
=3D 16, md_leaf_pages =3D 1507329, md_overflow_pages =3D 0, md_entries =3D=
3838928, md_root =3D 3833844}<o:p></o:p></p>
<p class=3D"MsoPlainText"> do_sub=
=3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> insert=
_key =3D -30798 <-------- #define MDB_NOTFOUND &n=
bsp; (-30798)<o:p></o:p></p>
<p class=3D"MsoPlainText"> insert=
_data =3D -30798 <-------- #define MDB_NOTFOUND &=
nbsp; (-30798)<o:p></o:p></p>
<p class=3D"MsoPlainText"> mcount=
=3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> dcount=
=3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> nospil=
l =3D 0 <--------<o:p></o:p></p>
<p class=3D"MsoPlainText"> nsize =
=3D <value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> rc =3D=
0 <o:p></o:p></p>
<p class=3D"MsoPlainText"> r=
c2 =3D <value optimized out><o:p></o:p></p>
<p class=3D"MsoPlainText"> nflags=
=3D 0 <--------<o:p></o:p></p>
<p class=3D"MsoPlainText"> __func=
__ =3D "mdb_cursor_put" =
<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">We know that mc->mc_top and mc->mc_pg[0] we=
re initialized to 0 in mdb_cursor_init(). As my annotations of the source c=
ode below suggest, careful analysis reveals that the paths actually taken t=
hrough mdb_cursor_put() do not modify these
assignments.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">Excerpted Source Code For mdb_cursor_put() From m=
db.c<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">int<o:p></o:p></p>
<p class=3D"MsoPlainText">mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_=
val *data,<o:p></o:p></p>
<p class=3D"MsoPlainText"> unsigned int flags)<o:p></o:p>=
</p>
<p class=3D"MsoPlainText">{<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_env &n=
bsp;  =
; *env;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_node &=
nbsp; *leaf =3D NULL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_page &=
nbsp; *fp, *mp, *sub_root =3D NULL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; uint16_t &=
nbsp; fp_flags;<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_val &n=
bsp;  =
; x=
data, *rdata, dkey, olddata;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; MDB_db dummy;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; int do_sub =3D 0, insert_key, ins=
ert_data;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; unsigned int mcount =3D 0, dcount=
=3D 0, nospill;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; size_t nsize;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; int rc, rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; unsigned int nflags;<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; DKBUF;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (mc =3D=3D NULL || key =3D=3D =
NULL)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return EINVA=
L;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; env =3D mc->mc_txn->mt_env;=
<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; /* Check this first so counter wi=
ll always be zero on any<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; * early failures.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (flags & MDB_MULTIPLE) {<o=
:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; dcount =3D d=
ata[1].mv_size;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; data[1].mv_s=
ize =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (!F_ISSET=
(mc->mc_db->md_flags, MDB_DUPFIXED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_INCOMPATIBLE;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nospill =3D flags & MDB_NOSPI=
LL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; flags &=3D ~MDB_NOSPILL;<o:p>=
</o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (mc->mc_txn->mt_flags &a=
mp; (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return (mc-&=
gt;mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;<o:p></=
o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (key->mv_size-1 >=3D ENV=
_MAXKEY(env))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return MDB_B=
AD_VALSIZE;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">#if SIZE_MAX > MAXDATASIZE<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (data->mv_size > ((mc-&g=
t;mc_db->md_flags & MDB_DUPSORT) ? ENV_MAXKEY(env) : MAXDATASIZE))<o=
:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return MDB_B=
AD_VALSIZE;<o:p></o:p></p>
<p class=3D"MsoPlainText">#else<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if ((mc->mc_db->md_flags &a=
mp; MDB_DUPSORT) && data->mv_size > ENV_MAXKEY(env))<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; return MDB_B=
AD_VALSIZE;<o:p></o:p></p>
<p class=3D"MsoPlainText">#endif<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; DPRINTF(("=3D=3D> put db =
%d key [%s], size %"Z"u, data size %"Z"u",<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; DDBI(mc), DK=
EY(key), key ? key->mv_size : 0, data->mv_size));<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; dkey.mv_size =3D 0;<o:p></o:p></p=
>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (flags =3D=3D MDB_CURRENT) { &=
lt;-------- false flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (!(mc->=
;mc_flags & C_INITIALIZED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; =
&nb=
sp; return EINVAL;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; rc =3D MDB_S=
UCCESS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else if (mc->mc_db->md_ro=
ot =3D=3D P_INVALID) { <-------- false, mc->mc_db->md_root =3D 68<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* new datab=
ase, cursor has nothing to point to */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_sn=
um =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_to=
p =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_fl=
ags &=3D ~C_INITIALIZED;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; rc =3D MDB_N=
O_ROOT; <o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else { <-------- executed<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; int exact =
=3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; MDB_val d2;<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (flags &a=
mp; MDB_APPEND) { <-------- false flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; MDB_val k2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc =3D mdb_cursor_last(mc, &k2, &d2);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (rc =3D=3D 0) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; rc =3D mc->mc_dbx->md_cmp(key, &k2)=
;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (rc > 0) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc =3D MDB_NOTFOUND;<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mc->mc_ki[mc->mc_t=
op]++;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* new key is <=3D la=
st key */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc =3D MDB_KEYEXIST;<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } else {<=
-------- executed<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc =3D mdb_cursor_set(mc, key, &d2, MDB_SET, &exact); <=
-------- returns -30798 which is MDB_NOTFOUND<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<-------=
- executed<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((flags &=
amp; MDB_NOOVERWRITE) && rc =3D=3D 0) { <-------- false flags =
=3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; DPRINTF(("duplicate key [%s]", DKEY(key)));<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; *data =3D d2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_KEYEXIST;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (rc &=
& rc !=3D MDB_NOTFOUND) <-------- false rc =3D MDB_NOTFOUND<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<-------- executed<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (mc->mc_flags & C_DEL)<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_fl=
ags ^=3D C_DEL;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; /* Cursor is positioned, check fo=
r room in the dirty list */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (!nospill) { <-------- true=
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (flags &a=
mp; MDB_MULTIPLE) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rdata =3D &xdata;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_size =3D data->mv_size * dcount;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } else {<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rdata =3D data; <-------- executed<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((rc2 =3D=
mdb_page_spill(mc, key, rdata))) <-------- returned 0 or would have ret=
urned<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; }<-------- executed<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (rc =3D=3D MDB_NO_ROOT) { <=
-------- false <o:p>
</o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; MDB_page *np=
;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* new datab=
ase, write a root leaf page */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; DPUTS("=
allocating new root leaf page");<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((rc2 =3D=
mdb_page_new(mc, P_LEAF, 1, &np))) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_cursor_p=
ush(mc, np);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_db=
->md_root =3D np->mp_pgno;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_db=
->md_depth++;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; *mc->mc_d=
bflag |=3D DB_DIRTY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((mc->=
mc_db->md_flags & (MDB_DUPSORT|MDB_DUPFIXED))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; =3D=3D MDB_DUPFIXED)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; np->mp_flags |=3D P_LEAF2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mc->mc_fl=
ags |=3D C_INITIALIZED;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* make sure=
all cursor pages are writable */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; rc2 =3D mdb_=
cursor_touch(mc); <-------- is this called and returns 0 because it does=
not return<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (rc2)<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } <-------- executed<o:p></o:p=
></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; insert_key =3D insert_data =3D rc=
; <-------- rc =3D -30798 or MDB_NOTFOUND!<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (insert_key) { <-------- tr=
ue<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* The key d=
oes not exist */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; DPRINTF((&qu=
ot;inserting key at index %i", mc->mc_ki[mc->mc_top]));<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((mc->=
mc_db->md_flags & MDB_DUPSORT) &&<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; LEAFSIZE(key, data) > env->me_nodemax) <-------- false si=
nce mc->mc_db->md_flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; {<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Too big for a node, insert in sub-DB. Set up an empty<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * "old sub-page" for prep_subDB to expand to a full page=
.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp_flags =3D P_LEAF|P_DIRTY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp =3D env->me_pbuf;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_pad =3D data->mv_size; /* used if MDB_DUPFIXED */<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_lower =3D fp->mp_upper =3D (PAGEHDRSZ-PAGEBASE);<o:p>=
</o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; olddata.mv_size =3D PAGEHDRSZ;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto prep_subDB;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } <------=
-- this was not executed, and the very long external else contingency below=
should be skipped!<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* there's o=
nly a key anyway, so this is a no-op */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (IS_LEAF2=
(mc->mc_pg[mc->mc_top])) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; char *ptr;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; unsigned int ksize =3D mc->mc_db->md_pad;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (key->mv_size !=3D ksize)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; return MDB_BAD_VALSIZE;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; ptr =3D LEAF2KEY(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->=
mc_top], ksize);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(ptr, key->mv_data, ksize);<o:p></o:p></p>
<p class=3D"MsoPlainText">fix_parent:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* if overwriting slot 0 of leaf, need to<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * update branch key if there is a parent page<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (mc->mc_top && !mc->mc_ki[mc->mc_top]) {<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; unsigned short dtop =3D 1;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mc->mc_top--;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* slot 0 is always an empty key, find real s=
lot */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; while (mc->mc_top && !mc->mc_ki=
[mc->mc_top]) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mc->mc_top--;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dtop++;<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (mc->mc_ki[mc->mc_top])<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc2 =3D mdb_update_key(m=
c, key);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; else<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc2 =3D MDB_SUCCESS;<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mc->mc_top +=3D dtop;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (rc2)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc2;<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_SUCCESS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">more:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; leaf =3D NOD=
EPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; olddata.mv_s=
ize =3D NODEDSZ(leaf);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; olddata.mv_d=
ata =3D NODEDATA(leaf);<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* DB has du=
ps? */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (F_ISSET(=
mc->mc_db->md_flags, MDB_DUPSORT)) {
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Prepare (sub-)page/sub-DB to accept the new item,<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * if needed. fp: old sub-page or a header faking<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * it. mp: new (sub-)page. offset: growth in page<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * size. xdata: node data with new page or DB.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; unsigned &nbs=
p; i, offset =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mp =3D fp =3D xdata.mv_data =3D env->me_pbuf;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mp->mp_pgno =3D mc->mc_pg[mc->mc_top]->mp_pgno;<o:p></=
o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Was a single item before, must convert now */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; MDB_cmp_func *dcmp;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Just overwrite the current item */<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (flags =3D=3D MDB_CURRENT)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto current;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dcmp =3D mc->mc_dbx->md_dcmp;<o:p></o:p=
></p>
<p class=3D"MsoPlainText">#if UINT_MAX < SIZE_MAX<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (dcmp =3D=3D mdb_cmp_int && olddat=
a.mv_size =3D=3D sizeof(size_t))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dcmp =3D mdb_cmp_clong;<=
o:p></o:p></p>
<p class=3D"MsoPlainText">#endif<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* does data match? */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (!dcmp(data, &olddata)) {<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (flags & (MDB_NOD=
UPDATA|MDB_APPENDDUP))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; ret=
urn MDB_KEYEXIST;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* overwrite it */<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto current;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Back up original data item */<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dkey.mv_size =3D olddata.mv_size;<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dkey.mv_data =3D memcpy(fp+1, olddata.mv_=
data, olddata.mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Make sub-page header for the dup items, wi=
th dummy body */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp->mp_flags =3D P_LEAF|P_DIRTY|P_SUBP;<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp->mp_lower =3D (PAGEHDRSZ-PAGEBASE);<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; xdata.mv_size =3D PAGEHDRSZ + dkey.mv_siz=
e + data->mv_size;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; =
&nb=
sp; =
if (mc->mc_db->md_flags & MDB_DUPFIXED) =
{<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_flags |=3D P_L=
EAF2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_pad =3D data-&=
gt;mv_size;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_size +=3D 2=
* data->mv_size; /* leave space for 2 mor=
e */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_size +=3D 2=
* (sizeof(indx_t) + NODESIZE) +<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; (dk=
ey.mv_size & 1) + (data->mv_size & 1);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp->mp_upper =3D xdata.mv_size - PAGEBASE;=
<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; olddata.mv_size =3D xdata.mv_size; /* pretend=
olddata is fp */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; } else if (leaf->mn_flags & F_SUBDATA) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Data is on sub-DB, just store it */<o:p></=
o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; flags |=3D F_DUPDATA|F_SUBDATA;<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; goto put_sub;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* Data is on sub-page */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp =3D olddata.mv_data;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; switch (flags) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; default:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!(mc->mc_db->m=
d_flags & MDB_DUPFIXED)) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; off=
set =3D EVEN(NODESIZE + sizeof(indx_t) +<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; data->mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; bre=
ak;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; offset =3D fp->mp_pad=
;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (SIZELEFT(fp) < of=
fset) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; off=
set *=3D 4; /* space for 4 more */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; bre=
ak;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* FALLTHRU: Big enough =
MDB_DUPFIXED sub-page */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; case MDB_CURRENT:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_flags |=3D P_D=
IRTY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; COPY_PGNO(fp->mp_pgno=
, mp->mp_pgno);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mc->mc_xcursor->mx=
_cursor.mc_pg[0] =3D fp;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; flags |=3D F_DUPDATA;<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto put_sub;<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; xdata.mv_size =3D olddata.mv_size + offse=
t;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp_flags =3D fp->mp_flags;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (NODESIZE + NODEKSZ(leaf) + xdata.mv_size > env->=
me_nodemax) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Too big for a sub-pag=
e, convert to sub-DB */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp_flags &=3D ~P_SUB=
P;<o:p></o:p></p>
<p class=3D"MsoPlainText">prep_subDB:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (mc->mc_db->md_=
flags & MDB_DUPFIXED) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; fp_=
flags |=3D P_LEAF2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dum=
my.md_pad =3D fp->mp_pad;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dum=
my.md_flags =3D MDB_DUPFIXED;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if =
(mc->mc_db->md_flags & MDB_INTEGERDUP)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dummy.md_flags |=3D MDB_INTEGERKEY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dum=
my.md_pad =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; dum=
my.md_flags =3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_depth =3D 1;<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_branch_pages =
=3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; =
&nb=
sp; =
&nb=
sp; dummy.md_leaf_pages =3D 1;<o:=
p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_overflow_pages =
=3D 0;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_entries =3D NUM=
KEYS(fp);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_size =3D sizeof=
(MDB_db);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; xdata.mv_data =3D &d=
ummy;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if ((rc =3D mdb_page_all=
oc(mc, 1, &mp)))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; ret=
urn rc;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; offset =3D env->me_ps=
ize - olddata.mv_size;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; flags |=3D F_DUPDATA|F_S=
UBDATA;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; dummy.md_root =3D mp->=
;mp_pgno;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; sub_root =3D mp;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (mp !=3D fp) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp->mp_flags =3D fp_flags | P_DIRTY;<o:p><=
/o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp->mp_pad =3D fp->mp_pad;<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp->mp_lower =3D fp->mp_lower;<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp->mp_upper =3D fp->mp_upper + off=
set;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (fp_flags & P_LEAF2) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(METADATA(mp), MET=
ADATA(fp), NUMKEYS(fp) * fp->mp_pad);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy((char *)mp + =
mp->mp_upper + PAGEBASE, (char *)fp + fp->mp_upper + PAGE=
BASE,<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; old=
data.mv_size - fp->mp_upper - PAGEBASE);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; for (i=3D0; i<NUMKEYS=
(fp); i++)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mp-=
>mp_ptrs[i] =3D fp->mp_ptrs[i] + offset;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rdata =3D &xdata;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; flags |=3D F_DUPDATA;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; do_sub =3D 1;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!insert_key)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mdb_node_del(mc, 0);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto new_sub;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText">current:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* LMDB pass=
es F_SUBDATA in 'flags' to write a DB record */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((leaf-&g=
t;mn_flags ^ flags) & F_SUBDATA)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_INCOMPATIBLE;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* overflow =
page overwrites need special handling */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if (F_ISSET(=
leaf->mn_flags, F_BIGDATA)) { <-------- is this taken?<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; MDB_page *omp;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; pgno_t pg;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; int level, ovpages, dpages =3D OVPAGES(data->mv_size, env->m=
e_psize);<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(&pg, olddata.mv_data, sizeof(pg));<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if ((rc2 =3D mdb_page_get(mc->mc_txn, pg, &omp, &level)=
) !=3D 0)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; ovpages =3D omp->mp_pages;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Is the ov page large enough? */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (ovpages >=3D dpages) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!(omp->mp_flags & P_DIRTY) &&<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; (level || (env->me_flags & MDB_=
WRITEMAP)))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; rc =3D mdb_page_unspill(mc->mc_txn, omp, &=
amp;omp); <-------- is this taken?<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (rc)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return rc;<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; level =3D 0; &nb=
sp; =
/* dirty=
in this txn or clean */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Is it dirty? */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (omp->mp_flags & P_DIRTY) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* yes, overwrite it. Note in this case we do=
n't<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; * bother to try shrinking the page if the new=
data<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; * is smaller than the overflow threshold.<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (level > 1) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* It is writable only i=
n a parent txn */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; size_t sz =3D (size_t) e=
nv->me_psize * ovpages, off;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; MDB_page *np =3D mdb_pag=
e_malloc(mc->mc_txn, ovpages);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; MDB_ID2 id2;<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!np)<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; ret=
urn ENOMEM;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; id2.mid =3D pg;<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; id2.mptr =3D np;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Note - this page is a=
lready counted in parent's dirty_room */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; rc2 =3D mdb_mid2l_insert=
(mc->mc_txn->mt_u.dirty_list, &id2);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; mdb_cassert(mc, rc2 =3D=
=3D 0);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (!(flags & MDB_RE=
SERVE)) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; /* =
Copy end of page, adjusting alignment so<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; * c=
ompiler may copy words instead of bytes.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; */<=
o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; off=
=3D (PAGEHDRSZ + data->mv_size) & -sizeof(size_t);<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; mem=
cpy((size_t *)((char *)np + off),<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; (size_t *)((char *)omp + off), sz - off);<o:p></o:p><=
/p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; sz =
=3D PAGEHDRSZ;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(np, omp, sz); /* =
Copy beginning of page */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; omp =3D np;<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; SETDSZ(leaf, data->mv_size);<o:p></o:p></p=
>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; if (F_ISSET(flags, MDB_RESERVE))<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; data->mv_data =3D MET=
ADATA(omp);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; else<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; memcpy(METADATA(omp), da=
ta->mv_data, data->mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; return MDB_SUCCESS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if ((rc2 =3D mdb_ovpage_free(mc, omp)) !=3D MDB_SUCCESS)<o:p></o:p=
></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; return rc2;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } else if (d=
ata->mv_size =3D=3D olddata.mv_size) {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* same size, just replace it. Note that we could<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * also reuse this node if the new data is smaller,<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * but instead we opt to shrink the node in that case.<o:p></o:p></=
p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; if (F_ISSET(flags, MDB_RESERVE))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; data->mv_data =3D olddata.mv_data;<o:p></o=
:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; else if (!(mc->mc_flags & C_SUB))<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; memcpy(olddata.mv_data, data->mv_data, dat=
a->mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; else {<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; memcpy(NODEKEY(leaf), key->mv_data, key-&g=
t;mv_size);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; &=
nbsp; goto fix_parent;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; }<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; return MDB_SUCCESS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; }<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; mdb_node_del=
(mc, 0);<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } <-------- This entire else c=
ontingency was likely skipped!!<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; rdata =3D data;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">new_sub:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nflags =3D flags & NODE_ADD_F=
LAGS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nsize =3D IS_LEAF2(mc->mc_pg[m=
c->mc_top]) ? key->mv_size : mdb_leaf_size(env, key, rdata); <----=
---- SEGV<o:p></o:p></p>
<p class=3D"MsoPlainText">... &nbs=
p; <o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">This may be an identifiable bug in mdb_cursor_put=
() as It does not safely handle the case when the noted call to mdb_cursor_=
set() returns MDB_NOTFOUND (-30798)!<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">It explicitly fails to preemptively exit by retur=
ning an error in this case.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">The value of -30798 is in turn assigned to insert=
_key, which is therefore non-null in the condition of the subsequent if sta=
tement.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; insert_key =3D insert_data =3D rc=
; <-------- insert_key =3D -30798 or MDB_NOTFOUND!<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; if (insert_key) { <-------- tr=
ue<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; /* The key d=
oes not exist */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; DPRINTF((&qu=
ot;inserting key at index %i", mc->mc_ki[mc->mc_top]));<o:p></o:=
p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; if ((mc->=
mc_db->md_flags & MDB_DUPSORT) &&<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; LEAFSIZE(key, data) > env->me_nodemax) <-------- false si=
nce mc->mc_db->md_flags =3D 0<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; {<o:p></o:p>=
</p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; /* Too big for a node, insert in sub-DB. Set up an empty<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; * "old sub-page" for prep_subDB to expand to a full page=
.<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; */<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp_flags =3D P_LEAF|P_DIRTY;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp =3D env->me_pbuf;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_pad =3D data->mv_size; /* used if MDB_DUPFIXED */<o:p=
></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; fp->mp_lower =3D fp->mp_upper =3D (PAGEHDRSZ-PAGEBASE);<o:p>=
</o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; olddata.mv_size =3D PAGEHDRSZ;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; &=
nbsp; &nbs=
p; goto prep_subDB;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; &nbs=
p; } <------=
-- this was not executed, and the very long else contingency below is skipp=
ed!<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; } else {<o:p></o:p></p>
<p class=3D"MsoPlainText">Since mc->mc_db->md_flags =3D 0, the contin=
gency in the embedded if statement fails.<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">The segmentation fault occurs due to the call of =
IS_LEAF2 on the null pointer mc->mc_pg[0].<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; rdata =3D data;<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoPlainText">new_sub:<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nflags =3D flags & NODE_ADD_F=
LAGS;<o:p></o:p></p>
<p class=3D"MsoPlainText"> &=
nbsp; nsize =3D IS_LEAF2(mc->mc_pg[m=
c->mc_top]) ? key->mv_size : mdb_leaf_size(env, key, rdata); <----=
---- SEGV<o:p></o:p></p>
<p class=3D"MsoPlainText"><o:p> </o:p></p>
<p class=3D"MsoNormal">Regards,<o:p></o:p></p>
<p class=3D"MsoNormal">Robins.<o:p></o:p></p>
</div>
</body>
</html>
--_000_MN2PR06MB55017A7261FA27380778753BAFEA0MN2PR06MB5501namp_--
4 years, 5 months
Re: (ITS#9037) observing crash in mdb_cursor_put()
by hyc@symas.com
Robins George wrote:
> Hello Howard,
> we are not able to reproduce the issue consistently so test code is not available at this time, and I do believe this issue will be present in the latest code as well since Myk also reported the same.. Attaching analysis from our side, hope it helps.
Thanks. Notes below...
>
> The call stack what we have seen is,
>
> #0 0x0011b62e in mdb_cursor_put (mc=0xffe52d18, key=0xffe52e74, data=0xffe52e6c, flags=0) at mdb.c:6688
> #1 0x0011c8ec in mdb_put (txn=0xdc13f008, dbi=2, key=0xffe52e74, data=0xffe52e6c, flags=0) at mdb.c:8771
> #2 0x00b792b8 in LMDB::LMDBContext::createSession (this=0x80ca418, sid=0x8297be4 "sidebf3708f0fd9fcb8e062529da47adf51402dfc4600000000+") at lmdbint.cc:460
> #3 0x08053564 in updateLMDB (request=..., forward=@0xffe5315f) at sessionserver.cc:1075
> #4 processRequestWithoutResponse (request=..., forward=@0xffe5315f) at sessionserver.cc:1160
> #5 0x08056a80 in processRequest (this=0x80b2ac0, fd=33) at sessionserver.cc:1189
> #6 readFromSock (this=0x80b2ac0, fd=33) at sessionserver.cc:1342
> #7 SockHandler::ioReady (this=0x80b2ac0, fd=33) at sessionserver.cc:1455
> #8 0x00ba2592 in runCoreDispatcher (default_t=<value optimized out>, flags=-1) at fds.cc:889
> #9 0x00ba2ff7 in DSEvntFds::runDispatcher () at fds.cc:945
> #10 0x080559c6 in main () at sessionserver.cc:1739
>
> Here it is helpful to examine frames #0 and #1 in detail in relation to the relevant source code /libraries/liblmdb/mdb.c.
>
> Frame #1
>
> #1 0x0011c8ec in mdb_put (txn=0xdc13f008, dbi=2, key=0xffe52e74, data=0xffe52e6c, flags=0) at mdb.c:8771
> mc = {mc_next = 0x0, mc_backup = 0x0, mc_xcursor = 0x0, mc_txn = 0xdc13f008, mc_dbi = 2, mc_db = 0xdc13f088, mc_dbx = 0xe1215038, mc_dbflag = 0xdc1cf09a "\033", '\032' <repeats 51 times>, mc_snum = 0, mc_top = 0, mc_flags = 0, mc_pg = {0x0, 0x80b2ac0, 0xffe52d68, 0x28afce, 0xdc13f008, 0x80ce9b0, 0xffe52dc8, 0x4c5ff4, 0x2b, 0x80b2ac0, 0xffe52d98, 0x49209a, 0x2b, 0x4c5ff4, 0x2121cb, 0x21576c, 0x8297d34, 0x3497af, 0x21576c, 0x21316a, 0x8297d34, 0x80ac7b0, 0x1e, 0x46eed6, 0x2b, 0x0, 0x80ce9b0, 0x4c5ff4, 0x80ac7b0, 0x8297d34, 0xffe52df8, 0x46fb96}, mc_ki = {0, 2089, 51120, 2058, 30, 0, 16796, 17, 11760, 65509, 3, 0, 32040, 2089, 30, 0, 0, 0, 0, 0, 3, 0, 24564, 76, 51120, 2058, 10944, 2059, 11800, 65509, 64758, 70}} <--------
>
> mx = {mx_cursor = {mc_next = 0x38, mc_backup = 0x3, mc_xcursor = 0x0, mc_txn = 0x0, mc_dbi = 0, mc_db = 0x28, mc_dbx = 0x0, mc_dbflag = 0x0, mc_snum = 3, mc_top = 0, mc_flags = 17, mc_pg = {0x3a93d8, 0x10, 0x0, 0x18, 0x3a93a0, 0x0, 0x3a93d0, 0x289abe, 0x3a93a0, 0xffe52d3f, 0xffe52c68, 0x28afce, 0xffe52dbc, 0xffe52db4, 0x3, 0x4c5ff4, 0x11, 0x36c99b, 0x6e, 0x77, 0x7c, 0x5b, 0x38, 0x289abe, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x3, 0x10}, mc_ki = {37848, 58, 51611, 54, 110, 0, 119, 0, 124, 0, 91, 0, 58, 0, 39614, 40, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 2, 0, 18, 0, 136, 0}}, mx_db = {md_pad = 3838936, md_flags = 51611, md_depth = 54, md_branch_pages = 110, md_leaf_pages = 119, md_overflow_pages = 124, md_entries = 91, md_root = 56}, mx_dbx = {md_name = {mv_size = 6, mv_data = 0x0}, md_cmp = 0, md_dcmp = 0, md_rel = 0x40, md_relctx = 0x0}, mx_dbflag = 0 '\000'}
> rc = 0
>
> And source code for mdb_put() is from mdb.c
>
> int
> mdb_put(MDB_txn *txn, MDB_dbi dbi,
> MDB_val *key, MDB_val *data, unsigned int flags)
> {
> MDB_cursor mc;
> MDB_xcursor mx;
> int rc;
>
> if (!key || !data || !TXN_DBI_EXIST(txn, dbi, DB_USRVALID))
> return EINVAL;
>
> if (flags & ~(MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP))
> return EINVAL;
>
> if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_BLOCKED))
> return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
>
> mdb_cursor_init(&mc, txn, dbi, &mx); <-------- see source code below
> mc.mc_next = txn->mt_cursors[dbi];
> txn->mt_cursors[dbi] = &mc;
> rc = mdb_cursor_put(&mc, key, data, flags); <-------- see Frame #0
> txn->mt_cursors[dbi] = mc.mc_next;
> return rc;
> }
>
>
> Source Code For mdb_cursor_init() From mdb.c
> /** Initialize a cursor for a given transaction and database. */
> static void
> mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
> {
> mc->mc_next = NULL;
> mc->mc_backup = NULL;
> mc->mc_dbi = dbi;
> mc->mc_txn = txn;
> mc->mc_db = &txn->mt_dbs[dbi];
> mc->mc_dbx = &txn->mt_dbxs[dbi];
> mc->mc_dbflag = &txn->mt_dbflags[dbi];
> mc->mc_snum = 0; <--------
> mc->mc_top = 0; <--------
> mc->mc_pg[0] = 0; <--------
> mc->mc_ki[0] = 0;
> mc->mc_flags = 0;
> if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
> mdb_tassert(txn, mx != NULL);
> mc->mc_xcursor = mx;
> mdb_xcursor_init0(mc);
> } else {
> mc->mc_xcursor = NULL;
> }
> if (*mc->mc_dbflag & DB_STALE) { <-------- false *mc->mc_dbflag = 27, DB_STALE = 0x02 /**< Named-DB record is older than txnID */
27 = 0x1b, so DB_STALE is true. mdb_page_search ought to have been invoked to set the root of the cursor.
> mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
> }
> }
>
> From this we know that when mdb_cursor_put() is called, the following values remain assigned:
>
> mc->mc_snum = 0; <--------
> mc->mc_top = 0; <--------
> mc->mc_pg[0] = 0; <--------
>
> and its noted these two values still have their initial values at the time of the segmentation fault.
There is no issue with mdb_cursor_put then. The question is why didn't mdb_page_search find the DBI's root node?
--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/
4 years, 5 months