]> git.sur5r.net Git - openldap/blobdiff - libraries/liblmdb/mdb.c
Windows compat
[openldap] / libraries / liblmdb / mdb.c
index 0520eb72d51dd55fdc55abca99d05066997e64e2..4712ac25d60c471c844942bfcdda53fcb06a6b9f 100644 (file)
@@ -1149,8 +1149,8 @@ typedef struct MDB_ntxn {
        ((txn) && (dbi) < (txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & DB_VALID))
 
        /** Check for misused \b dbi handles */
-#define TXN_DBI_CHANGED(txn, md_name, dbi) \
-       (!(md_name).mv_size || (txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi])
+#define TXN_DBI_CHANGED(txn, dbi) \
+       ((txn)->mt_dbiseqs[dbi] != (txn)->mt_env->me_dbiseqs[dbi])
 
 static int  mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp);
 static int  mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp);
@@ -1248,7 +1248,7 @@ static char *const mdb_errstr[] = {
        "MDB_TXN_FULL: Transaction has too many dirty pages - transaction too big",
        "MDB_CURSOR_FULL: Internal error - cursor stack limit reached",
        "MDB_PAGE_FULL: Internal error - page has no more space",
-       "MDB_MAP_RESIZED: Environment mapsize was changed by another process",
+       "MDB_MAP_RESIZED: Database contents grew beyond environment mapsize",
        "MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed",
        "MDB_BAD_RSLOT: Invalid reuse of reader locktable slot",
        "MDB_BAD_TXN: Transaction cannot recover - it must be aborted",
@@ -1259,6 +1259,14 @@ static char *const mdb_errstr[] = {
 char *
 mdb_strerror(int err)
 {
+#ifdef _WIN32
+       /** HACK: pad 4KB on stack over the buf. Return system msgs in buf.
+        *      This works as long as no function between the call to mdb_strerror
+        *      and the actual use of the message uses more than 4K of stack.
+        */
+       char pad[4096];
+       char buf[1024], *ptr = buf;
+#endif
        int i;
        if (!err)
                return ("Successful return: 0");
@@ -1268,7 +1276,32 @@ mdb_strerror(int err)
                return mdb_errstr[i];
        }
 
+#ifdef _WIN32
+       /* These are the C-runtime error codes we use. The comment indicates
+        * their numeric value, and the Win32 error they would correspond to
+        * if the error actually came from a Win32 API. A major mess, we should
+        * have used LMDB-specific error codes for everything.
+        */
+       switch(err) {
+       case ENOENT:    /* 2, FILE_NOT_FOUND */
+       case EIO:               /* 5, ACCESS_DENIED */
+       case ENOMEM:    /* 12, INVALID_ACCESS */
+       case EACCES:    /* 13, INVALID_DATA */
+       case EBUSY:             /* 16, CURRENT_DIRECTORY */
+       case EINVAL:    /* 22, BAD_COMMAND */
+       case ENOSPC:    /* 28, OUT_OF_PAPER */
+               return strerror(err);
+       default:
+               ;
+       }
+       buf[0] = 0;
+       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+               FORMAT_MESSAGE_IGNORE_INSERTS,
+               NULL, err, 0, ptr, sizeof(buf), pad);
+       return ptr;
+#else
        return strerror(err);
+#endif
 }
 
 /** assert(3) variant in cursor context */
@@ -2503,9 +2536,9 @@ mdb_txn_renew0(MDB_txn *txn)
        }
        txn->mt_dbflags[0] = txn->mt_dbflags[1] = DB_VALID;
 
-       /* If we didn't ask for a resize, but the size changed, fail */
+       /* If we didn't ask for a resize, but the size grew, fail */
        if (!(env->me_flags & MDB_RESIZING)
-               && env->me_mapsize != meta->mm_mapsize) {
+               && env->me_mapsize < meta->mm_mapsize) {
                mdb_txn_reset0(txn, "renew0-mapfail");
                if (new_notls) {
                        txn->mt_u.reader->mr_pid = 0;
@@ -2564,21 +2597,31 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
                tsize = sizeof(MDB_ntxn);
        }
        size = tsize + env->me_maxdbs * (sizeof(MDB_db)+1);
-       if (!(flags & MDB_RDONLY))
-               size += env->me_maxdbs * (sizeof(MDB_cursor *)+sizeof(unsigned int));
+       if (!(flags & MDB_RDONLY)) {
+               size += env->me_maxdbs * sizeof(MDB_cursor *);
+               /* child txns use parent's dbiseqs */
+               if (!parent)
+                       size += env->me_maxdbs * sizeof(unsigned int);
+       }
 
        if ((txn = calloc(1, size)) == NULL) {
-               DPRINTF(("calloc: %s", strerror(ErrCode())));
+               DPRINTF(("calloc: %s", strerror(errno)));
                return ENOMEM;
        }
        txn->mt_dbs = (MDB_db *) ((char *)txn + tsize);
        if (flags & MDB_RDONLY) {
                txn->mt_flags |= MDB_TXN_RDONLY;
                txn->mt_dbflags = (unsigned char *)(txn->mt_dbs + env->me_maxdbs);
+               txn->mt_dbiseqs = env->me_dbiseqs;
        } else {
                txn->mt_cursors = (MDB_cursor **)(txn->mt_dbs + 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);
+               if (parent) {
+                       txn->mt_dbiseqs = parent->mt_dbiseqs;
+                       txn->mt_dbflags = (unsigned char *)(txn->mt_cursors + env->me_maxdbs);
+               } else {
+                       txn->mt_dbiseqs = (unsigned int *)(txn->mt_cursors + env->me_maxdbs);
+                       txn->mt_dbflags = (unsigned char *)(txn->mt_dbiseqs + env->me_maxdbs);
+               }
        }
        txn->mt_env = env;
 
@@ -2658,11 +2701,13 @@ mdb_dbis_update(MDB_txn *txn, int keep)
                                env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDB_VALID;
                        } else {
                                char *ptr = env->me_dbxs[i].md_name.mv_data;
-                               env->me_dbxs[i].md_name.mv_data = NULL;
-                               env->me_dbxs[i].md_name.mv_size = 0;
-                               env->me_dbflags[i] = 0;
-                               env->me_dbiseqs[i]++;
-                               free(ptr);
+                               if (ptr) {
+                                       env->me_dbxs[i].md_name.mv_data = NULL;
+                                       env->me_dbxs[i].md_name.mv_size = 0;
+                                       env->me_dbflags[i] = 0;
+                                       env->me_dbiseqs[i]++;
+                                       free(ptr);
+                               }
                        }
                }
        }
