MDB_page *me_dpages; /**< list of malloc'd blocks for re-use */
/** IDL of pages that became unused in a write txn */
MDB_IDL me_free_pgs;
- /** ID2L of pages that were written during a write txn */
- MDB_ID2 me_dirty_list[MDB_IDL_UM_SIZE];
+ /** ID2L of pages written during a write txn. Length MDB_IDL_UM_SIZE. */
+ MDB_ID2L me_dirty_list;
/** Max number of freelist items that can fit in a single overflow page */
unsigned int me_maxfree_1pg;
/** Max size of a node on a page */
if (!e)
return ENOMEM;
- e->me_free_pgs = mdb_midl_alloc();
- if (!e->me_free_pgs) {
- free(e);
- return ENOMEM;
- }
e->me_maxreaders = DEFAULT_READERS;
e->me_maxdbs = 2;
e->me_fd = INVALID_HANDLE_VALUE;
* @param[in] lpath The pathname of the file used for the lock region.
* @param[in] mode The Unix permissions for the file, if we create it.
* @param[out] excl Resulting file lock type: -1 none, 0 shared, 1 exclusive
+ * @param[in,out] excl In -1, out lock type: -1 none, 0 shared, 1 exclusive
* @return 0 on success, non-zero on failure.
*/
static int
mdb_env_setup_locks(MDB_env *env, char *lpath, int mode, int *excl)
{
+#ifdef _WIN32
+# define MDB_ERRCODE_ROFS ERROR_WRITE_PROTECT
+#else
+# define MDB_ERRCODE_ROFS EROFS
+#ifdef O_CLOEXEC /* Linux: Open file and set FD_CLOEXEC atomically */
+# define MDB_CLOEXEC O_CLOEXEC
+#else
+ int fdflags;
+# define MDB_CLOEXEC 0
+#endif
+#endif
int rc;
off_t size, rsize;
- *excl = -1;
-
#ifdef _WIN32
- if ((env->me_lfd = CreateFile(lpath, GENERIC_READ|GENERIC_WRITE,
+ env->me_lfd = CreateFile(lpath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
- rc = ErrCode();
- if (rc == ERROR_WRITE_PROTECT && (env->me_flags & MDB_RDONLY)) {
- env->me_flags |= MDB_ROFS;
- return MDB_SUCCESS;
- }
- goto fail_errno;
- }
- /* Try to get exclusive lock. If we succeed, then
- * nobody is using the lock region and we should initialize it.
- */
- if ((rc = mdb_env_excl_lock(env, excl))) goto fail;
- size = GetFileSize(env->me_lfd, NULL);
-
+ FILE_ATTRIBUTE_NORMAL, NULL);
#else
-#if !(O_CLOEXEC)
- {
- int fdflags;
- if ((env->me_lfd = open(lpath, O_RDWR|O_CREAT, mode)) == -1) {
- rc = ErrCode();
- if (rc == EROFS && (env->me_flags & MDB_RDONLY)) {
- env->me_flags |= MDB_ROFS;
- return MDB_SUCCESS;
- }
- goto fail_errno;
- }
- /* Lose record locks when exec*() */
- if ((fdflags = fcntl(env->me_lfd, F_GETFD) | FD_CLOEXEC) >= 0)
- fcntl(env->me_lfd, F_SETFD, fdflags);
- }
-#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) {
+ env->me_lfd = open(lpath, O_RDWR|O_CREAT|MDB_CLOEXEC, mode);
+#endif
+ if (env->me_lfd == INVALID_HANDLE_VALUE) {
rc = ErrCode();
- if (rc == EROFS && (env->me_flags & MDB_RDONLY)) {
+ if (rc == MDB_ERRCODE_ROFS && (env->me_flags & MDB_RDONLY)) {
env->me_flags |= MDB_ROFS;
return MDB_SUCCESS;
}
goto fail_errno;
}
+#if ! ((MDB_CLOEXEC) || defined(_WIN32))
+ /* Lose record locks when exec*() */
+ if ((fdflags = fcntl(env->me_lfd, F_GETFD) | FD_CLOEXEC) >= 0)
+ fcntl(env->me_lfd, F_SETFD, fdflags);
#endif
/* Try to get exclusive lock. If we succeed, then
*/
if ((rc = mdb_env_excl_lock(env, excl))) goto fail;
+#ifdef _WIN32
+ size = GetFileSize(env->me_lfd, NULL);
+#else
size = lseek(env->me_lfd, 0, SEEK_END);
#endif
rsize = (env->me_maxreaders-1) * sizeof(MDB_reader) + sizeof(MDB_txninfo);
int
mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
{
- int oflags, rc, len, excl;
+ int oflags, rc, len, excl = -1;
char *lpath, *dpath;
if (env->me_fd!=INVALID_HANDLE_VALUE || (flags & ~(CHANGEABLE|CHANGELESS)))
sprintf(dpath, "%s" DATANAME, path);
}
+ rc = MDB_SUCCESS;
flags |= env->me_flags;
- /* silently ignore WRITEMAP if we're only getting read access */
- if (F_ISSET(flags, MDB_RDONLY|MDB_WRITEMAP))
- flags ^= MDB_WRITEMAP;
+ if (flags & MDB_RDONLY) {
+ /* silently ignore WRITEMAP when we're only getting read access */
+ flags &= ~MDB_WRITEMAP;
+ } else {
+ if (!((env->me_free_pgs = mdb_midl_alloc()) &&
+ (env->me_dirty_list = calloc(MDB_IDL_UM_SIZE, sizeof(MDB_ID2)))))
+ rc = ENOMEM;
+ }
env->me_flags = flags |= MDB_ENV_ACTIVE;
+ if (rc)
+ goto leave;
+
+ env->me_path = strdup(path);
+ env->me_dbxs = calloc(env->me_maxdbs, sizeof(MDB_dbx));
+ env->me_dbflags = calloc(env->me_maxdbs, sizeof(uint16_t));
+ if (!(env->me_dbxs && env->me_path && env->me_dbflags)) {
+ rc = ENOMEM;
+ goto leave;
+ }
rc = mdb_env_setup_locks(env, lpath, mode, &excl);
if (rc)
#endif
if (excl > 0) {
rc = mdb_env_share_locks(env, &excl);
- if (rc)
- goto leave;
}
- env->me_dbxs = calloc(env->me_maxdbs, sizeof(MDB_dbx));
- env->me_dbflags = calloc(env->me_maxdbs, sizeof(uint16_t));
- env->me_path = strdup(path);
- if (!env->me_dbxs || !env->me_dbflags || !env->me_path)
- rc = ENOMEM;
}
leave:
free(env->me_dbflags);
free(env->me_dbxs);
free(env->me_path);
+ free(env->me_dirty_list);
+ if (env->me_free_pgs)
+ mdb_midl_free(env->me_free_pgs);
if (env->me_numdbs) {
pthread_key_delete(env->me_txkey);
}
mdb_env_close0(env, 0);
- mdb_midl_free(env->me_free_pgs);
free(env);
}