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> * </ul>
*/ */
int mdb_env_open(MDB_env *env, const char *path, unsigned flags, mode_t mode); 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. /** @brief Copy an LMDB environment to the specified path.
* *
* This function may be used to make a backup of an existing environment. * 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; struct flock lock_info;
int rc = 0; int rc = 0;
env->me_txns->mti_txnid = meta->mm_txnid;
/* The shared lock replaces the existing lock */ /* The shared lock replaces the existing lock */
memset((void *)&lock_info, 0, sizeof(lock_info)); memset((void *)&lock_info, 0, sizeof(lock_info));
lock_info.l_type = F_RDLCK; lock_info.l_type = F_RDLCK;
@ -4600,6 +4598,12 @@ fail:
int ESECT int ESECT
mdb_env_open(MDB_env *env, const char *path, unsigned flags, mode_t mode) 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; int oflags, rc, len, excl = -1;
char *lpath, *dpath; 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) { if ((rc = mdb_env_open2(env, &meta)) == MDB_SUCCESS) {
mdb_debug("opened dbenv %p", (void *) env); mdb_debug("opened dbenv %p", (void *) env);
if (excl > 0) { if (excl > 0) {
rc = mdb_env_share_locks(env, &excl, &meta); env->me_txns->mti_txnid = meta.mm_txnid;
if (rc) if (exclusive == NULL || *exclusive < 2) {
goto leave; /* 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)) { if (!(flags & MDB_RDONLY)) {
MDB_txn *txn; MDB_txn *txn;

View File

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