[Dovecot] Loadable module
Timo Sirainen
tss at iki.fi
Tue Jul 22 20:53:59 EEST 2003
On Tuesday, Jul 22, 2003, at 18:11 Europe/Helsinki, Maikel Verheijen
wrote:
> But if I read your suggestions right, you propose a "fixed" change in
> the maildir functions that call the quota update functions if
> necessary. So perhaps we should make a quota_enabled = yes|no flag int
> the config file, and use that? I would still be trying to make the
> quota update functions for you, and try to put them in.
No, the core code wouldn't know anything about quota. The module would
simply grab the calls to mailbox interface itself.
Actually I'd really like if the same quota code was mail storage
independent. So if you accessed the messages only through Dovecot's
APIs the same code would work with maildir, mbox and whatever future
formats I come up with. But I'm not sure how good idea this is with
current APIs .. you probably could do it but it could be done faster.
> > expunge(): nothing special, just update the quota file after expunges
> Expunge should recalculate the whole mailfolder?
Well .. it would be faster if it didn't have to. Problem is that you
might not know the message's size always. Also there's some locking
problems / race conditions if you try to calculate the new quota before
actually expunging.
> > copy(): this is somewhat problematic, if there wasn't the
> > maildir hardlinks you wouldn't have to touch it at all..
>
> A copy can duplicate a message in the same store, but do hardlinks
> work on nfs? If not, we should add the message to the quota list. And
> maybe we should just add size of the email anyway, it won't be that
> much of a loss to the user, and it would save us a lot of checking. :)
Hard links work with NFS. But the problem is adding the message to
quota list. Normally copy() reads the messages and saves them using the
normal save*() functions, so the quota checking would be done
automatically. With hard links it doesn't go through save*(), so you'd
have to do some special kludging if you wanted to account that copied
message from quota too.
One possibility is to just go through the messageset, get the message
sizes, call copy(), see if quota was accounted by save*() functions, if
not do it yourself.
Another possibility is to fix the API by splitting all functions which
handle multiple messages at once and replace them with iterator
functions. ie. fetch*(), search*() and save*() are ok now, but
expunge() and copy() are not. Something like:
// initialize. very much like fetching messages.
struct mail_copy_context *(*copy_init)(struct mailbox *box,
enum mail_fetch_field wanted_fields, const char *messageset, int
uidset);
// copy next message. returns pointer to original message where you can
find it's info
// including message's size
struct mail *(*copy_next)(struct mail_copy_context *ctx);
You'd call copy_init() with wanted_fields being MESSAGE_FETCH_SIZE (or
actually I should probably add _REAL_SIZE which would tell how much
actual disk space it takes rather than the size with virtual CRs). Then
you'd call copy_next(), use some kludge to see if it called your
save_next(), if not you get the message size with mail->get_size(mail)
and add it to quota.
Expunging would work pretty much the same way:
struct mail_expunge_context *(*expunge_init)(struct mailbox *box,
enum mail_fetch_field wanted_fields);
struct mail (*expunge_next)(struct mail_expunge_context *ctx);
Only difference would be that mail->get_size() might return you -1, ie.
unknown. In that case you'd have to recalculate the quota for the
mailbox.
Hmm. There's still a few small problems. And the _next() calls should
probably be split to two, so you can first fetch the record, then
decide if you really want to copy/expunge that message by calling
_doit() or something. Umm. Actually then I might just as well use the
normal fetch*() interface and just add a few new methods to struct mail:
int (*expunge)(struct mail *mail);
int (*copy)(struct mail *mail, struct mailbox *dest);
I think that'd work. :) I'll try to make these changes to CVS soon.
> And how about a user that has no quota file (yet), can we "recreate"
> them? Maybe do a quota lookup for the user (database or file)? This
> can be done using a module I guess, so it could be "user > configurable".
Depends on how you want the quota stuff to work. I'm not sure about
that yet. Maildir++ quota seemed a bit slow. It would require
rescanning _all_ the mailboxes once in a while. That's kind of
pointless if only a few mailboxes have changed. Of course we could
internally calculate the quotas per mailbox and combine them all to one
Maildir++ compatible quota file.
More information about the dovecot
mailing list