Fix last commit.

Add flag MDB_ENV_ACTIVE instead of using the state of me_lfd.
Require MDB_RDONLY for MDB_ROFS.  Swap reader/writer mutex lock.
vmware
Hallvard Furuseth 12 years ago
parent e40713b631
commit 462d9dfd10
  1. 46
      libraries/libmdb/mdb.c

@ -915,6 +915,8 @@ struct MDB_env {
#define MDB_FATAL_ERROR 0x80000000U #define MDB_FATAL_ERROR 0x80000000U
/** Read-only Filesystem. Allow read access, no locking. */ /** Read-only Filesystem. Allow read access, no locking. */
#define MDB_ROFS 0x40000000U #define MDB_ROFS 0x40000000U
/** Some fields are initialized. */
#define MDB_ENV_ACTIVE 0x20000000U
uint32_t me_flags; /**< @ref mdb_env */ uint32_t me_flags; /**< @ref mdb_env */
unsigned int me_psize; /**< size of a page, from #GET_PAGESIZE */ unsigned int me_psize; /**< size of a page, from #GET_PAGESIZE */
unsigned int me_maxreaders; /**< size of the reader table */ unsigned int me_maxreaders; /**< size of the reader table */
@ -2583,14 +2585,13 @@ mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers)
/** Further setup required for opening an MDB environment /** Further setup required for opening an MDB environment
*/ */
static int static int
mdb_env_open2(MDB_env *env, unsigned int flags) mdb_env_open2(MDB_env *env)
{ {
unsigned int flags = env->me_flags;
int i, newenv = 0, prot; int i, newenv = 0, prot;
MDB_meta meta; MDB_meta meta;
MDB_page *p; MDB_page *p;
env->me_flags |= flags;
memset(&meta, 0, sizeof(meta)); memset(&meta, 0, sizeof(meta));
if ((i = mdb_env_read_header(env, &meta)) != 0) { if ((i = mdb_env_read_header(env, &meta)) != 0) {
@ -2931,7 +2932,7 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl)
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
rc = ErrCode(); rc = ErrCode();
if (rc == ERROR_WRITE_PROTECT) { if (rc == ERROR_WRITE_PROTECT && (env->me_flags & MDB_RDONLY)) {
env->me_flags |= MDB_ROFS; env->me_flags |= MDB_ROFS;
return MDB_SUCCESS; return MDB_SUCCESS;
} }
@ -2949,7 +2950,7 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl)
int fdflags; int fdflags;
if ((env->me_lfd = open(lpath, O_RDWR|O_CREAT, mode)) == -1) { if ((env->me_lfd = open(lpath, O_RDWR|O_CREAT, mode)) == -1) {
rc = ErrCode(); rc = ErrCode();
if (rc == EROFS) { if (rc == EROFS && (env->me_flags & MDB_RDONLY)) {
env->me_flags |= MDB_ROFS; env->me_flags |= MDB_ROFS;
return MDB_SUCCESS; return MDB_SUCCESS;
} }
@ -2962,7 +2963,7 @@ mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl)
#else /* O_CLOEXEC on Linux: Open file and set FD_CLOEXEC atomically */ #else /* O_CLOEXEC on Linux: Open file and set FD_CLOEXEC atomically */
if ((env->me_lfd = open(lpath, O_RDWR|O_CREAT|O_CLOEXEC, mode)) == -1) { if ((env->me_lfd = open(lpath, O_RDWR|O_CREAT|O_CLOEXEC, mode)) == -1) {
rc = ErrCode(); rc = ErrCode();
if (rc == EROFS) { if (rc == EROFS && (env->me_flags & MDB_RDONLY)) {
env->me_flags |= MDB_ROFS; env->me_flags |= MDB_ROFS;
return MDB_SUCCESS; return MDB_SUCCESS;
} }
@ -3154,15 +3155,15 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mode_t mode)
sprintf(dpath, "%s" DATANAME, path); sprintf(dpath, "%s" DATANAME, path);
} }
env->me_flags = 0; /* silently ignore WRITEMAP if we're only getting read access */
if (F_ISSET(flags, MDB_RDONLY|MDB_WRITEMAP))
flags ^= MDB_WRITEMAP;
env->me_flags = flags |= MDB_ENV_ACTIVE;
rc = mdb_env_setup_locks(env, lpath, mode, &excl); rc = mdb_env_setup_locks(env, lpath, mode, &excl);
if (rc) if (rc)
goto leave; goto leave;
/* silently ignore WRITEMAP if we're only getting read access */
if (F_ISSET(flags, MDB_RDONLY) && F_ISSET(flags, MDB_WRITEMAP))
flags ^= MDB_WRITEMAP;
#ifdef _WIN32 #ifdef _WIN32
if (F_ISSET(flags, MDB_RDONLY)) { if (F_ISSET(flags, MDB_RDONLY)) {
oflags = GENERIC_READ; oflags = GENERIC_READ;
@ -3187,7 +3188,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mode_t mode)
goto leave; goto leave;
} }
if ((rc = mdb_env_open2(env, flags)) == MDB_SUCCESS) { if ((rc = mdb_env_open2(env)) == MDB_SUCCESS) {
if (flags & (MDB_RDONLY|MDB_NOSYNC|MDB_NOMETASYNC|MDB_WRITEMAP)) { if (flags & (MDB_RDONLY|MDB_NOSYNC|MDB_NOMETASYNC|MDB_WRITEMAP)) {
env->me_mfd = env->me_fd; env->me_mfd = env->me_fd;
} else { } else {
@ -3242,7 +3243,7 @@ mdb_env_close0(MDB_env *env, int excl)
{ {
int i; int i;
if (env->me_lfd == INVALID_HANDLE_VALUE) /* 1st field to get inited */ if (!(env->me_flags & MDB_ENV_ACTIVE))
return; return;
free(env->me_dbflags); free(env->me_dbflags);
@ -3303,9 +3304,11 @@ mdb_env_close0(MDB_env *env, int excl)
#endif #endif
munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo)); munmap((void *)env->me_txns, (env->me_maxreaders-1)*sizeof(MDB_reader)+sizeof(MDB_txninfo));
} }
if (env->me_lfd != INVALID_HANDLE_VALUE) {
close(env->me_lfd); close(env->me_lfd);
}
env->me_lfd = INVALID_HANDLE_VALUE; /* Mark env as reset */ env->me_flags &= ~MDB_ENV_ACTIVE;
} }
int int
@ -3357,14 +3360,26 @@ mdb_env_copy(MDB_env *env, const char *path)
} }
#endif #endif
/* Do the lock/unlock of the reader mutex before starting the
* write txn. Otherwise other read txns could block writers.
*/
rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
if (rc)
goto leave;
if (!(env->me_flags & MDB_ROFS)) {
/* We must start the actual read txn after blocking writers */
mdb_txn_reset0(txn);
/* Temporarily block writers until we snapshot the meta pages */ /* Temporarily block writers until we snapshot the meta pages */
LOCK_MUTEX_W(env); LOCK_MUTEX_W(env);
rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); rc = mdb_txn_renew0(txn);
if (rc) { if (rc) {
UNLOCK_MUTEX_W(env); UNLOCK_MUTEX_W(env);
goto leave; goto leave;
} }
}
wsize = env->me_psize * 2; wsize = env->me_psize * 2;
#ifdef _WIN32 #ifdef _WIN32
@ -3377,6 +3392,7 @@ mdb_env_copy(MDB_env *env, const char *path)
rc = write(newfd, env->me_map, wsize); rc = write(newfd, env->me_map, wsize);
rc = (rc == (int)wsize) ? MDB_SUCCESS : ErrCode(); rc = (rc == (int)wsize) ? MDB_SUCCESS : ErrCode();
#endif #endif
if (! (env->me_flags & MDB_ROFS))
UNLOCK_MUTEX_W(env); UNLOCK_MUTEX_W(env);
if (rc) if (rc)

Loading…
Cancel
Save