]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.11-20131101
authorWietse Venema <wietse@porcupine.org>
Fri, 1 Nov 2013 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sat, 2 Nov 2013 01:53:14 +0000 (21:53 -0400)
postfix/HISTORY
postfix/src/global/mail_version.h
postfix/src/util/dict_lmdb.c
postfix/src/util/slmdb.c
postfix/src/util/slmdb.h

index f5a5ff460d65afb017466eb66b4fb23397d8c987..3e6a0bce76025e637a62296437cad6bbd4cff078 100644 (file)
@@ -19023,3 +19023,9 @@ Apologies for any names omitted.
        numbers in lockfiles that can prevent automatic crash
        recovery.  Files: proto/LMDB_README.html, proto/postconf.proto,
        mantools/postlink, util/dict_lmdb.c.
+
+20131101
+
+       Cleanup: restore ability to build without LMDB support;
+       further slmdb API streamlining. Files: util/slmdb.[hc],
+       util/dict_lmdb.c.
index 47daf13c3f9cbd16d4b5be3f8981f416d10a89ab..f153424454e6683090bfae2bb812eecaaea1ce98 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20131031"
+#define MAIL_RELEASE_DATE      "20131101"
 #define MAIL_VERSION_NUMBER    "2.11"
 
 #ifdef SNAPSHOT
index f02f93267fb29ea10cd6a764d04416d65c1b6303..dcacd6efada48a2e6491ffdbabfe4abb368a359a 100644 (file)
@@ -99,6 +99,9 @@ typedef struct {
   * Each dict(3) API call is retried no more than a few times. For bulk-mode
   * transactions the number of retries is proportional to the size of the
   * address space.
+  * 
+  * We do not expise these details to the Postfix user interface. The purpose of
+  * Postfix is to solve problems, not punt them to the user.
   */
 #ifndef SSIZE_T_MAX                    /* The maximum map size */
 #define SSIZE_T_MAX __MAXINT__(ssize_t)        /* XXX Assumes two's complement */
@@ -471,7 +474,7 @@ static void dict_lmdb_close(DICT *dict)
     dict_free(dict);
 }
 
