--- a/src.lock_maildirsize Sun Feb 20 23:59:48 2011 +0100
+++ b/src.lock_maildirsize Wed Feb 23 00:53:41 2011 +0100
@@ -1,18 +1,18 @@
# HG changeset patch
-# Parent 5037ac63d7aece4b5e96e26bace1ab4b7e791804
+# Parent d54ee7005f7f7b5970ce45caf7487a9fd929e55f
-diff -r 5037ac63d7ae Local/Makefile
---- a/Local/Makefile Sat Feb 19 13:42:16 2011 +0100
-+++ b/Local/Makefile Sun Feb 20 23:37:25 2011 +0100
+diff -r d54ee7005f7f Local/Makefile
+--- a/Local/Makefile Mon Feb 21 22:52:42 2011 +0100
++++ b/Local/Makefile Wed Feb 23 00:53:29 2011 +0100
@@ -1,4 +1,5 @@
# $Cambridge: exim/src/src/EDITME,v 1.27 2010/06/12 15:21:25 jetmore Exp $
+EXTRALIBS_EXIM=-lrt
##################################################
# The Exim mail transport agent #
-diff -r 5037ac63d7ae src/transports/appendfile.c
---- a/src/transports/appendfile.c Sat Feb 19 13:42:16 2011 +0100
-+++ b/src/transports/appendfile.c Sun Feb 20 23:37:25 2011 +0100
+diff -r d54ee7005f7f src/transports/appendfile.c
+--- a/src/transports/appendfile.c Mon Feb 21 22:52:42 2011 +0100
++++ b/src/transports/appendfile.c Wed Feb 23 00:53:29 2011 +0100
@@ -13,6 +13,7 @@
#ifdef SUPPORT_MAILDIR
@@ -21,7 +21,38 @@
#endif
-@@ -278,8 +279,8 @@
+@@ -239,6 +240,30 @@
+ TRUE /* quota_is_inclusive */
+ };
+
++void hs12_lock(int fd, int type, const char* msg)
++{
++ struct timespec t0, t1;
++ clock_gettime(CLOCK_REALTIME, &t0);
++ const char *ltype =
++ type == F_UNLCK ? "UNLOCK"
++ : type == F_RDLCK ? "READ LOCK"
++ : "WRITE LOCK";
++
++ DEBUG(D_transport) debug_printf("%s: %s\n", ltype, msg);
++
++
++ (void)apply_lock(fd, type, 1, 120, 0, 0);
++ if (type == F_UNLCK) return;
++
++ clock_gettime(CLOCK_REALTIME, &t1);
++ t1.tv_sec -= t0.tv_sec;
++ t1.tv_nsec -= t0.tv_nsec;
++ if (t1.tv_nsec < 0) { t1.tv_sec--; t1.tv_nsec *= -1; }
++ DEBUG(D_transport)
++ debug_printf("%s: %s was waiting for %d.%09d seconds\n",
++ ltype, msg, t1.tv_sec, t1.tv_nsec);
++ return;
++}
+
+
+ /*************************************************
+@@ -278,8 +303,8 @@
gid = gid;
if (ob->expand_maildir_use_size_file)
@@ -32,7 +63,7 @@
/* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size,
mailbox_filecount */
-@@ -841,7 +842,7 @@
+@@ -841,7 +866,7 @@
sigalrm_seen set if there has been a timeout
*/
@@ -41,7 +72,7 @@
apply_lock(int fd, int fcntltype, BOOL dofcntl, int fcntltime, BOOL doflock,
int flocktime)
{
-@@ -887,7 +888,6 @@
+@@ -887,7 +912,6 @@
@@ -49,14 +80,11 @@
#ifdef SUPPORT_MBX
/*************************************************
* Copy message into MBX mailbox *
-@@ -2416,18 +2416,32 @@
+@@ -2416,18 +2440,19 @@
{
off_t size;
int filecount;
+ uschar *excuse;
-+
-+ struct timespec t0, t1;
-+ clock_gettime(CLOCK_REALTIME, &t0);
maildirsize_fd = maildir_ensure_sizefile(check_path, ob, regex, dir_regex,
- &size, &filecount);
@@ -67,34 +95,24 @@
addr->basic_errno = errno;
- addr->message = string_sprintf("while opening or reading "
- "%s/maildirsize", check_path);
-+ //addr->message = string_sprintf("%s", excuse);
+ addr->message = excuse;
return FALSE;
}
+
-+ clock_gettime(CLOCK_REALTIME, &t1);
-+ t1.tv_sec -= t0.tv_sec;
-+ t1.tv_nsec -= t0.tv_nsec;
-+ if (t1.tv_nsec < 0) { t1.tv_sec--; t1.tv_nsec *= -1; }
-+ DEBUG(D_transport) {
-+ if (t1.tv_sec >= 1) debug_printf("%s/maildirsize was locked for %d.09ld seconds\n",
-+ check_path, t1.tv_sec, t1.tv_nsec);
-+ }
-+
if (mailbox_size < 0) mailbox_size = size;
if (mailbox_filecount < 0) mailbox_filecount = filecount;
}
-@@ -3125,6 +3139,8 @@
+@@ -3125,6 +3150,8 @@
uschar *renamename = newname;
fd = -1;
-+ if (lockfd >= 0) (void)apply_lock(lockfd, F_RDLCK, 1, 120, 0, 0); // hs12
++ if (lockfd >= 0) hs12_lock(lockfd, F_RDLCK, "delivery");
+
DEBUG(D_transport) debug_printf("renaming temporary file\n");
/* If there is no rename name set, we are in a non-maildir, non-mailstore
-@@ -3245,6 +3261,7 @@
+@@ -3245,6 +3272,7 @@
filename = dataname = NULL; /* Prevents attempt to unlink at end */
}
} /* maildir or mailstore */
@@ -102,21 +120,21 @@
} /* successful write + close */
} /* isdirectory */
} /* write success */
-@@ -3280,6 +3297,11 @@
+@@ -3280,6 +3308,11 @@
detected, in order to get the file closed and the lock file tidied away. */
RETURN:
+if (lockfd >= 0)
+ {
-+ (void)apply_lock(lockfd, F_UNLCK, 1, 120, 0, 0); // hs12
++ hs12_lock(lockfd, F_UNLCK, "done delivery");
+ (void)close(lockfd);
+ }
#ifdef SUPPORT_MBX
if (mbx_lockfd >= 0)
-diff -r 5037ac63d7ae src/transports/appendfile.h
---- a/src/transports/appendfile.h Sat Feb 19 13:42:16 2011 +0100
-+++ b/src/transports/appendfile.h Sun Feb 20 23:37:25 2011 +0100
+diff -r d54ee7005f7f src/transports/appendfile.h
+--- a/src/transports/appendfile.h Mon Feb 21 22:52:42 2011 +0100
++++ b/src/transports/appendfile.h Wed Feb 23 00:53:29 2011 +0100
@@ -95,5 +95,8 @@
/* Function that is shared with tf_maildir.c */
@@ -126,9 +144,9 @@
+
/* End of transports/appendfile.h */
-diff -r 5037ac63d7ae src/transports/tf_maildir.c
---- a/src/transports/tf_maildir.c Sat Feb 19 13:42:16 2011 +0100
-+++ b/src/transports/tf_maildir.c Sun Feb 20 23:37:25 2011 +0100
+diff -r d54ee7005f7f src/transports/tf_maildir.c
+--- a/src/transports/tf_maildir.c Mon Feb 21 22:52:42 2011 +0100
++++ b/src/transports/tf_maildir.c Wed Feb 23 00:53:29 2011 +0100
@@ -367,13 +367,16 @@
Returns: >=0 a file descriptor for an open maildirsize file
@@ -147,7 +165,7 @@
{
int count, fd;
off_t cached_quota = 0;
-@@ -381,25 +384,80 @@
+@@ -381,25 +384,48 @@
int filecount = 0;
int linecount = 0;
off_t size = 0;
@@ -157,69 +175,36 @@
uschar *ptr = buffer;
uschar *endptr;
+-/* Try a few times to open or create the file, in case another process is doing
+-the same thing. */
+filename = string_sprintf("%s/maildirsize", path);
+lockname = string_sprintf("%s.lock", filename);
+hitchname = string_sprintf( "%s.%s.%08x.%08x", lockname, primary_hostname,
+ (unsigned int)(time(NULL)), (unsigned int)getpid());
-+
+
+-filename = string_sprintf("%s/maildirsize", path);
+/* Try to create a lock file. Here we should copy the loop from appendfile.c,
+since our approach is quite simplified */
+lockfd = Uopen(lockname, O_CREAT|O_RDWR, ob->mode ? ob->mode : 0600);
+if (lockfd < 0)
-+ {
-+ if (errno != ENOENT)
+ {
+ *excuse = string_sprintf("open %s", lockname);
+ return -1;
+ }
+
-+ lockfd = Uopen(hitchname, O_WRONLY|O_CREAT|O_EXCL, ob->mode ? ob->mode : 0600);
-+ if (lockfd < 0)
-+ {
-+ *excuse = string_sprintf("open %s", hitchname);
-+ return -1;
-+ }
-+ if (link(hitchname, lockname) < 0)
-+ {
-+ int save_errno = errno;
-+ (void)unlink(hitchname);
-+ errno = save_errno;
-+ if (errno != EEXIST)
-+ {
-+ *excuse = string_sprintf("link %s -> %s", hitchname, lockname);
-+ return -1;
-+ }
-+ (void)close(lockfd);
-+ lockfd = Uopen(lockname, O_WRONLY, ob->mode ? ob->mode : 0600);
-+ if (lockfd < 0)
-+ {
-+ *excuse = string_sprintf("open %s", lockname);
-+ return -1;
-+ }
-+ }
-+ (void)unlink(hitchname);
-+ }
-+
-+
+/* Before doing anything here we try to open and lock the maildirsize.lock
+file. This should prevent/avoid races and parallel recalculations. We
+need to do this on an extra lockfile, since the maildirsize file itself
+gets renamed during the recalculation. */
+
-+if (lockfd >= 0)
-+(void)apply_lock(lockfd, F_WRLCK, 1, 120, 0, 0); // hs12
++hs12_lock(lockfd, F_WRLCK, "checking");
+if (sigalrm_seen)
+ {
+ *excuse = string_sprintf("timeout locking %s", lockname);
+ return -1;
+ }
-+DEBUG(D_transport) debug_printf("locked (WR) %s\n", lockname);
+
- /* Try a few times to open or create the file, in case another process is doing
- the same thing. */
--filename = string_sprintf("%s/maildirsize", path);
--
DEBUG(D_transport) debug_printf("looking for maildirsize in %s\n", path);
fd = Uopen(filename, O_RDWR|O_APPEND, ob->mode ? ob->mode : 0600);
-if (fd < 0)
@@ -231,24 +216,64 @@
goto RECALCULATE;
- }
+}
++(void)lseek(fd, 0, SEEK_SET);
++
/* The file has been successfully opened. Check that the cached quota value is
still correct, and that the size of the file is still small enough. If so,
-@@ -588,8 +646,10 @@
+@@ -520,16 +546,12 @@
+ }
}
}
+-
+-
+-/* If *endptr is not zero, there was a syntax error in the file. */
+-
+-else
++else /* If *endptr is not zero, there was a syntax error in the file. */
+ {
++ time_t old_latest, new_latest;
+ int len;
+- time_t old_latest, new_latest;
+ uschar *tempname;
+- struct timeval tv;
++ struct timeval tv;
-+ DEBUG(D_transport) debug_printf("releasing lock\n");
-+ (void)apply_lock(lockfd, F_UNLCK, 1, 120, 0, 0);
+ DEBUG(D_transport)
+ {
+@@ -549,6 +571,13 @@
+
+ RECALCULATE:
+
++ //hs12_lock(lockfd, F_WRLCK, "recalc");
++ if (sigalrm_seen)
++ {
++ *excuse = "timeout while locking for recalc";
++ return -1;
++ }
++
+ if (fd >= 0) (void)close(fd);
+ old_latest = 0;
+ filecount = 0;
+@@ -586,10 +615,14 @@
+ (void)close(fd);
+ fd = -2;
+ }
++ hs12_lock(lockfd, F_UNLCK, "done recalc");
+ }
+
++ hs12_lock(lockfd, F_UNLCK, "done check");
++
++
+
/* Return the sizes and the file descriptor, if any */
-
DEBUG(D_transport) debug_printf("returning maildir size=" OFF_T_FMT
" filecount=%d\n", size, filecount);
*returned_size = size;
-diff -r 5037ac63d7ae src/transports/tf_maildir.h
---- a/src/transports/tf_maildir.h Sat Feb 19 13:42:16 2011 +0100
-+++ b/src/transports/tf_maildir.h Sun Feb 20 23:37:25 2011 +0100
+diff -r d54ee7005f7f src/transports/tf_maildir.h
+--- a/src/transports/tf_maildir.h Mon Feb 21 22:52:42 2011 +0100
++++ b/src/transports/tf_maildir.h Wed Feb 23 00:53:29 2011 +0100
@@ -16,7 +16,7 @@
uschar *);
extern int maildir_ensure_sizefile(uschar *,