lmdb: added mdb_env_open_ex() and exclusive/monopoly mode for mdb_chk.

Change-Id: I867e7f17924ffecb744440e95db96c0a7411d6ef
This commit is contained in:
Leo Yuriev 2015-08-07 20:05:10 +03:00
parent 59b74d5df0
commit 96d69e3fa1
3 changed files with 42 additions and 21 deletions

2
lmdb.h
View File

@ -616,7 +616,7 @@ int mdb_env_create(MDB_env **env);
* </ul>
*/
int mdb_env_open(MDB_env *env, const char *path, unsigned flags, mode_t mode);
int mdb_env_open_ex(MDB_env *env, const char *path, unsigned flags, mode_t mode, int *exclusive);
/** @brief Copy an LMDB environment to the specified path.
*
* This function may be used to make a backup of an existing environment.

22
mdb.c
View File

@ -4345,8 +4345,6 @@ mdb_env_share_locks(MDB_env *env, int *excl, MDB_meta *meta)
struct flock lock_info;
int rc = 0;
env->me_txns->mti_txnid = meta->mm_txnid;
/* The shared lock replaces the existing lock */
memset((void *)&lock_info, 0, sizeof(lock_info));
lock_info.l_type = F_RDLCK;
@ -4600,6 +4598,12 @@ fail:
int ESECT
mdb_env_open(MDB_env *env, const char *path, unsigned flags, mode_t mode)
{
return mdb_env_open_ex(env, path, flags, mode, NULL);
}
int ESECT
mdb_env_open_ex(MDB_env *env, const char *path, unsigned flags, mode_t mode, int *exclusive)
{
int oflags, rc, len, excl = -1;
char *lpath, *dpath;
@ -4678,9 +4682,17 @@ mdb_env_open(MDB_env *env, const char *path, unsigned flags, mode_t mode)
if ((rc = mdb_env_open2(env, &meta)) == MDB_SUCCESS) {
mdb_debug("opened dbenv %p", (void *) env);
if (excl > 0) {
rc = mdb_env_share_locks(env, &excl, &meta);
if (rc)
goto leave;
env->me_txns->mti_txnid = meta.mm_txnid;
if (exclusive == NULL || *exclusive < 2) {
/* LY: downgrade lock only if exclusive access not requested.
* in case exclusive==1, just leave value as is. */
rc = mdb_env_share_locks(env, &excl, &meta);
if (rc)
goto leave;
}
} else if (exclusive) {
/* LY: just indicate that is not an exclusive access. */
*exclusive = 0;
}
if (!(flags & MDB_RDONLY)) {
MDB_txn *txn;

View File

@ -61,6 +61,7 @@ size_t dbi_payload_bytes[MAX_DBI];
short *pagemap;
size_t pgcount;
size_t total_payload_bytes, total_unused_bytes;
int exclusive = 2;
MDB_env *env;
MDB_txn *txn, *locktxn;
@ -458,7 +459,8 @@ static void usage(char *prog)
" -v\tmore verbose, could be used multiple times\n"
" -n\tNOSUBDIR mode for open\n"
" -q\tbe quiet\n"
" -w\tstart write-txn to lock db\n", prog);
" -w\tstart write-txn to lock db\n"
" -c\tforce cooperative mode (don't try exclusive)\n", prog);
exit(EXIT_FAILURE);
}
@ -474,7 +476,7 @@ const char* meta_synctype(size_t sign) {
}
int meta_lt(size_t txn1, size_t sign1, size_t txn2, size_t sign2) {
return ((sign1 > 1) == (sign2 > 1)) ? txn1 < txn2 : sign2 > 1;
return ((sign1 > 1) == (sign2 > 1)) ? txn1 < txn2 : txn2 && sign2 > 1;
}
int main(int argc, char *argv[])
@ -491,7 +493,7 @@ int main(int argc, char *argv[])
usage(prog);
}
while ((i = getopt(argc, argv, "Vvqnw")) != EOF) {
while ((i = getopt(argc, argv, "Vvqnwc")) != EOF) {
switch(i) {
case 'V':
printf("%s\n", MDB_VERSION_STRING);
@ -509,6 +511,9 @@ int main(int argc, char *argv[])
case 'w':
envflags &= ~MDB_RDONLY;
break;
case 'c':
exclusive = 0;
break;
default:
usage(prog);
}
@ -545,11 +550,13 @@ int main(int argc, char *argv[])
mdb_env_set_maxdbs(env, 3);
rc = mdb_env_open(env, envname, envflags, 0664);
rc = mdb_env_open_ex(env, envname, envflags, 0664, &exclusive);
if (rc) {
error("mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
goto bailout;
}
if (verbose)
print(" - %s mode\n", exclusive ? "monopolistic" : "cooperative");
rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
if (rc) {
@ -619,18 +626,20 @@ int main(int argc, char *argv[])
info.me_meta2_txnid, info.me_last_txnid);
}
if (! meta_lt(info.me_meta1_txnid, info.me_meta1_sign,
info.me_meta2_txnid, info.me_meta2_sign)
&& info.me_meta1_txnid != info.me_last_txnid) {
print(" - meta-1 txn-id mismatch\n");
++problems_meta;
}
if (exclusive > 1) {
if (! meta_lt(info.me_meta1_txnid, info.me_meta1_sign,
info.me_meta2_txnid, info.me_meta2_sign)
&& info.me_meta1_txnid != info.me_last_txnid) {
print(" - meta-1 txn-id mismatch\n");
++problems_meta;
}
if (! meta_lt(info.me_meta2_txnid, info.me_meta2_sign,
info.me_meta1_txnid, info.me_meta1_sign)
&& info.me_meta2_txnid != info.me_last_txnid) {
print(" - meta-2 txn-id mismatch\n");
++problems_meta;
if (! meta_lt(info.me_meta2_txnid, info.me_meta2_sign,
info.me_meta1_txnid, info.me_meta1_sign)
&& info.me_meta2_txnid != info.me_last_txnid) {
print(" - meta-2 txn-id mismatch\n");
++problems_meta;
}
}
print("Walking b-tree...\n");