On-demand pagemapping for 32bit mode

Build with -DVL32 to enable.
vl32
Howard Chu 10 years ago
parent 891e662754
commit 61559e279e
  1. 1
      libraries/liblmdb/Makefile
  2. 123
      libraries/liblmdb/mdb.c
  3. 4
      libraries/liblmdb/midl.h
  4. 2
      libraries/liblmdb/mtest.c

@ -24,6 +24,7 @@ CFLAGS = $(THREADS) $(OPT) $(W) $(XCFLAGS)
LDLIBS = LDLIBS =
SOLIBS = SOLIBS =
prefix = /usr/local prefix = /usr/local
XCFLAGS = -DVL32
######################################################################## ########################################################################

@ -988,6 +988,10 @@ struct MDB_txn {
MDB_cursor **mt_cursors; MDB_cursor **mt_cursors;
/** Array of flags for each DB */ /** Array of flags for each DB */
unsigned char *mt_dbflags; unsigned char *mt_dbflags;
#ifdef VL32
/** List of read-only pages */
MDB_ID2L mt_rpages;
#endif
/** Number of DB records in use. This number only ever increments; /** Number of DB records in use. This number only ever increments;
* we don't decrement it when individual DB handles are closed. * we don't decrement it when individual DB handles are closed.
*/ */
@ -1090,6 +1094,9 @@ struct MDB_env {
HANDLE me_fd; /**< The main data file */ HANDLE me_fd; /**< The main data file */
HANDLE me_lfd; /**< The lock file */ HANDLE me_lfd; /**< The lock file */
HANDLE me_mfd; /**< just for writing the meta pages */ HANDLE me_mfd; /**< just for writing the meta pages */
#if defined(VL32) && defined(_WIN32)
HANDLE me_fmh; /**< File Mapping handle */
#endif
/** Failed to update the meta page. Probably an I/O error. */ /** Failed to update the meta page. Probably an I/O error. */
#define MDB_FATAL_ERROR 0x80000000U #define MDB_FATAL_ERROR 0x80000000U
/** Some fields are initialized. */ /** Some fields are initialized. */
@ -2638,6 +2645,15 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
DPRINTF(("calloc: %s", strerror(errno))); DPRINTF(("calloc: %s", strerror(errno)));
return ENOMEM; return ENOMEM;
} }
#ifdef VL32
if (!parent) {
txn->mt_rpages = calloc(MDB_IDL_UM_SIZE, sizeof(MDB_ID2));
if (!txn->mt_rpages) {
free(txn);
return ENOMEM;
}
}
#endif
txn->mt_dbs = (MDB_db *) ((char *)txn + tsize); txn->mt_dbs = (MDB_db *) ((char *)txn + tsize);
if (flags & MDB_RDONLY) { if (flags & MDB_RDONLY) {
txn->mt_flags |= MDB_TXN_RDONLY; txn->mt_flags |= MDB_TXN_RDONLY;
@ -2676,6 +2692,9 @@ ok:
txn->mt_numdbs = parent->mt_numdbs; txn->mt_numdbs = parent->mt_numdbs;
txn->mt_flags = parent->mt_flags; txn->mt_flags = parent->mt_flags;
txn->mt_dbxs = parent->mt_dbxs; txn->mt_dbxs = parent->mt_dbxs;
#ifdef VL32
txn->mt_rpages = parent->mt_rpages;
#endif
memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDB_db)); memcpy(txn->mt_dbs, parent->mt_dbs, txn->mt_numdbs * sizeof(MDB_db));
/* Copy parent's mt_dbflags, but clear DB_NEW */ /* Copy parent's mt_dbflags, but clear DB_NEW */
for (i=0; i<txn->mt_numdbs; i++) for (i=0; i<txn->mt_numdbs; i++)
@ -2799,6 +2818,22 @@ mdb_txn_reset0(MDB_txn *txn, const char *act)
if (env->me_txns) if (env->me_txns)
UNLOCK_MUTEX_W(env); UNLOCK_MUTEX_W(env);
} }
#ifdef VL32
{
unsigned i, n = txn->mt_rpages[0].mid;
for (i = 1; i <= n; i++) {
#ifdef _WIN32
UnmapViewOfFile(txn->mt_rpages[i].mptr);)
#else
MDB_page *mp = txn->mt_rpages[i].mptr;
int size = txn->mt_env->me_psize;
if (IS_OVERFLOW(mp)) size *= mp->mp_pages;
munmap(mp, size);
#endif
}
}
txn->mt_rpages[0].mid = 0;
#endif
} }
void void
@ -3714,13 +3749,29 @@ mdb_env_map(MDB_env *env, void *addr)
sizehi, sizelo, NULL); sizehi, sizelo, NULL);
if (!mh) if (!mh)
return ErrCode(); return ErrCode();
#ifdef VL32
msize = 2 * env->me_psize;
#endif
env->me_map = MapViewOfFileEx(mh, flags & MDB_WRITEMAP ? env->me_map = MapViewOfFileEx(mh, flags & MDB_WRITEMAP ?
FILE_MAP_WRITE : FILE_MAP_READ, FILE_MAP_WRITE : FILE_MAP_READ,
0, 0, msize, addr); 0, 0, msize, addr);
rc = env->me_map ? 0 : ErrCode(); rc = env->me_map ? 0 : ErrCode();
#ifdef VL32
env->me_fmh = mh;
#else
CloseHandle(mh); CloseHandle(mh);
#endif
if (rc) if (rc)
return rc; return rc;
#else
#ifdef VL32
(void) flags;
env->me_map = mmap(addr, 2 * env->me_psize, PROT_READ, MAP_SHARED,
env->me_fd, 0);
if (env->me_map == MAP_FAILED) {
env->me_map = NULL;
return ErrCode();
}
#else #else
int prot = PROT_READ; int prot = PROT_READ;
if (flags & MDB_WRITEMAP) { if (flags & MDB_WRITEMAP) {
@ -3754,6 +3805,7 @@ mdb_env_map(MDB_env *env, void *addr)
*/ */
if (addr && env->me_map != addr) if (addr && env->me_map != addr)
return EBUSY; /* TODO: Make a new MDB_* error code? */ return EBUSY; /* TODO: Make a new MDB_* error code? */
#endif
p = (MDB_page *)env->me_map; p = (MDB_page *)env->me_map;
env->me_metas[0] = METADATA(p); env->me_metas[0] = METADATA(p);
@ -4405,6 +4457,17 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
if (env->me_fd!=INVALID_HANDLE_VALUE || (flags & ~(CHANGEABLE|CHANGELESS))) if (env->me_fd!=INVALID_HANDLE_VALUE || (flags & ~(CHANGEABLE|CHANGELESS)))
return EINVAL; return EINVAL;
#ifdef VL32
if (flags & MDB_WRITEMAP) {
/* silently ignore WRITEMAP in 32 bit mode */
flags ^= MDB_WRITEMAP;
}
if (flags & MDB_FIXEDMAP) {
/* cannot support FIXEDMAP */
return EINVAL;
}
#endif
len = strlen(path); len = strlen(path);
if (flags & MDB_NOSUBDIR) { if (flags & MDB_NOSUBDIR) {
rc = len + sizeof(LOCKSUFF) + len + 1; rc = len + sizeof(LOCKSUFF) + len + 1;
@ -4525,6 +4588,13 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
txn->mt_dbiseqs = (unsigned int *)(txn->mt_cursors + env->me_maxdbs); txn->mt_dbiseqs = (unsigned int *)(txn->mt_cursors + env->me_maxdbs);
txn->mt_dbflags = (unsigned char *)(txn->mt_dbiseqs + env->me_maxdbs); txn->mt_dbflags = (unsigned char *)(txn->mt_dbiseqs + env->me_maxdbs);
txn->mt_env = env; txn->mt_env = env;
#ifdef VL32
txn->mt_rpages = calloc(MDB_IDL_UM_SIZE, sizeof(MDB_ID2));
if (!txn->mt_rpages) {
free(txn);
rc = ENOMEM;
}
#endif
env->me_txn0 = txn; env->me_txn0 = txn;
} else { } else {
rc = ENOMEM; rc = ENOMEM;
@ -4576,7 +4646,11 @@ mdb_env_close0(MDB_env *env, int excl)
} }
if (env->me_map) { if (env->me_map) {
#ifdef VL32
munmap(env->me_map, 2*env->me_psize);
#else
munmap(env->me_map, env->me_mapsize); munmap(env->me_map, env->me_mapsize);
#endif
} }
if (env->me_mfd != env->me_fd && env->me_mfd != INVALID_HANDLE_VALUE) if (env->me_mfd != env->me_fd && env->me_mfd != INVALID_HANDLE_VALUE)
(void) close(env->me_mfd); (void) close(env->me_mfd);
@ -4943,7 +5017,56 @@ mdb_page_get(MDB_txn *txn, pgno_t pgno, MDB_page **ret, int *lvl)
if (pgno < txn->mt_next_pgno) { if (pgno < txn->mt_next_pgno) {
level = 0; level = 0;
#ifdef VL32
{
unsigned x = mdb_mid2l_search(txn->mt_rpages, pgno);
if (x <= txn->mt_rpages[0].mid && txn->mt_rpages[x].mid == pgno) {
p = txn->mt_rpages[x].mptr;
goto done;
}
if (txn->mt_rpages[0].mid < MDB_IDL_UM_SIZE) {
MDB_ID2 id2;
size_t len = env->me_psize;
int np;
#ifdef _WIN32
size_t off = pgno * env->me_psize;
DWORD lo, hi;
lo = off & 0xffffffff;
hi = off >> 16 >> 16;
p = MapViewOfFile(env->me_fmh, FILE_MAP_READ, hi, lo, len);
if (p == NULL)
return ErrCode();
if (IS_OVERFLOW(p)) {
np = p->mp_pages;
UnmapViewOfFile(p);
len *= np;
p = MapViewOfFile(env->me_fmh, FILE_MAP_READ, hi, lo, len);
if (p == NULL)
return ErrCode();
}
#else
off_t off = pgno * env->me_psize;
p = mmap(NULL, len, PROT_READ, MAP_SHARED, env->me_fd, off);
if (p == MAP_FAILED)
return errno;
if (IS_OVERFLOW(p)) {
np = p->mp_pages;
munmap(p, len);
len *= np;
p = mmap(NULL, len, PROT_READ, MAP_SHARED, env->me_fd, off);
if (p == MAP_FAILED)
return errno;
}
#endif
id2.mid = pgno;
id2.mptr = p;
mdb_mid2l_insert(txn->mt_rpages, &id2);
goto done;
}
}
#else
p = (MDB_page *)(env->me_map + env->me_psize * pgno); p = (MDB_page *)(env->me_map + env->me_psize * pgno);
#endif
} else { } else {
DPRINTF(("page %"Z"u not found", pgno)); DPRINTF(("page %"Z"u not found", pgno));
txn->mt_flags |= MDB_TXN_ERROR; txn->mt_flags |= MDB_TXN_ERROR;

@ -55,7 +55,11 @@ typedef MDB_ID *MDB_IDL;
/* IDL sizes - likely should be even bigger /* IDL sizes - likely should be even bigger
* limiting factors: sizeof(ID), thread stack size * limiting factors: sizeof(ID), thread stack size
*/ */
#ifdef VL32
#define MDB_IDL_LOGN 10 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
#else
#define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */ #define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
#endif
#define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN) #define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
#define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1)) #define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))

@ -46,7 +46,7 @@ int main(int argc,char * argv[])
E(mdb_env_create(&env)); E(mdb_env_create(&env));
E(mdb_env_set_mapsize(env, 10485760)); E(mdb_env_set_mapsize(env, 10485760));
E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP /*|MDB_NOSYNC*/, 0664)); E(mdb_env_open(env, "./testdb", 0 /* MDB_FIXEDMAP |MDB_NOSYNC*/, 0664));
E(mdb_txn_begin(env, NULL, 0, &txn)); E(mdb_txn_begin(env, NULL, 0, &txn));
E(mdb_open(txn, NULL, 0, &dbi)); E(mdb_open(txn, NULL, 0, &dbi));

Loading…
Cancel
Save