Merge remote-tracking branch 'origin/mdb.master'

This commit is contained in:
Howard Chu 2012-12-11 14:22:31 -08:00
commit bae86317e0
2 changed files with 64 additions and 34 deletions

View File

@ -574,6 +574,9 @@ int mdb_env_get_path(MDB_env *env, const char **path);
* of the database. The value should be chosen as large as possible, * of the database. The value should be chosen as large as possible,
* to accommodate future growth of the database. * to accommodate future growth of the database.
* This function may only be called after #mdb_env_create() and before #mdb_env_open(). * This function may only be called after #mdb_env_create() and before #mdb_env_open().
* The size may be changed by closing and reopening the environment.
* Any attempt to set a size smaller than the space already consumed
* by the environment will be silently changed to the current size of the used space.
* @param[in] env An environment handle returned by #mdb_env_create() * @param[in] env An environment handle returned by #mdb_env_create()
* @param[in] size The size in bytes * @param[in] size The size in bytes
* @return A non-zero error value on failure and 0 on success. Some possible * @return A non-zero error value on failure and 0 on success. Some possible

View File

@ -2416,47 +2416,61 @@ mdb_env_read_header(MDB_env *env, MDB_meta *meta)
MDB_pagebuf pbuf; MDB_pagebuf pbuf;
MDB_page *p; MDB_page *p;
MDB_meta *m; MDB_meta *m;
int rc, err; int i, rc, err;
/* We don't know the page size yet, so use a minimum value. /* We don't know the page size yet, so use a minimum value.
* Read both meta pages so we can use the latest one.
*/ */
for (i=0; i<2; i++) {
#ifdef _WIN32 #ifdef _WIN32
if (!ReadFile(env->me_fd, &pbuf, MDB_PAGESIZE, (DWORD *)&rc, NULL) || rc == 0) if (!ReadFile(env->me_fd, &pbuf, MDB_PAGESIZE, (DWORD *)&rc, NULL) || rc == 0)
#else #else
if ((rc = read(env->me_fd, &pbuf, MDB_PAGESIZE)) == 0) if ((rc = read(env->me_fd, &pbuf, MDB_PAGESIZE)) == 0)
#endif #endif
{ {
return ENOENT; return ENOENT;
} }
else if (rc != MDB_PAGESIZE) { else if (rc != MDB_PAGESIZE) {
err = ErrCode(); err = ErrCode();
if (rc > 0) if (rc > 0)
err = MDB_INVALID; err = MDB_INVALID;
DPRINTF("read: %s", strerror(err)); DPRINTF("read: %s", strerror(err));
return err; return err;
} }
p = (MDB_page *)&pbuf; p = (MDB_page *)&pbuf;
if (!F_ISSET(p->mp_flags, P_META)) { if (!F_ISSET(p->mp_flags, P_META)) {
DPRINTF("page %zu not a meta page", p->mp_pgno); DPRINTF("page %zu not a meta page", p->mp_pgno);
return MDB_INVALID; return MDB_INVALID;
}
m = METADATA(p);
if (m->mm_magic != MDB_MAGIC) {
DPUTS("meta has invalid magic");
return MDB_INVALID;
}
if (m->mm_version != MDB_VERSION) {
DPRINTF("database is version %u, expected version %u",
m->mm_version, MDB_VERSION);
return MDB_VERSION_MISMATCH;
}
if (i) {
if (m->mm_txnid > meta->mm_txnid)
memcpy(meta, m, sizeof(*m));
} else {
memcpy(meta, m, sizeof(*m));
#ifdef _WIN32
if (SetFilePointer(env->me_fd, meta->mm_psize, NULL, FILE_BEGIN) != meta->mm_psize)
#else
if (lseek(env->me_fd, meta->mm_psize, SEEK_SET) != meta->mm_psize)
#endif
return ErrCode();
}
} }
m = METADATA(p);
if (m->mm_magic != MDB_MAGIC) {
DPUTS("meta has invalid magic");
return MDB_INVALID;
}
if (m->mm_version != MDB_VERSION) {
DPRINTF("database is version %u, expected version %u",
m->mm_version, MDB_VERSION);
return MDB_VERSION_MISMATCH;
}
memcpy(meta, m, sizeof(*m));
return 0; return 0;
} }
@ -2504,10 +2518,12 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
#ifdef _WIN32 #ifdef _WIN32
{ {
DWORD len; DWORD len;
SetFilePointer(env->me_fd, 0, NULL, FILE_BEGIN);
rc = WriteFile(env->me_fd, p, psize * 2, &len, NULL); rc = WriteFile(env->me_fd, p, psize * 2, &len, NULL);
rc = (len == psize * 2) ? MDB_SUCCESS : ErrCode(); rc = (len == psize * 2) ? MDB_SUCCESS : ErrCode();
} }
#else #else
lseek(env->me_fd, 0, SEEK_SET);
rc = write(env->me_fd, p, psize * 2); rc = write(env->me_fd, p, psize * 2);
rc = (rc == (int)psize * 2) ? MDB_SUCCESS : ErrCode(); rc = (rc == (int)psize * 2) ? MDB_SUCCESS : ErrCode();
#endif #endif
@ -2722,11 +2738,22 @@ mdb_env_open2(MDB_env *env)
return i; return i;
DPUTS("new mdbenv"); DPUTS("new mdbenv");
newenv = 1; newenv = 1;
meta.mm_mapsize = env->me_mapsize > DEFAULT_MAPSIZE ? env->me_mapsize : DEFAULT_MAPSIZE;
} }
if (env->me_mapsize < meta.mm_mapsize) /* Was a mapsize configured? */
env->me_mapsize = meta.mm_mapsize; if (!env->me_mapsize) {
/* If this is a new environment, take the default,
* else use the size recorded in the existing env.
*/
env->me_mapsize = newenv ? DEFAULT_MAPSIZE : meta.mm_mapsize;
} else if (env->me_mapsize < meta.mm_mapsize) {
/* If the configured size is smaller, make sure it's
* still big enough. Silently round up to minimum if not.
*/
size_t minsize = (meta.mm_last_pg + 1) * meta.mm_psize;
if (env->me_mapsize < minsize)
env->me_mapsize = minsize;
}
#ifdef _WIN32 #ifdef _WIN32
{ {