aboutsummaryrefslogtreecommitdiff
path: root/external/db_drivers/liblmdb/mdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'external/db_drivers/liblmdb/mdb.c')
-rw-r--r--external/db_drivers/liblmdb/mdb.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/external/db_drivers/liblmdb/mdb.c b/external/db_drivers/liblmdb/mdb.c
index 6314d5775..bf60c7013 100644
--- a/external/db_drivers/liblmdb/mdb.c
+++ b/external/db_drivers/liblmdb/mdb.c
@@ -1467,6 +1467,8 @@ struct MDB_env {
#endif
/** Failed to update the meta page. Probably an I/O error. */
#define MDB_FATAL_ERROR 0x80000000U
+ /** using a raw block device */
+#define MDB_RAWPART 0x40000000U
/** Some fields are initialized. */
#define MDB_ENV_ACTIVE 0x20000000U
/** me_txkey is set */
@@ -4038,6 +4040,8 @@ fail:
return rc;
}
+static int ESECT mdb_env_map(MDB_env *env, void *addr);
+
/** Read the environment parameters of a DB environment before
* mapping it into memory.
* @param[in] env the environment handle
@@ -4054,6 +4058,31 @@ mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta)
int i, rc, off;
enum { Size = sizeof(pbuf) };
+ if (env->me_flags & MDB_RAWPART) {
+#define VM_ALIGN 0x200000
+ env->me_mapsize += VM_ALIGN-1;
+ env->me_mapsize &= ~(VM_ALIGN-1);
+ env->me_psize = env->me_os_psize;
+ rc = mdb_env_map(env, NULL);
+ if (rc) {
+ DPRINTF(("mdb_env_map: %s", mdb_strerror(rc)));
+ return rc;
+ }
+ p = (MDB_page *)env->me_map;
+ for (i=0; i<NUM_METAS; i++) {
+ if (!F_ISSET(p->mp_flags, P_META))
+ return ENOENT;
+ if (env->me_metas[i]->mm_magic != MDB_MAGIC)
+ return MDB_INVALID;
+ if (env->me_metas[i]->mm_version != MDB_DATA_VERSION)
+ return MDB_VERSION_MISMATCH;
+ if (i == 0 || env->me_metas[i]->mm_txnid > meta->mm_txnid)
+ *meta = *env->me_metas[i];
+ p = (MDB_page *)((char *)p + env->me_psize);
+ }
+ return 0;
+ }
+
/* We don't know the page size yet, so use a minimum value.
* Read both meta pages so we can use the latest one.
*/
@@ -4081,6 +4110,8 @@ mdb_env_read_header(MDB_env *env, int prev, MDB_meta *meta)
p = (MDB_page *)&pbuf;
if (!F_ISSET(p->mp_flags, P_META)) {
+ if (env->me_flags & MDB_RAWPART)
+ return ENOENT;
DPRINTF(("page %"Yu" not a meta page", p->mp_pgno));
return MDB_INVALID;
}
@@ -4148,6 +4179,18 @@ mdb_env_init_meta(MDB_env *env, MDB_meta *meta)
psize = env->me_psize;
+ if ((env->me_flags & (MDB_RAWPART|MDB_WRITEMAP)) == (MDB_RAWPART|MDB_WRITEMAP)) {
+ p = (MDB_page *)env->me_map;
+ p->mp_pgno = 0;
+ p->mp_flags = P_META;
+ *(MDB_meta *)METADATA(p) = *meta;
+ q = (MDB_page *)((char *)p + psize);
+ q->mp_pgno = 1;
+ q->mp_flags = P_META;
+ *(MDB_meta *)METADATA(q) = *meta;
+ return 0;
+ }
+
p = calloc(NUM_METAS, psize);
if (!p)
return ENOMEM;
@@ -4410,7 +4453,7 @@ mdb_env_map(MDB_env *env, void *addr)
int prot = PROT_READ;
if (flags & MDB_WRITEMAP) {
prot |= PROT_WRITE;
- if (ftruncate(env->me_fd, env->me_mapsize) < 0)
+ if (!(flags & MDB_RAWPART) && ftruncate(env->me_fd, env->me_mapsize) < 0)
return ErrCode();
}
env->me_map = mmap(addr, env->me_mapsize, prot, MAP_SHARED,
@@ -5449,6 +5492,17 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode
goto leave;
#endif
#endif
+#ifndef _WIN32
+ {
+ struct stat st;
+ flags &= ~MDB_RAWPART;
+ if (!stat(path, &st) && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) {
+ flags |= MDB_RAWPART | MDB_NOSUBDIR;
+ if (!env->me_mapsize)
+ env->me_mapsize = DEFAULT_MAPSIZE;
+ }
+ }
+#endif
flags |= MDB_ENV_ACTIVE; /* tell mdb_env_close0() to clean up */
if (flags & MDB_RDONLY) {
@@ -7668,7 +7722,7 @@ more:
offset *= 4; /* space for 4 more */
break;
}
- /* FALLTHRU: Big enough MDB_DUPFIXED sub-page */
+ /* FALLTHRU *//* Big enough MDB_DUPFIXED sub-page */
case MDB_CURRENT:
fp->mp_flags |= P_DIRTY;
COPY_PGNO(fp->mp_pgno, mp->mp_pgno);