Commit e70212c1 e70212c14a55b8e5e55eb3ad44513fd402553026 by Sergey Poznyakoff

Fix locking of Berkeley databases.

* include/mailutils/locker.h (mu_locker_lock_mode): New proto.
* libmailutils/base/locker.c (_mu_locker_lock): Rename to
mu_locker_lock_mode.  All callers updated.
* libmu_dbm/berkeley.c (bdb_file) <locker>: New member.
(do_bdb_open): New function.  Lock the database file before opening it.
Drop support for version 2.
(_bdb_open): Rewrite as a wrapper over do_bdb_open.
* mu/dbm.c (dbm_doc): Document the "dump" subcommand.

* NEWS: Version 2.99.96
* configure.ac: Likewise.
1 parent fb53814d
1 GNU mailutils NEWS -- history of user-visible changes. 2011-12-31 1 GNU mailutils NEWS -- history of user-visible changes. 2012-02-26
2 Copyright (C) 2002-2012 Free Software Foundation, Inc. 2 Copyright (C) 2002-2012 Free Software Foundation, Inc.
3 See the end of file for copying conditions. 3 See the end of file for copying conditions.
4 4
5 Please send mailutils bug reports to <bug-mailutils@gnu.org>. 5 Please send mailutils bug reports to <bug-mailutils@gnu.org>.
6 6
7 7
8 Version 2.99.95 (Git) 8 Version 2.99.96 (Git)
9 9
10 This version is a major rewrite of GNU Mailutils. Quite a few parts 10 This version is a major rewrite of GNU Mailutils. Quite a few parts
11 of the basic framework were rewritten from scratch, while some others 11 of the basic framework were rewritten from scratch, while some others
......
...@@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License along ...@@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License along
16 dnl with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. 16 dnl with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
17 17
18 AC_PREREQ(2.63) 18 AC_PREREQ(2.63)
19 AC_INIT([GNU Mailutils], [2.99.95], [bug-mailutils@gnu.org], [mailutils]) 19 AC_INIT([GNU Mailutils], [2.99.96], [bug-mailutils@gnu.org], [mailutils])
20 AC_CONFIG_SRCDIR([libmailutils/mailbox/mailbox.c]) 20 AC_CONFIG_SRCDIR([libmailutils/mailbox/mailbox.c])
21 AC_CONFIG_AUX_DIR([build-aux]) 21 AC_CONFIG_AUX_DIR([build-aux])
22 AM_INIT_AUTOMAKE([gnits 1.11 dist-bzip2 dist-xz std-options silent-rules]) 22 AM_INIT_AUTOMAKE([gnits 1.11 dist-bzip2 dist-xz std-options silent-rules])
......
...@@ -133,6 +133,7 @@ enum mu_locker_mode ...@@ -133,6 +133,7 @@ enum mu_locker_mode
133 locking otherwise */ 133 locking otherwise */
134 }; 134 };
135 135
136 extern int mu_locker_lock_mode (mu_locker_t, enum mu_locker_mode);
136 extern int mu_locker_lock (mu_locker_t); 137 extern int mu_locker_lock (mu_locker_t);
137 extern int mu_locker_touchlock (mu_locker_t); 138 extern int mu_locker_touchlock (mu_locker_t);
138 extern int mu_locker_unlock (mu_locker_t); 139 extern int mu_locker_unlock (mu_locker_t);
......
...@@ -547,7 +547,7 @@ mu_locker_destroy (mu_locker_t *plocker) ...@@ -547,7 +547,7 @@ mu_locker_destroy (mu_locker_t *plocker)
547 } 547 }
548 548
549 int 549 int
550 _mu_locker_lock (mu_locker_t lock, enum mu_locker_mode mode) 550 mu_locker_lock_mode (mu_locker_t lock, enum mu_locker_mode mode)
551 { 551 {
552 int rc; 552 int rc;
553 unsigned type; 553 unsigned type;
...@@ -598,7 +598,7 @@ _mu_locker_lock (mu_locker_t lock, enum mu_locker_mode mode) ...@@ -598,7 +598,7 @@ _mu_locker_lock (mu_locker_t lock, enum mu_locker_mode mode)
598 int 598 int
599 mu_locker_lock (mu_locker_t lock) 599 mu_locker_lock (mu_locker_t lock)
600 { 600 {
601 return _mu_locker_lock (lock, mu_lck_exc); 601 return mu_locker_lock_mode (lock, mu_lck_exc);
602 } 602 }
603 603
604 int 604 int
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
26 #include <mailutils/errno.h> 26 #include <mailutils/errno.h>
27 #include <mailutils/error.h> 27 #include <mailutils/error.h>
28 #include <mailutils/stream.h> 28 #include <mailutils/stream.h>
29 #include <mailutils/locker.h>
29 #include "mudbm.h" 30 #include "mudbm.h"
30 31
31 #if defined(WITH_BDB) 32 #if defined(WITH_BDB)
...@@ -35,6 +36,7 @@ struct bdb_file ...@@ -35,6 +36,7 @@ struct bdb_file
35 { 36 {
36 DB *db; 37 DB *db;
37 DBC *dbc; 38 DBC *dbc;
39 mu_locker_t locker;
38 }; 40 };
39 41
40 static int 42 static int
...@@ -59,56 +61,70 @@ _bdb_get_fd (mu_dbm_file_t db, int *pag, int *dir) ...@@ -59,56 +61,70 @@ _bdb_get_fd (mu_dbm_file_t db, int *pag, int *dir)
59 } 61 }
60 62
61 static int 63 static int
62 _bdb_open (mu_dbm_file_t mdb, int flags, int mode) 64 do_bdb_open (mu_dbm_file_t mdb, int flags, int mode)
63 { 65 {
64 struct bdb_file *bdb_file; 66 struct bdb_file *bdb_file = mdb->db_descr;
65 int f, rc; 67 int f, rc, locker_flags;
66 DB *db; 68 enum mu_locker_mode locker_mode;
67 69
68 switch (flags) 70 switch (flags)
69 { 71 {
70 case MU_STREAM_CREAT: 72 case MU_STREAM_CREAT:
71 f = DB_CREATE|DB_TRUNCATE; 73 f = DB_CREATE|DB_TRUNCATE;
74 locker_mode = mu_lck_exc;
72 break; 75 break;
73 76
74 case MU_STREAM_READ: 77 case MU_STREAM_READ:
75 f = DB_RDONLY; 78 f = DB_RDONLY;
79 locker_mode = mu_lck_shr;
76 break; 80 break;
77 81
78 case MU_STREAM_RDWR: 82 case MU_STREAM_RDWR:
79 f = DB_CREATE; 83 f = DB_CREATE;
84 locker_mode = mu_lck_exc;
80 break; 85 break;
81 86
82 default: 87 default:
83 return EINVAL; 88 return EINVAL;
84 } 89 }
85 90
86 #if WITH_BDB == 2 91 #ifdef DB_FCNTL_LOCKING
87 rc = db_open (db->db_name, DB_HASH, f, mode, NULL, NULL, &db); 92 f |= DB_FCNTL_LOCKING;
93 locker_flags = MU_LOCKER_KERNEL;
88 #else 94 #else
89 rc = db_create (&db, NULL, 0); 95 locker_flags = 0;
90 if (rc != 0 || db == NULL)
91 return MU_ERR_FAILURE;
92 # if DB_VERSION_MAJOR == 3
93 rc = db->open (db, mdb->db_name, NULL, DB_HASH, f, mode);
94 # else
95 rc = db->open (db, NULL, mdb->db_name, NULL, DB_HASH, f, mode);
96 # endif
97 #endif 96 #endif
98 97 rc = mu_locker_create (&bdb_file->locker, mdb->db_name,
98 locker_flags|MU_LOCKER_RETRY);
99 if (rc) 99 if (rc)
100 return MU_ERR_FAILURE; 100 return rc;
101 101
102 bdb_file = malloc (sizeof *bdb_file); 102 rc = mu_locker_lock_mode (bdb_file->locker, locker_mode);
103 if (!bdb_file) 103 switch (rc)
104 { 104 {
105 db->close (db, 0); 105 case 0:
106 return ENOMEM; 106 break;
107
108 case EACCES:
109 mu_locker_destroy (&bdb_file->locker);
110 break;
111
112 default:
113 return rc;
107 } 114 }
108 bdb_file->db = db;
109 bdb_file->dbc = NULL;
110 115
111 mdb->db_descr = bdb_file; 116 rc = db_create (&bdb_file->db, NULL, 0);
117 if (rc != 0 || bdb_file->db == NULL)
118 return MU_ERR_FAILURE;
119 #if DB_VERSION_MAJOR == 3
120 rc = bdb_file->db->open (bdb_file->db, mdb->db_name, NULL, DB_HASH, f, mode);
121 #else
122 rc = bdb_file->db->open (bdb_file->db, NULL, mdb->db_name, NULL, DB_HASH,
123 f, mode);
124 #endif
125
126 if (rc)
127 return MU_ERR_FAILURE;
112 128
113 return 0; 129 return 0;
114 } 130 }
...@@ -119,7 +135,13 @@ _bdb_close (mu_dbm_file_t db) ...@@ -119,7 +135,13 @@ _bdb_close (mu_dbm_file_t db)
119 if (db->db_descr) 135 if (db->db_descr)
120 { 136 {
121 struct bdb_file *bdb_file = db->db_descr; 137 struct bdb_file *bdb_file = db->db_descr;
138 if (bdb_file->db)
122 bdb_file->db->close (bdb_file->db, 0); 139 bdb_file->db->close (bdb_file->db, 0);
140 if (bdb_file->locker)
141 {
142 mu_locker_unlock (bdb_file->locker);
143 mu_locker_destroy (&bdb_file->locker);
144 }
123 free (bdb_file); 145 free (bdb_file);
124 db->db_descr = NULL; 146 db->db_descr = NULL;
125 } 147 }
...@@ -127,6 +149,23 @@ _bdb_close (mu_dbm_file_t db) ...@@ -127,6 +149,23 @@ _bdb_close (mu_dbm_file_t db)
127 } 149 }
128 150
129 static int 151 static int
152 _bdb_open (mu_dbm_file_t mdb, int flags, int mode)
153 {
154 int rc;
155 struct bdb_file *bdb_file;
156
157 bdb_file = calloc (1, sizeof *bdb_file);
158 if (!bdb_file)
159 return ENOMEM;
160
161 mdb->db_descr = bdb_file;
162 rc = do_bdb_open (mdb, flags, mode);
163 if (rc)
164 _bdb_close (mdb);
165 return rc;
166 }
167
168 static int
130 _bdb_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key, 169 _bdb_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
131 struct mu_dbm_datum *ret) 170 struct mu_dbm_datum *ret)
132 { 171 {
......
...@@ -35,6 +35,7 @@ static char dbm_doc[] = N_("mu dbm - DBM management tool\n" ...@@ -35,6 +35,7 @@ static char dbm_doc[] = N_("mu dbm - DBM management tool\n"
35 "Valid COMMANDs are:\n" 35 "Valid COMMANDs are:\n"
36 "\n" 36 "\n"
37 " create or load - create the database\n" 37 " create or load - create the database\n"
38 " dump - dump the database\n"
38 " list - list contents of the database\n" 39 " list - list contents of the database\n"
39 " delete - delete specified keys from the database\n" 40 " delete - delete specified keys from the database\n"
40 " add - add records to the database\n" 41 " add - add records to the database\n"
......