|
|
@ -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) |
|
|
|