@@ -3252,7 +3297,7 @@ mdb_txn_commit(MDB_txn *txn)
                mdb_cursor_init(&mc, txn, MAIN_DBI, NULL);
                for (i = 2; i < txn->mt_numdbs; i++) {
                        if (txn->mt_dbflags[i] & DB_DIRTY) {
-                               if (TXN_DBI_CHANGED(txn, txn->mt_dbxs[i].md_name, i)) {
+                               if (TXN_DBI_CHANGED(txn, i)) {
                                        rc = MDB_BAD_DBI;
                                        goto fail;
                                }
@@ -3779,13 +3824,17 @@ mdb_env_open2(MDB_env *env)
                 * 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;
+       } 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;
+               }
+               if (env->me_mapsize != meta.mm_mapsize)
+                       env->me_flags |= MDB_RESIZING;
        }
 
        rc = mdb_env_map(env, meta.mm_address, newenv || env->me_mapsize != meta.mm_mapsize);
@@ -4976,7 +5025,7 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags)
                /* Make sure we're using an up-to-date root */
                if (*mc->mc_dbflag & DB_STALE) {
                                MDB_cursor mc2;
-                               if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbx->md_name, mc->mc_dbi))
+                               if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi))
                                        return MDB_BAD_DBI;
                                mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, NULL);
                                rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, 0);
@@ -5832,7 +5881,7 @@ mdb_cursor_touch(MDB_cursor *mc)
        if (mc->mc_dbi > MAIN_DBI && !(*mc->mc_dbflag & DB_DIRTY)) {
                MDB_cursor mc2;
                MDB_xcursor mcx;
-               if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbx->md_name, mc->mc_dbi))
+               if (TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi))
                        return MDB_BAD_DBI;
                mdb_cursor_init(&mc2, mc->mc_txn, MAIN_DBI, &mcx);
                rc = mdb_page_search(&mc2, &mc->mc_dbx->md_name, MDB_PS_MODIFY);
@@ -8808,7 +8857,7 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
        MDB_dbi i;
        MDB_cursor mc;
        int rc, dbflag, exact;
-       unsigned int unused = 0;
+       unsigned int unused = 0, seq;
        size_t len;
 
        if (txn->mt_dbxs[FREE_DBI].md_cmp == NULL) {
@@ -8893,9 +8942,12 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
                txn->mt_dbxs[slot].md_name.mv_size = len;
                txn->mt_dbxs[slot].md_rel = NULL;
                txn->mt_dbflags[slot] = dbflag;
-               /* read txns don't track sequence numbers */
-               if (!(txn->mt_flags & MDB_TXN_RDONLY))
-                       txn->mt_dbiseqs[slot] = ++txn->mt_env->me_dbiseqs[slot];
+               /* txn-> and env-> are the same in read txns, use
+                * tmp variable to avoid undefined assignment
+                */
+               seq = ++txn->mt_env->me_dbiseqs[slot];
+               txn->mt_dbiseqs[slot] = seq;
+
                memcpy(&txn->mt_dbs[slot], data.mv_data, sizeof(MDB_db));
                *dbi = slot;
                mdb_default_cmp(txn, slot);
@@ -8930,11 +8982,14 @@ void mdb_dbi_close(MDB_env *env, MDB_dbi dbi)
        if (dbi <= MAIN_DBI || dbi >= env->me_maxdbs)
                return;
        ptr = env->me_dbxs[dbi].md_name.mv_data;
-       env->me_dbxs[dbi].md_name.mv_data = NULL;
-       env->me_dbxs[dbi].md_name.mv_size = 0;
-       env->me_dbflags[dbi] = 0;
-       env->me_dbiseqs[dbi]++;
-       free(ptr);
+       /* If there was no name, this was already closed */
+       if (ptr) {
+               env->me_dbxs[dbi].md_name.mv_data = NULL;
+               env->me_dbxs[dbi].md_name.mv_size = 0;
+               env->me_dbflags[dbi] = 0;
+               env->me_dbiseqs[dbi]++;
+               free(ptr);
+       }
 }
 
 int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags)
@@ -9044,7 +9099,7 @@ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
        if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
                return EACCES;
 
-       if (dbi > MAIN_DBI && TXN_DBI_CHANGED(txn, txn->mt_dbxs[dbi].md_name, dbi))
+       if (dbi > MAIN_DBI && TXN_DBI_CHANGED(txn, dbi))
                return MDB_BAD_DBI;
 
        rc = mdb_cursor_open(txn, dbi, &mc);