statuscache and fatal

2009-11-04 Thread Cyril Servant
Hello,

I wonder why is a fatal function called when the statuscache backend
can't be opened. This makes the process terminate (then fork again,
then terminate, then...). This is not logical, because statuscache
is... a cache ! Cyrus should work fine without (and actually, it does,
with the patch attached).

As we use an sql backend for statuscache, when the sql server is not
available, we prefer that cyrus-imapd works without cache than a total
breakdown.

-- 
Cyril
--- imap/statuscache_db.c	30 Mar 2009 07:52:37 -	1.1.1.2
+++ imap/statuscache_db.c	4 Nov 2009 10:17:11 -
@@ -94,7 +94,7 @@
 if (ret != 0) {
 	syslog(LOG_ERR, DBERROR: opening %s: %s, fname,
 	   cyrusdb_strerror(ret));
+	syslog(LOG_ERR, statuscache in degraded mode);
- 	fatal(can't read statuscache file, EC_TEMPFAIL);
 }
 
 if (tofree) free(tofree);


statuscache

2008-01-17 Thread Ken Murchison
Looking (again) at integrating this.  Two observations, the first 
somewhat minor, and the second somewhat major:


- statuscache v.2 doesn't have support for HIGHESTMODSEQ.  This is 
trivial to add to a v.3.


- statuscache v.2 stores statuscache_data as a binary blob, which is 
platform dependent (byte-order  word size).  This make statuscache.db 
non-portable.  I believe that this might be the first cyrusdb that would 
be non-portable.  Does anybody care?


--
Kenneth Murchison
Systems Programmer
Project Cyrus Developer/Maintainer
Carnegie Mellon University


Re: statuscache

2008-01-17 Thread Ken Murchison

Bron Gondwana wrote:

On Thu, Jan 17, 2008 at 02:47:27PM -0500, Ken Murchison wrote:
Looking (again) at integrating this.  Two observations, the first somewhat 
minor, and the second somewhat major:


- statuscache v.2 doesn't have support for HIGHESTMODSEQ.  This is trivial 
to add to a v.3.


Yeah, shouldn't be a big problem.

- statuscache v.2 stores statuscache_data as a binary blob, which is 
platform dependent (byte-order  word size).  This make statuscache.db 
non-portable.  I believe that this might be the first cyrusdb that would be 
non-portable.  Does anybody care?


Hmm - it would be a very minor cost to make it platform independent.  On
the flip side, it's not supposed to persist over shutdowns of Cyrus
anyway.

Still, I would vote for fixing that too - might as well keep the
platform safeness.  Processor time is cheap compared to disk IO
at least in our setup.


The only tricky part is going to be upgrading from v.2 to v.3.  If its 
not designed to be persistent and/or migrated between platforms, I'm not 
sure I care, since your design is definitely quicker.


I'm in the process of refactoring your patch a little, and I'm going to 
leave the storage method alone for now.  I'll send you my patch when 
complete.  I'll have it done later tonight, after I make dinner for my kids.


BTW, is statuscache:log necessary, or is it just for debugging?

--
Kenneth Murchison
Systems Programmer
Project Cyrus Developer/Maintainer
Carnegie Mellon University


Re: statuscache

2008-01-17 Thread Rob Mueller



- statuscache v.2 stores statuscache_data as a binary blob, which is
platform dependent (byte-order  word size).  This make statuscache.db 
non-portable.  I believe that this might be the first cyrusdb that would 
be non-portable.  Does anybody care?


The only tricky part is going to be upgrading from v.2 to v.3.  If its not 
designed to be persistent and/or migrated between platforms, I'm not sure 
I care, since your design is definitely quicker.


Basically our startup scripts completely delete the statuscache.db file on 
startup, so migrating isn't an issue for us at all.


So if you want to make it platform independent for others in the future, I'm 
fine with that.



BTW, is statuscache:log necessary, or is it just for debugging?


It's not necessary, it was just helpful for debugging rather than having to 
recompile everything. From memory, clients make SO many status calls, that 
it can completely flood the log if you leave the syslog calls in.


Rob



Re: statuscache

2008-01-17 Thread Ken Murchison

Rob Mueller wrote:

Basically our startup scripts completely delete the statuscache.db file 
on startup, so migrating isn't an issue for us at all.


Why do you delete the cache?  I doesn't appear from the code that the 
cache entries would be invalid if the mailbox and seen state aren't touched.




BTW, is statuscache:log necessary, or is it just for debugging?


It's not necessary, it was just helpful for debugging rather than having 
to recompile everything. From memory, clients make SO many status calls, 
that it can completely flood the log if you leave the syslog calls in.


I'm changing the statuscache option to a switch and leaving the logging 
in as LOG_DEBUG



--
Kenneth Murchison
Systems Programmer
Project Cyrus Developer/Maintainer
Carnegie Mellon University


Re: statuscache

2008-01-17 Thread Rob Mueller



Why do you delete the cache?  I doesn't appear from the code that the
cache entries would be invalid if the mailbox and seen state aren't 
touched.


Historical. We only use berkeley db for statuscache and duplicate delivery, 
and because of problems in the past with berkeley db's corrupting 
themselves, we found it easier to just delete them on startup. It avoids the 
case of cyrus failing to start if one of the bdb's is corrupted


I'm changing the statuscache option to a switch and leaving the logging in 
as LOG_DEBUG


My only concern with this is that it can cause a LOT of log messages. I've 
never been entirely sure how well syslog handles the case of lots of log 
messages. I think it still has to send them over the socket to the syslogd. 
Most people then have a syslog.conf that discards debug messages, so it 
always seemed like a possible way to overflow the syslog socket buffer and 
loose important messages (i'm pretty sure syslog never guarantees that a 
message will be logged, which is why djb implemented his own way that uses 
streams rather than dgrams). This is probably all entirely academic and not 
a real issue...


Rob



Re: statuscache

2008-01-17 Thread Ken Murchison
)) {
+	statuscache_close();
+	statuscache_done();
+}
+
 if (imapd_in) {
 	/* Flush the incoming buffer */
 	prot_NONBLOCK(imapd_in);
@@ -6747,21 +6757,19 @@
 void cmd_status(char *tag, char *name)
 {
 int c;
-int statusitems = 0;
+unsigned statusitems = 0;
 static struct buf arg;
-struct mailbox mailbox;
 char mailboxname[MAX_MAILBOX_NAME+1];
 int mbtype;
-char *server;
+char *server, *acl;
 int r = 0;
-int doclose = 0;
 
 r = (*imapd_namespace.mboxname_tointernal)(imapd_namespace, name,
 	   imapd_userid, mailboxname);
 
 if (!r) {
 	r = mlookup(tag, name, mailboxname, mbtype, NULL, NULL,
-		server, NULL, NULL);
+		server, acl, NULL);
 }
 if (r == IMAP_MAILBOX_MOVED) {
 	/* Eat the argument */
@@ -6864,24 +6872,18 @@
 }
 
 if (!r) {
-	r = mailbox_open_header(mailboxname, imapd_authstate, mailbox);
-}
+	int myrights = cyrus_acl_myrights(imapd_authstate, acl);
 
-if (!r) {
-	doclose = 1;
-	r = mailbox_open_index(mailbox);
-}
-if (!r  !(mailbox.myrights  ACL_READ)) {
-	r = (imapd_userisadmin || (mailbox.myrights  ACL_LOOKUP)) ?
-	  IMAP_PERMISSION_DENIED : IMAP_MAILBOX_NONEXISTENT;
+	if (!(myrights  ACL_READ)) {
+	r = (imapd_userisadmin || (myrights  ACL_LOOKUP)) ?
+		IMAP_PERMISSION_DENIED : IMAP_MAILBOX_NONEXISTENT;
+	}
 }
 
 if (!r) {
-	r = index_status(mailbox, name, statusitems);
+	r = index_status(mailboxname, name, statusitems);
 }
 
-if (doclose) mailbox_close(mailbox);
-
 if (r) {
 	prot_printf(imapd_out, %s NO %s\r\n, tag, error_message(r));
 	return;
Index: imap/imapd.h
===
RCS file: /afs/andrew/system/cvs/src/cyrus/imap/imapd.h,v
retrieving revision 1.69
diff -u -r1.69 imapd.h
--- imap/imapd.h	17 Jan 2008 13:07:40 -	1.69
+++ imap/imapd.h	18 Jan 2008 04:16:12 -
@@ -272,8 +272,7 @@
 			struct searchargs *searchargs, int usinguid);
 extern int index_copy(struct mailbox *mailbox, char *sequence,
 		  int usinguid, char *name, char **copyuidp, int nolink);
-extern int index_status(struct mailbox *mailbox, char *name,
-			   int statusitems);
+extern int index_status(char *mboxname, char *name, unsigned statusitems);
 
 extern int index_getuids(struct mailbox *mailbox, unsigned lowuid);
 extern int index_getstate(struct mailbox *mailbox);
Index: imap/index.c
===
RCS file: /afs/andrew/system/cvs/src/cyrus/imap/index.c,v
retrieving revision 1.241
diff -u -r1.241 index.c
--- imap/index.c	17 Jan 2008 13:07:40 -	1.241
+++ imap/index.c	18 Jan 2008 04:16:12 -
@@ -69,10 +69,12 @@
 #include lsort.h
 #include mailbox.h
 #include map.h
+#include mboxlist.h
 #include message.h
 #include parseaddr.h
 #include search_engines.h
 #include seen.h
+#include statuscache.h
 #include strhash.h
 #include stristr.h
 #include util.h
@@ -1550,53 +1552,107 @@
 /*
  * Performs a STATUS command
  */
-int
-index_status(mailbox, name, statusitems)
-struct mailbox *mailbox;
-char *name;
-int statusitems;
+int index_status(char *mboxname, char *name, unsigned statusitems)
 {
 int r;
-struct seen *status_seendb;
-time_t last_read, last_change = 0;
-unsigned last_uid;
-char *last_seenuids;
+struct statuscache_data scdata;
+struct mailbox mailbox;
+int doclose = 0;
 int num_recent = 0;
 int num_unseen = 0;
 int sepchar;
 static struct seq_set seq_set = { NULL, 0, 0, 0 , NULL};
 
-if (mailbox-exists != 0 
-	(statusitems 
-	 (STATUS_RECENT | STATUS_UNSEEN))) {
-	r = seen_open(mailbox,
-		  (mailbox-options  OPT_IMAP_SHAREDSEEN) ? anyone :
+/* Check status cache if possible */
+if (config_getswitch(IMAPOPT_STATUSCACHE)) {
+	/* Do actual lookup of cache item. */
+	r = statuscache_lookup(mboxname, imapd_userid, scdata);
+
+	/* We need to find everything we're looking for in the cache,
+	   otherwise we fallback to the regular method */
+	if (!r  (scdata.statusitems  statusitems) != statusitems) {
+	r = IMAP_NO_NOSUCHMSG;
+	}
+
+	if (!r) {
+	/* If index file has changed, fallback to regular method */
+	char *path, *mpath;
+	struct stat index;
+
+	/* Get path to mailbox */
+	r = mboxlist_detail(mboxname, NULL, path, mpath, NULL, NULL, NULL);
+	if (!r) r = mailbox_stat(path, mpath, NULL, index, NULL);
+
+	if (!r 
+		(index.st_mtime != scdata.message_mtime ||
+		 index.st_ino   != scdata.message_ino ||
+		 index.st_size  != scdata.message_size)) {
+		r = IMAP_NO_NOSUCHMSG;
+	}
+
+	/* Seen/recent status uses push invalidation events from
+	 * seen_db.c.   This avoids needing to open cyrus.header to get
+	 * the mailbox uniqueid to open the seen db and get the
+	 * unseen_mtime and recentuid.
+	 */
+	}
+
+	if (!r) {
+	syslog(LOG_DEBUG, statuscache, '%s', '%s', '0x%02x', 'yes',
+		   mboxname, imapd_userid, statusitems);
+	goto statusdone

Re: RHEL5 x64, skiplist statuscache SIGV

2007-09-23 Thread Bron Gondwana

On Sun, 23 Sep 2007 21:58:57 +0200, Michael Glad [EMAIL PROTECTED] said:
 
 Hello Bron, I've tested Cyrus 2.3.9 + your FM patches as of September 20
 on a RHEL5 x64 Opteron virtual machine. 

We don't have any experience (yet) with 64 bit.  I believe it's less
well tested.

 As I'm a BDB skepticist  I use skiplists where ever possible including 
 the statuscache.

From memory it's not a good match because of the various strengths and
weaknesses of the the database methods used.  Skiplist is good for heavy
read loads, not so good for heavy write loads.

 But Imapd SIGV's in the skiplist mydelete routine (invoked from
 statuscache_invalidate) when the first 'select INBOX' command is
 received.
 
 I've looked into the cause and would to hear your opinion before I
 post the info below to the devel list.
 
 It seems to me that the skiplist routine is to blame. The SIGV
 arises from line 1305:
 
   newoffset = htonl(FORWARD(ptr, i));
 
 But ptr at the time of the crash points to db-map_base which is the
 initial skiplist header = Kaboom.
 
 When I apply the patch:
 
 @@ -1292,6 +1292,11 @@
  ptr = find_node(db, key, keylen, updateoffsets);
  if (ptr == db-map_base ||
 !db-compar(KEY(ptr), KEYLEN(ptr), key, keylen)) {
 +/* start glad */
 +if(ptr == db-map_base) {
 +   ptr = DUMMY_PTR(db);
 +}
 +/* end glad */
 /* gotcha */
 offset = ptr - db-map_base;
 
 things doesn't SIGV and output from
 
   /usr/lib/cyrus-imapd/cyr_dbtool /var/lib/imap/statuscache.db skiplist 
 show
 
 looks sensible -- it is partly garbled on my nonpatched RHEL4 
 x32 production system.


I have CC'd this to the cyrus development list, as there are probably people 
with
more skiplist and 64 bit programming experience who can tell you if this is the
right approach, and hopefully push the fix into the next Cyrus release!

Bron.
-- 
  Bron Gondwana
  [EMAIL PROTECTED]