-/* dict_lmdb_longjmp - debug logging */
+/* dict_lmdb_longjmp - repeat bulk transaction */
 
 static void dict_lmdb_longjmp(void *context, int val)
 {
@@ -517,30 +520,38 @@ static void dict_lmdb_notify(void *context, int error_code,...)
 
 /* dict_lmdb_open - open LMDB data base */
 
-DICT   *dict_lmdb_open(const char *path, int dict_open_flags, int dict_flags)
+DICT   *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
 {
     DICT_LMDB *dict_lmdb;
     DICT   *dict;
     struct stat st;
     SLMDB   slmdb;
     char   *mdb_path;
-    int     mdb_open_flags, status;
+    int     mdb_flags, slmdb_flags, status;
     int     db_fd;
 
     mdb_path = concatenate(path, "." DICT_TYPE_LMDB, (char *) 0);
 
-    mdb_open_flags = MDB_NOSUBDIR | MDB_NOLOCK;
-    if (dict_open_flags == O_RDONLY)
-       mdb_open_flags |= MDB_RDONLY;
+    /*
+     * Impedance adapters.
+     */
+    mdb_flags = MDB_NOSUBDIR | MDB_NOLOCK;
+    if (open_flags == O_RDONLY)
+       mdb_flags |= MDB_RDONLY;
+
+    slmdb_flags = 0;
+    if (dict_flags & DICT_FLAG_BULK_UPDATE)
+       slmdb_flags |= SLMDB_FLAG_BULK;
 
     /*
      * Gracefully handle most database open errors.
      */
-    if ((status = slmdb_open(&slmdb, mdb_path, dict_open_flags, mdb_open_flags,
-                    dict_flags & DICT_FLAG_BULK_UPDATE, dict_lmdb_map_size,
-                          DICT_LMDB_SIZE_INCR, DICT_LMDB_SIZE_MAX)) != 0) {
-       dict = dict_surrogate(DICT_TYPE_LMDB, path, dict_open_flags,
-                             dict_flags, "open database %s: %m", mdb_path);
+    if ((status = slmdb_init(&slmdb, dict_lmdb_map_size, DICT_LMDB_SIZE_INCR,
+                            DICT_LMDB_SIZE_MAX)) != 0
+       || (status = slmdb_open(&slmdb, mdb_path, open_flags, mdb_flags,
+                               slmdb_flags)) != 0) {
+       dict = dict_surrogate(DICT_TYPE_LMDB, path, open_flags, dict_flags,
+                   "open database %s: %s", mdb_path, mdb_strerror(status));
        myfree(mdb_path);
        return (dict);
     }
index 25f147f8c8d35c26414d1a72b08fcf4b2a542089..c022d7870074d4d396e3661494b864adee5c4c65 100644 (file)
@@ -6,57 +6,61 @@
 /* SYNOPSIS
 /*     #include <slmdb.h>
 /*
-/*     size_t  slmdb_map_size;
+/*     int     slmdb_init(slmdb, curr_limit, size_incr, hard_limit)
+/*     SLMDB   *slmdb;
+/*     size_t  curr_limit;
+/*     int     size_incr;
+/*     size_t  hard_limit;
 /*
-/*     int     slmdb_open(slmdb, path, open_flags, lmdb_flags, bulk_mode,
-/*                             curr_limit, size_incr, hard_limit)
-/*     SLMDB *slmdb;
+/*     int     slmdb_open(slmdb, path, open_flags, lmdb_flags, slmdb_flags)
+/*     SLMDB   *slmdb;
 /*     const char *path;
 /*     int     open_flags;
 /*     int     lmdb_flags;
-/*     int     bulk_mode;
-/*     size_t  curr_limit;
-/*     int     size_incr;
-/*     size_t  hard_limit;
+/*     int     slmdb_flags;
 /*
 /*     int     slmdb_close(slmdb)
-/*     SLMDB *slmdb;
+/*     SLMDB   *slmdb;
 /*
 /*     int     slmdb_get(slmdb, mdb_key, mdb_value)
-/*     SLMDB *slmdb;
+/*     SLMDB   *slmdb;
 /*     MDB_val *mdb_key;
 /*     MDB_val *mdb_value;
 /*
 /*     int     slmdb_put(slmdb, mdb_key, mdb_value, flags)
-/*     SLMDB *slmdb;
+/*     SLMDB   *slmdb;
 /*     MDB_val *mdb_key;
 /*     MDB_val *mdb_value;
 /*     int     flags;
 /*
 /*     int     slmdb_del(slmdb, mdb_key)
-/*     SLMDB *slmdb;
+/*     SLMDB   *slmdb;
 /*     MDB_val *mdb_key;
 /*
 /*     int     slmdb_cursor_get(slmdb, mdb_key, mdb_value, op)
-/*     SLMDB *slmdb;
+/*     SLMDB   *slmdb;
 /*     MDB_val *mdb_key;
 /*     MDB_val *mdb_value;
 /*     MDB_cursor_op op;
 /* AUXILIARY FUNCTIONS
 /*     int     slmdb_fd(slmdb)
-/*     SLMDB *slmdb;
+/*     SLMDB   *slmdb;
 /*
 /*     size_t  slmdb_curr_limit(slmdb)
-/*     SLMDB *slmdb;
+/*     SLMDB   *slmdb;
 /*
-/*     int     slmdb_control(slmdb, id, ...)
-/*     SLMDB *slmdb;
-/*     int     id;
+/*     int     slmdb_control(slmdb, request, ...)
+/*     SLMDB   *slmdb;
+/*     int     request;
 /* DESCRIPTION
 /*     This module simplifies the LMDB API by hiding recoverable
 /*     errors from the application.  Details are given in the
 /*     section "ERROR RECOVERY".
 /*
+/*     slmdb_init() performs mandatory initialization before opening
+/*     an LMDB database. The result value is an LMDB status code
+/*     (zero in case of success).
+/*
 /*     slmdb_open() opens an LMDB database.  The result value is
 /*     an LMDB status code (zero in case of success).
 /*
 /*     recovery.  The result value is an LMDB status code (zero
 /*     in case of success).
 /*
-/*     slmdb_cursor_get() iterates over an LMDB database.  The
-/*     result value is an LMDB status code (zero in case of success).
+/*     slmdb_cursor_get() is an mdb_cursor_get() wrapper with
+/*     automatic error recovery.  The result value is an LMDB
+/*     status code (zero in case of success).
 /*
-/*     slmdb_fd() returns the file descriptor for an open LMDB
+/*     slmdb_fd() returns the file descriptor for the specified
 /*     database.  This may be used for file status queries or
 /*     application-controlled locking.
 /*
 /*     slmdb_curr_limit() returns the current database size limit
 /*     for the specified database.
 /*
-/*     slmdb_control() specifies optional features. The arguments
-/*     are a list of (name, value) pairs, terminated with
-/*     SLMDB_CTL_END.  The result is 0 in case of success, or -1
-/*     with errno indicating the nature of the problem. The following
-/*     text enumerates the symbolic request names and the types
-/*     of the corresponding additional arguments.
-/* .IP "SLMDB_CTL_LONGJMP_FN (void (*)(void *, int))
+/*     slmdb_control() specifies optional features. The result is
+/*     0 in case of success, or -1 with errno indicating the nature
+/*     of the problem.
+/*
+/* Arguments:
+/* .IP slmdb
+/*     Pointer to caller-provided storage.
+/* .IP curr_limit
+/*     The initial memory mapping size limit. This limit is
+/*     automatically increased when the database becomes full.
+/* .IP size_incr
+/*     An integer factor by which the memory mapping size limit
+/*     is increased when the database becomes full.
+/* .IP hard_limit
+/*     The upper bound for the memory mapping size limit.
+/* .IP path
+/*     LMDB database pathname.
+/* .IP open_flags
+/*     Flags that control file open operations. Do not specify
+/*     locking flags here.
+/* .IP lmdb_flags
+/*     Flags that control the LMDB environment.
+/* .IP slmdb_flags
+/*     Bit-wise OR of zero or more of the following:
+/* .RS
+/* .IP SLMDB_FLAG_BULK
+/*     Open the database for a "bulk" transaction that is not
+/*     committed until the database is closed.
+/* .RE
+/* .IP mdb_key
+/*     Pointer to caller-provided lookup key storage.
+/* .IP mdb_value
+/*     Pointer to caller-provided value storage.
+/* .IP op
+/*     LMDB cursor operation.
+/* .IP request
+/*     The start of a list of (name, value) pairs, terminated with
+/*     SLMDB_CTL_END.  The following text enumerates the symbolic
+/*     request names and the corresponding value types.
+/* .RS .IP "SLMDB_CTL_LONGJMP_FN (void (*)(void *, int))
 /*     Application long-jump call-back function pointer. The
 /*     function must not return and is called to repeat a failed
-/*     bulk-mode transaction from the start. The arguments are
-/*     the application context and the setjmp() or sigsetjmp()
-/*     result value.
+/*     bulk-mode transaction from the start. The arguments are the
+/*     application context and the setjmp() or sigsetjmp() result
+/*     value.
 /* .IP "SLMDB_CTL_NOTIFY_FN (void (*)(void *, int, ...))"
 /*     Application notification call-back function pointer. The
-/*     function is called after succesful error recovery with as
+/*     function is called after succesful error recovery with
 /*     arguments the application context, the MDB error code, and
-/*     additional arguments that depend on the error code.
-/*     Details are given in the section "ERROR RECOVERY".
+/*     additional arguments that depend on the error code.  Details
+/*     are given in the section "ERROR RECOVERY".
 /* .IP "SLMDB_CTL_CONTEXT (void *)"
 /*     Application context that is passed in application notification
 /*     and long-jump call-back function calls.
 /* .IP "SLMDB_CTL_BULK_RETRY_LIMIT (int)"
 /*     How many times to recover from a bulk-mode transaction
 /*     before giving up.
+/* .RE
 /* ERROR RECOVERY
 /* .ad
 /* .fi
 /*     This module automatically repeats failed requests after
-/*     recoverable errors, up to limits specified with slmdb_control().
+/*     recoverable errors, up to the limits specified with
+/*     slmdb_control().
 /*
 /*     Recoverable errors are reported through an optional
 /*     notification function specified with slmdb_control().  With
 /*     Yorktown Heights, NY 10598, USA
 /*--*/
 
+#ifdef HAS_LMDB
+
 /* System library. */
 
 #include <sys/stat.h>
@@ -226,20 +268,17 @@ static int slmdb_prepare(SLMDB *slmdb)
      * - With O_TRUNC we make a "drop" request before updating the database.
      * 
      * - With a bulk-mode transaction we commit when the database is closed.
-     * 
-     * XXX If we want to make the slmdb API suitable for general use, then the
-     * bulk/non-bulk handling must be generalized.
      */
     if (slmdb->open_flags & O_TRUNC) {
        if ((status = mdb_drop(slmdb->txn, slmdb->dbi, 0)) != 0)
            return (status);
-       if ((slmdb->bulk_mode) == 0) {
+       if ((slmdb->slmdb_flags & SLMDB_FLAG_BULK) == 0) {
            if ((status = mdb_txn_commit(slmdb->txn)))
                return (status);
            slmdb->txn = 0;
        }
     } else if ((slmdb->lmdb_flags & MDB_RDONLY) != 0
-              || (slmdb->bulk_mode) == 0) {
+              || (slmdb->slmdb_flags & SLMDB_FLAG_BULK) == 0) {
        mdb_txn_abort(slmdb->txn);
        slmdb->txn = 0;
     }
@@ -267,9 +306,6 @@ static int slmdb_recover(SLMDB *slmdb, int status)
      * 
      * slmdb->txn must be either null (non-bulk transaction error), or an
      * aborted bulk-mode transaction.
-     * 
-     * XXX If we want to make the slmdb API suitable for general use, then the
-     * bulk/non-bulk handling must be generalized.
      */
     switch (status) {
 
@@ -583,11 +619,27 @@ int     slmdb_close(SLMDB *slmdb)
     SLMDB_API_RETURN(slmdb, status);
 }
 
+/* slmdb_init - mandatory initialization */
+
+int     slmdb_init(SLMDB *slmdb, size_t curr_limit, int size_incr,
+                          size_t hard_limit)
+{
+
+    /*
+     * This is a separate operation to keep the slmdb_open() API simple.
+     * Don't allocate resources here. Just store control information,
+     */
+    slmdb->curr_limit = curr_limit;
+    slmdb->size_incr = size_incr;
+    slmdb->hard_limit = hard_limit;
+
+    return (MDB_SUCCESS);
+}
+
 /* slmdb_open - open wrapped LMDB database */
 
 int     slmdb_open(SLMDB *slmdb, const char *path, int open_flags,
-                          int lmdb_flags, int bulk_mode, size_t curr_limit,
-                          int size_incr, size_t hard_limit)
+                          int lmdb_flags, int slmdb_flags)
 {
     struct stat st;
     MDB_env *env;
@@ -604,20 +656,21 @@ int     slmdb_open(SLMDB *slmdb, const char *path, int open_flags,
 
     /*
      * Make sure that the memory map has room to store and commit an initial
-     * "drop" transaction. We have no way to recover from errors before the
-     * first application-level request.
+     * "drop" transaction as well as fixed database metadata. We have no way
+     * to recover from errors before the first application-level I/O request.
      */
-#define SLMDB_FUDGE      8192
-
-    if (curr_limit < SLMDB_FUDGE)
-       curr_limit = SLMDB_FUDGE;
-    if (stat(path, &st) == 0 && st.st_size > curr_limit - SLMDB_FUDGE) {
-       if (st.st_size > hard_limit)
-           hard_limit = st.st_size;
-       if (st.st_size < hard_limit - SLMDB_FUDGE)
-           curr_limit = st.st_size + SLMDB_FUDGE;
+#define SLMDB_FUDGE      10240
+
+    if (slmdb->curr_limit < SLMDB_FUDGE)
+       slmdb->curr_limit = SLMDB_FUDGE;
+    if (stat(path, &st) == 0
+       && st.st_size > slmdb->curr_limit - SLMDB_FUDGE) {
+       if (st.st_size > slmdb->hard_limit)
+           slmdb->hard_limit = st.st_size;
+       if (st.st_size < slmdb->hard_limit - SLMDB_FUDGE)
+           slmdb->curr_limit = st.st_size + SLMDB_FUDGE;
        else
-           curr_limit = hard_limit;
+           slmdb->curr_limit = slmdb->hard_limit;
     }
 
     /*
@@ -625,7 +678,7 @@ int     slmdb_open(SLMDB *slmdb, const char *path, int open_flags,
      * an LMDB environment, we usually don't need to do anything else with
      * the txn. It is currently used for truncate and for bulk transactions.
      */
-    if ((status = mdb_env_set_mapsize(env, curr_limit)) != 0
+    if ((status = mdb_env_set_mapsize(env, slmdb->curr_limit)) != 0
        || (status = mdb_env_open(env, path, lmdb_flags, 0644)) != 0
        || (status = mdb_txn_begin(env, (MDB_txn *) 0,
                                   lmdb_flags & MDB_RDONLY, &txn)) != 0
@@ -640,10 +693,7 @@ int     slmdb_open(SLMDB *slmdb, const char *path, int open_flags,
      */
     slmdb->open_flags = open_flags;
     slmdb->lmdb_flags = lmdb_flags;
-    slmdb->bulk_mode = bulk_mode;
-    slmdb->curr_limit = curr_limit;
-    slmdb->size_incr = size_incr;
-    slmdb->hard_limit = hard_limit;
+    slmdb->slmdb_flags = slmdb_flags;
     slmdb->env = env;
     slmdb->dbi = dbi;
     slmdb->db_fd = db_fd;
@@ -662,3 +712,5 @@ int     slmdb_open(SLMDB *slmdb, const char *path, int open_flags,
 
     return (status);
 }
+
+#endif
index 1902c11632f7ebaa0278c7842d8a7f9e2435de6b..5a5e8021fd8cf94bba6e5509a7db55067801b647 100644 (file)
 #endif
 
 typedef struct {
-    int     open_flags;                        /* open() flags */
-    int     lmdb_flags;                        /* LMDB-specific flags */
-    int     bulk_mode;                 /* bulk-mode flag */
     size_t  curr_limit;                        /* database soft size limit */
-    int     size_incr;                 /* database growth factor */
+    int     size_incr;                 /* database expansion factor */
     size_t  hard_limit;                        /* database hard size limit */
+    int     open_flags;                        /* open() flags */
+    int     lmdb_flags;                        /* LMDB-specific flags */
+    int     slmdb_flags;               /* bulk-mode flag */
     MDB_env *env;                      /* database environment */
     MDB_dbi dbi;                       /* database instance */
     MDB_txn *txn;                      /* bulk transaction */
     int     db_fd;                     /* database file handle */
     MDB_cursor *cursor;                        /* iterator */
-    void    (*longjmp_fn) (void *, int);       /* exception handling */
+    void    (*longjmp_fn) (void *, int);/* exception handling */
     void    (*notify_fn) (void *, int,...);    /* workaround notification */
     void   *cb_context;                        /* call-back context */
     int     api_retry_count;           /* slmdb(3) API call retry count */
@@ -53,12 +53,15 @@ typedef struct {
     int     bulk_retry_limit;          /* bulk_mode retry limit */
 } SLMDB;
 
-extern int slmdb_open(SLMDB *, const char *, int, int, int, size_t, int, size_t);
+#define SLMDB_FLAG_BULK                (1 << 0)
+
+extern int slmdb_init(SLMDB *, size_t, int, size_t);
+extern int slmdb_open(SLMDB *, const char *, int, int, int);
 extern int slmdb_get(SLMDB *, MDB_val *, MDB_val *);
 extern int slmdb_put(SLMDB *, MDB_val *, MDB_val *, int);
 extern int slmdb_del(SLMDB *, MDB_val *);
 extern int slmdb_cursor_get(SLMDB *, MDB_val *, MDB_val *, MDB_cursor_op);
-extern int slmdb_control(SLMDB *, int, ...);
+extern int slmdb_control(SLMDB *, int,...);
 extern int slmdb_close(SLMDB *);
 
 #define slmdb_fd(slmdb)                        ((slmdb)->db_fd)
@@ -72,8 +75,8 @@ extern int slmdb_close(SLMDB *);
 #define SLMDB_CTL_API_RETRY_LIMIT      5       /* per slmdb(3) API call */
 #define SLMDB_CTL_BULK_RETRY_LIMIT     6       /* per bulk update */
 
-typedef void (*SLMDB_NOTIFY_FN)(void *, int, ...);
-typedef void (*SLMDB_LONGJMP_FN)(void *, int);
+typedef void (*SLMDB_NOTIFY_FN) (void *, int,...);
+typedef void (*SLMDB_LONGJMP_FN) (void *, int);
 
 /* LICENSE
 /* .ad