Since you're soliciting patches... here's one I sent in a while ago. Didn't see it appear in CVS, so I thought I'd repost it.
I've been running it locally with great success. Works fine, and it's fairly trivial. On 03/25/2010 05:28 AM, Bron Gondwana wrote: > Gosh, it's getting awfully close to my self imposed deadline of April > isn't it - though I think I'll be pulling an Ubuntu and saying "I > meant the end of April, honest". Sysadmin stuff got in the way for > rather longer than I intended. > > Due to making changes all over the place, I currently have a giant change > entry on the future branch with all the changes on it. I'll try to factor > them out into individual line items later, keeping it reviewable. I'm not > going to try to make every intermediate stage work - let alone even > compile - because it's too much makework for no benefit. > > That said, here's where things are! (long, but hopefully interesting to > at least some other people... if nothing else a handy memory jogger for > me if I get side-tracked at all) > > Rewritten (greatly simplified) API for getting file names: > ========================================================== > > char *fname = mailbox_meta_fname(&mailbox, META_INDEX); > char *newfname = mailbox_meta_newfname(&mailbox, META_INDEX); > > (uses a separate static buffer so you can just do this and then > your rename logic!) > > char *fname = mailbox_message_fname(&mailbox, uid); > > So that simplifies HEAPS of code and hides all the "is it meta" > behind one interface. > > Mboxlist functions return a struct > ================================== > > struct mboxlist_entry mbentry; > r = mboxlist_lookup(name, &mbentry, &tid); > > mbentry.mbtype, mbentry.partition, mbentry.acl > > Simplifies parameter passing to functions considerably > > Locking > ======= > > Here's the big one! I'll write a separate section on this in more > detail, but here are the basic contracts: > > New file: cyrus.lock - empty file. > > exclusive lock on cyrus.lock: > * free reign with all files. Delete what you like, rewrite > what you like > * no other locks required > > shared lock on cyrus.lock: > * MUST NOT replace cyrus.index or cyrus.cache files (change inode) > * MUST NOT change any files at all without cyrus.index lock > * MAY rewrite cyrus.squat. > > exclusive lock on cyrus.index: > * MUST have a shared lock on cyrus.lock > * MAY rewrite flags/modseq on any index record > * MAY append new index records > * MAY append to cyrus.cache > * MUST NOT rewrite older parts of cyrus.cache > * MAY rewrite cyrus.header (write .NEW, rename) > * MAY rewrite user.seen file > > shared lock on cyrus.index: > * optional - gives consistent reads. Otherwise modseqs higher than > last read header may be found, seen may be out of sync. I have a > simple concurrency test case that can see unintended data by being > clever. > > All this infrastructure is in place in the future branch now, though > untested so far. APIs are: > > mailbox_open_shared(name, auth_state, &mailbox); > mailbox_open_exclusive(name, auth_state, &mailbox); > > mailbox_lock_index(&mailbox); > mailbox_unlock_index(&mailbox); > > mailbox_close(&mailbox); > > CRCs and automatic bookkeeping > ============================== > > (remember the discussion on recno replacing msgno because expunged records > remain in cyrus.index rather than cyrus.expunge, so need to be skipped? > It's necessary for the above, because cyr_expire will get an exclusive lock > on the mailbox for the duration of its index rewrite!) > > Move "deleted / flagged / answered" meta count management into mailbox.c: > > mailbox_rewrite_index_record(&mailbox, recno, &record); > * reads the OLD record again, updates counts, updates CRC32 values including > XOR_CRC which is the XOR of all record CRCs. > * updates "exists" if it's an expunge. > * updates modseq value. Calls: > > mailbox_index_dirty(&mailbox) > * anything doing a write to ANYTHING does this. It sets a flag, > increments the highestmodseq and grabs a timestamp. All changes > use these values. > > mailbox_header_write(&mailbox); > * rewrites the header file. Also updates the mailbox->header_file_crc > value which will be saved when we call: > > mailbox_write_index_header(&mailbox); > * MUST be called after making any change to ensure all checksums and > XOR_CRC are correctlly stored - along with the bumped highestmodseq > and correct record counts. > > Oh, we missed: > > mailbox_append_index_records(&mailbox, &records, num); > > Stores "num" records to the index file. It's a pointer to an array of > "struct index_record" structs. > > I'm still reworking everything to use these rather than doing the > bookkeeping by hand! > > index.c - use a mailbox object > ============================== > > All the globals go away! There's just a global mailbox struct, which > will have a lock_fd in shared mode, meaning that all the offsets into > the cyrus.index and cyrus.cache mmaps are ALWAYS VALID. > > Along with compulsary CONDSTORE - vast swathes of code complexity are > being removed :) You don't need to track times when you have modseq > to determine if flags should be sent again. You don't have to keep > statting files, just re-read the header and then scan for updates. > > It WILL be necessary to keep a global array mapping from msgno to recno > so non-UID commands can be efficient. This can be rewritten whenever > highestmodseq is detected to have changed :) > > I'm just starting on this - hence there are lots of global references to > remove. > > Also - no more UID(msgno) and CACHE_OFFSET(msgno) and all that jazz. We > read a record with mailbox_read_index_record() and then use it. In native > form, in an easily accessible struct. Joy. No more > htonl((bit32 *)base_offset+SOME_CONSTANT) nonsense everywhere! Contain it, > wrap it, ensure accesses to it go via consistency checking, checksum > updating and header counter maintaining paths! > > > So - that's the status of the future branch! It also has most of the > interesting patches from the fastmail branch cherry-picked forwards to > sit on top of CVS trunk. > > Feel free to poke around, make suggestions, send patches, etc. Some of > the less popular (i.e. I don't use them) utilities could probably do with > some TLC or maybe merging into uber-tools if they don't do much. While I > haven't drifted too far incompatible just yet, it's getting that way! > > Speaking of which: cyrus.expunge. It's pretty much all stripped now. I'll > be writing something simple in to mailbox_upgrade_index which detects its > presence and does a sorted merge of the two files into the new cyrus.index, > complete with system_flags & FLAG_EXPUNGED. There's also FLAG_UNLINKED > which will allow us to have immediate expunge of the actual on-disk-file > (with the associated inabilithy to unexpunge of course!) if sites want that. > > > Thanks for reading! > > Bron. >
--- cyrus-imapd-2.3.15/lib/imapoptions.orig 2009-06-29 11:21:06.000000000 -0600 +++ cyrus-imapd-2.3.15/lib/imapoptions 2009-12-14 14:40:56.000000000 -0700 @@ -854,6 +854,10 @@ are listed with ``<none>''. strip the default realm from the userid (this does not affect the stripping of realms specified by the afspts_localrealms option) */ +{ "qosmarking", "cs0", ENUM("cs0", "cs1", "cs2", "cs3", "cs4", "cs5", "cs6", "cs7", "af11", "af12", "af13", "af21", "af22", "af23", "af31", "af32", "af33", "af41", "af42", "af43", "ef") } +/* This specifies the Class Selector or Differentiated Services Code Point + designation on IP headers (in the ToS field). */ + { "quota_db", "quotalegacy", STRINGLIST("flat", "berkeley", "berkeley-hash", "skiplist", "sql", "quotalegacy")} /* The cyrusdb backend to use for quotas. */ --- cyrus-imapd-2.3.15/lib/libconfig.c.orig 2009-08-20 09:26:15.000000000 -0600 +++ cyrus-imapd-2.3.15/lib/libconfig.c 2009-12-14 00:37:20.000000000 -0700 @@ -82,6 +82,7 @@ enum enum_value config_virtdomains; enum enum_value config_mupdate_config; /* IMAP_ENUM_MUPDATE_CONFIG_STANDARD */ int config_maxword; int config_maxquoted; +int config_qosmarking; /* declared in each binary that uses libconfig */ extern const int config_need_data; @@ -210,11 +211,21 @@ static void config_ispartition(const cha if (!strncmp("partition-", key, 10)) *found = 1; } +static const unsigned char qos[] = { +/* cs0..cs7 */ 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, +/* af11..af13 */ 0x28, 0x30, 0x38, +/* af21..af23 */ 0x48, 0x50, 0x58, +/* af31..af33 */ 0x68, 0x70, 0x78, +/* af41..af43 */ 0x88, 0x90, 0x98, +/* ef */ 0xb8 +}; + void config_read(const char *alt_config) { enum imapopt opt = IMAPOPT_ZERO; char buf[4096]; char *p; + int ival; /* xxx this is leaked, this may be able to be better in 2.2 (cyrus_done) */ if(alt_config) config_filename = xstrdup(alt_config); @@ -328,6 +339,9 @@ void config_read(const char *alt_config) /* set some limits */ config_maxquoted = config_getint(IMAPOPT_MAXQUOTED); config_maxword = config_getint(IMAPOPT_MAXWORD); + + ival = config_getenum(IMAPOPT_QOSMARKING); + config_qosmarking = qos[ival]; } #define GROWSIZE 4096 --- cyrus-imapd-2.3.15/lib/libconfig.h.orig 2008-09-23 11:34:38.000000000 -0600 +++ cyrus-imapd-2.3.15/lib/libconfig.h 2009-12-14 00:19:40.000000000 -0700 @@ -80,6 +80,7 @@ extern enum enum_value config_virtdomain extern enum enum_value config_mupdate_config; extern int config_maxquoted; extern int config_maxword; +extern int config_qosmarking; /* config requirement flags */ #define CONFIG_NEED_PARTITION_DATA (1<<0) --- cyrus-imapd-2.3.15/master/master.c.orig 2009-03-30 22:11:23.000000000 -0600 +++ cyrus-imapd-2.3.15/master/master.c 2009-12-14 15:18:24.000000000 -0700 @@ -439,6 +439,15 @@ void service_create(struct service *s) } #endif + /* set IP ToS if supported */ +#if defined(SOL_IP) && defined(IP_TOS) + r = setsockopt(s->socket, SOL_IP, IP_TOS, + (void *) &config_qosmarking, sizeof(config_qosmarking)); + if (r < 0) { + syslog(LOG_WARNING, "unable to setsocketopt(IP_TOS): %m"); + } +#endif + oldumask = umask((mode_t) 0); /* for linux */ r = bind(s->socket, res->ai_addr, res->ai_addrlen); umask(oldumask);