Commit ed63b7f6 ed63b7f6deebedfe6f56ca5966dff034008c80f7 by Alain Magloire

regroup the locking support in monitor.c, and first attempt to define a "folder"

1 parent c6eef46c
......@@ -38,8 +38,8 @@ typedef struct _envelope *envelope_t;
int envelope_create (envelope_t *, void *);
void envelope_destroy (envelope_t *, void *);
void * envelope_get_owner (envelope_t);
int envelope_set_from (envelope_t, int (*_from) __P ((envelope_t, char *, size_t, size_t*)), void *);
int envelope_from (envelope_t, char *, size_t, size_t *);
int envelope_set_sender (envelope_t, int (*_sender) __P ((envelope_t, char *, size_t, size_t*)), void *);
int envelope_sender (envelope_t, char *, size_t, size_t *);
int envelope_set_date (envelope_t, int (*_date) __P ((envelope_t, char *, size_t , size_t *)), void *);
int envelope_date (envelope_t, char *, size_t, size_t *);
......
......@@ -23,7 +23,7 @@
#include <mailutils/url.h>
#include <mailutils/observer.h>
#include <mailutils/debug.h>
#include <mailutils/list.h>
#include <mailutils/stream.h>
#include <mailutils/auth.h>
#include <mailutils/stream.h>
......@@ -44,6 +44,17 @@ extern "C" {
struct _folder;
typedef struct _folder *folder_t;
#define MU_FOLDER_ATTRIBUTE_NOINFERIORS 0x001
#define MU_FOLDER_ATTRIBUTE_NOSELECT 0x002
#define MU_FOLDER_ATTRIBUTE_MARKED 0x004
#define MU_FOLDER_ATTRIBUTE_UNMARKED 0x008
struct folder_list
{
int attribute;
int separator;
char *name;
};
/* Constructor/destructor and possible types. */
extern int folder_create __P ((folder_t *, const char *));
extern void folder_destroy __P ((folder_t *));
......@@ -53,7 +64,9 @@ extern int folder_close __P ((folder_t));
extern int folder_delete_mailbox __P ((folder_t, const char *));
extern int folder_list __P ((folder_t, char *vector[][], size_t *));
extern int folder_list __P ((folder_t, const char *pattern,
struct folder_list ***flist, size_t *));
extern int folder_list_destroy __P ((struct folder_list ***, size_t));
/* Stream settings. */
extern int folder_get_stream __P ((folder_t, stream_t *));
......
......@@ -80,7 +80,6 @@ extern int mailbox_set_ticket __P ((mailbox_t, ticket_t));
/* URL. */
extern int mailbox_get_url __P ((mailbox_t, url_t *));
extern int mailbox_set_url __P ((mailbox_t, url_t));
/* For any debuging */
extern int mailbox_get_debug __P ((mailbox_t, debug_t *));
......
......@@ -32,10 +32,20 @@ extern "C" {
# endif
#endif /*__P */
struct _monitor;
struct _monitor
{
void *data;
void *owner;
int allocated;
int flags;
};
typedef struct _monitor *monitor_t;
extern int monitor_create __P ((monitor_t *, void *owner));
#define MU_MONITOR_PTHREAD 0
#define MU_MONITOR_INITIALIZER {0, 0, 0, 0}
extern int monitor_create __P ((monitor_t *, int flags, void *owner));
extern void monitor_destroy __P ((monitor_t *, void *owner));
extern void *monitor_get_owner __P ((monitor_t));
......
......@@ -67,28 +67,30 @@ struct _record;
typedef struct _record* record_t;
/* Registration. */
extern int registrar_get_list __P ((list_t *));
extern int registrar_get_list __P ((list_t *));
extern int registrar_record __P ((record_t));
extern int unregistrar_record __P ((record_t));
/* Record. */
extern int record_create __P ((record_t *, void *owner));
extern void record_destroy __P ((record_t *));
extern int record_is_scheme __P ((record_t, const char *));
extern int record_set_scheme __P ((record_t, const char *));
extern int record_set_is_scheme __P ((record_t, int (*_is_scheme)
__P ((const char *))));
extern int record_get_mailbox __P ((record_t, mailbox_entry_t *));
extern int record_set_mailbox __P ((record_t, mailbox_entry_t));
extern int record_create __P ((record_t *, void *owner));
extern void record_destroy __P ((record_t *));
extern int record_is_scheme __P ((record_t, const char *));
extern int record_set_scheme __P ((record_t, const char *));
extern int record_set_is_scheme __P ((record_t, int (*_is_scheme)
__P ((const char *))));
extern int record_get_mailbox __P ((record_t, mailbox_entry_t *));
extern int record_set_mailbox __P ((record_t, mailbox_entry_t));
extern int record_set_get_mailbox __P ((record_t, int (*_get_mailbox)
__P ((mailbox_entry_t *))));
extern int record_get_mailer __P ((record_t, mailer_entry_t *));
extern int record_set_mailer __P ((record_t, mailer_entry_t));
extern int record_set_get_mailer __P ((record_t, int (*_get_mailer)
extern int record_get_mailer __P ((record_t, mailer_entry_t *));
extern int record_set_mailer __P ((record_t, mailer_entry_t));
extern int record_set_get_mailer __P ((record_t, int (*_get_mailer)
__P ((mailer_entry_t *))));
extern int record_get_folder __P ((record_t, folder_entry_t *));
extern int record_set_folder __P ((record_t, folder_entry_t));
extern int record_set_get_folder __P ((record_t, int (*_get_folder)
__P ((folder_entry_t *))));
extern int record_get_folder __P ((record_t, folder_entry_t *));
extern int record_set_folder __P ((record_t, folder_entry_t));
extern int record_set_get_folder __P ((record_t, int (*_get_folder)
__P ((folder_entry_t *))));
#define MU_POP_PORT 110
#define MU_POP_SCHEME "pop://"
......
......@@ -22,6 +22,7 @@ debug.c \
envelope.c \
file_stream.c \
folder.c \
folder_mbox.c \
header.c \
iterator.c \
list.c \
......
......@@ -56,25 +56,25 @@ envelope_get_owner (envelope_t envelope)
}
int
envelope_set_from (envelope_t envelope,
int (*_from) __P ((envelope_t, char *, size_t, size_t*)),
envelope_set_sender (envelope_t envelope,
int (*_sender) __P ((envelope_t, char *, size_t, size_t*)),
void *owner)
{
if (envelope == NULL)
return EINVAL;
if (envelope->owner != owner)
return EACCES;
envelope->_from = _from;
envelope->_sender = _sender;
return 0;
}
int
envelope_from (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
envelope_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
{
if (envelope == NULL)
return EINVAL;
if (envelope->_from)
return envelope->_from (envelope, buf, len, pnwrite);
if (envelope->_sender)
return envelope->_sender (envelope, buf, len, pnwrite);
if (buf && len)
*buf = '\0';
if (pnwrite)
......
......@@ -22,20 +22,16 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_PTHREAD_H
# include <pthread.h>
#endif
#include <mailutils/registrar.h>
#include <mailutils/iterator.h>
#include <mailutils/list.h>
#include <mailutils/monitor.h>
#include <misc.h>
#include <folder0.h>
#ifdef WITH_PTHREAD
static pthread_mutex_t slock = PTHREAD_MUTEX_INITIALIZER;
#endif
static struct _monitor folder_lock = MU_MONITOR_INITIALIZER;
/* Internal folder list. */
static list_t known_folder_list;
......@@ -99,24 +95,19 @@ folder_create (folder_t *pfolder, const char *name)
|| (status = entry->_url_init (url)) != 0)
return status;
#ifdef WITH_PTHREAD
pthread_mutex_lock (&slock);
#endif
monitor_wrlock (&folder_lock);
/* Check if we already have the same URL folder. */
if (is_known_folder (url, &folder))
{
folder->ref++;
*pfolder = folder;
url_destroy (&url);
#ifdef WITH_PTHREAD
pthread_mutex_unlock (&slock);
#endif
monitor_unlock (&folder_lock);
return 0;
}
#ifdef WITH_PTHREAD
else
pthread_mutex_unlock (&slock);
#endif
monitor_unlock (&folder_lock);
/* Create a new folder. */
......@@ -127,7 +118,7 @@ folder_create (folder_t *pfolder, const char *name)
folder->url = url;
/* Initialize the internal lock, now so the concrete
folder could use it. */
status = monitor_create (&(folder->monitor), folder);
status = monitor_create (&(folder->monitor), 0, folder);
if (status == 0)
{
/* Create the concrete folder type. */
......@@ -137,6 +128,8 @@ folder_create (folder_t *pfolder, const char *name)
*pfolder = folder;
folder->ref++;
/* Put on the internal list of known folders. */
if (known_folder_list == NULL)
list_create (&known_folder_list);
list_append (known_folder_list, folder);
}
}
......@@ -167,16 +160,17 @@ folder_destroy (folder_t *pfolder)
monitor_t monitor = folder->monitor;
monitor_wrlock (monitor);
#ifdef WITH_PTHREAD
pthread_mutex_lock (&slock);
#endif
monitor_wrlock (&folder_lock);
folder->ref--;
/* Remove the folder from the list of known folder. */
if (folder->ref <= 0)
list_remove (known_folder_list, folder);
#ifdef WITH_PHTREAD
pthread_mutex_unlock (&slock);
#endif
if (list_is_empty)
{
list_destroy (&known_folder_list);
known_folder_list = NULL;
}
monitor_unlock (&folder_lock);
if (folder->ref <= 0)
{
monitor_unlock (monitor);
......@@ -325,11 +319,34 @@ folder_get_debug (folder_t folder, debug_t *pdebug)
}
int
folder_list (folder_t folder, char *vector[][], size_t *pnum)
folder_list (folder_t folder, const char *dirname,
struct folder_list ***flist, size_t *pnum)
{
if (folder == NULL || folder->_list == NULL)
return ENOSYS;
return folder->_list (folder, vector, pnum);
return folder->_list (folder, dirname, flist, pnum);
}
int
folder_list_destroy (struct folder_list ***pflist, size_t count)
{
struct folder_list **list;
size_t i;
if (pflist == NULL || *pflist == NULL || count == 0)
return 0;
list = *pflist;
for (i = 0 ; i < count; i++)
{
if (list[i])
{
if (list[i]->name)
free (list[i]->name);
free (list[i]);
}
}
free (list);
*pflist = NULL;
return 0;
}
int
......@@ -340,6 +357,17 @@ folder_delete_mailbox (folder_t folder, const char *name)
return folder->_delete_mailbox (folder, name);
}
int
folder_get_url (folder_t folder, url_t *purl)
{
if (folder == NULL || purl == NULL)
return EINVAL;
*purl = folder->url;
return 0;
}
/* ---------------------- Private ---------------------- */
static int is_known_folder (url_t url, folder_t *pfolder)
{
int ret = 0;
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <folder0.h>
#include <registrar0.h>
static int fmbox_init (folder_t);
struct folder_entry _fmbox_entry =
{
url_path_init, fmbox_init
};
/* We export two functions: url parsing and the initialisation of
the mailbox, via the register entry/record. */
folder_entry_t fmbox_entry = &_fmbox_entry;
static void fmbox_destroy (folder_t);
static int fmbox_open (folder_t, int);
static int fmbox_close (folder_t);
static int fmbox_delete (folder_t, const char *);
static int fmbox_list (folder_t, const char *,
struct folder_list ***, size_t *);
static int fmbox_list0 (const char *, struct folder_list ***, size_t *, int);
struct _fmbox
{
char *dirname;
};
typedef struct _fmbox *fmbox_t;
static int
fmbox_init (folder_t folder)
{
fmbox_t dfolder;
//char *dirname;
size_t name_len = 0;
dfolder = folder->data = calloc (1, sizeof (dfolder));
if (dfolder == NULL)
return ENOMEM;
url_get_path (folder->url, NULL, 0, &name_len);
dfolder->dirname = calloc (name_len + 1, sizeof (char));
if (dfolder->dirname == NULL)
{
free (dfolder);
folder->data = NULL;
return ENOMEM;
}
url_get_path (folder->url, dfolder->dirname, name_len + 1, NULL);
folder->_init = fmbox_init;
folder->_destroy = fmbox_destroy;
folder->_open = fmbox_open;
folder->_close = fmbox_close;
folder->_list = fmbox_list;
folder->_delete_mailbox = fmbox_delete;
return 0;
}
void
fmbox_destroy (folder_t folder)
{
if (folder->data)
{
fmbox_t fmbox = folder->data;
if (fmbox->dirname)
free (fmbox->dirname);
free (folder->data);
folder->data = NULL;
}
}
static int
fmbox_open (folder_t folder, int flags)
{
(void)(folder);
(void)(flags);
return 0;
}
static int
fmbox_close (folder_t folder)
{
(void)(folder);
return 0;
}
static int
fmbox_delete (folder_t folder, const char *dirname)
{
(void)(folder);
(void)dirname;
return 0;
}
static int
fmbox_list (folder_t folder, const char *pattern,
struct folder_list ***pflist, size_t *pnum)
{
fmbox_t fmbox = folder->data;
struct folder_list **list = NULL;
char *dirname = NULL;
int status;
size_t num = 0;
if (pattern == NULL)
{
dirname = strdup (fmbox->dirname);
}
else if (pattern[0] != '/')
{
size_t len = strlen (pattern);
dirname = calloc (strlen (fmbox->dirname) + len + 2, sizeof (char));
if (dirname)
sprintf (dirname, "%s/%s", fmbox->dirname, pattern);
}
else
dirname = strdup (pattern);
if (dirname == NULL)
return errno;
status = fmbox_list0 (dirname, &list, &num, (strchr (dirname, '*') != NULL));
if (status == 0)
{
if (pflist)
*pflist = list;
if (pnum)
*pnum = num;
}
return status;
}
static int
fmbox_list0 (const char *dirname, struct folder_list ***pflist,
size_t *pnum, int recurse)
{
DIR *dp;
struct dirent *rp;
struct stat stbuf;
struct folder_list **flist = *pflist;
char buf[512];
dp = opendir (dirname);
if (dp == NULL)
{
return errno;
}
while ((rp = readdir (dp)) != NULL)
{
if (rp->d_name[0] == '.')
continue;
flist = realloc (flist, (*pnum + 1) * sizeof (*flist));
flist[*pnum] = calloc (1, sizeof (**flist));
sprintf (buf, "%s/%s", dirname, rp->d_name);
if (stat (buf, &stbuf) == 0)
{
int isdir = S_ISDIR(stbuf.st_mode);
if (isdir)
flist[*pnum]->attribute |= MU_FOLDER_ATTRIBUTE_NOSELECT;
flist[*pnum]->name = strdup (buf);
(*pnum)++;
if (isdir && recurse)
{
fmbox_list0 (buf, &flist, pnum, recurse);
}
}
else
(*pnum)++;
}
closedir (dp);
*pflist = flist;
return 0;
}
......@@ -40,7 +40,7 @@ struct _envelope
{
void *owner;
int (*_destroy) __P ((envelope_t));
int (*_from) __P ((envelope_t, char *, size_t, size_t*));
int (*_sender) __P ((envelope_t, char *, size_t, size_t*));
int (*_date) __P ((envelope_t, char *, size_t , size_t *));
};
......
......@@ -64,7 +64,8 @@ struct _folder
int (*_open) __P ((folder_t, int flag));
int (*_close) __P ((folder_t));
int (*_list) __P ((folder_t, char *vector[][], size_t *num));
int (*_list) __P ((folder_t, const char *,
struct folder_list ***, size_t *));
int (*_delete_mailbox) __P ((folder_t, const char *));
};
......
......@@ -41,51 +41,6 @@ extern "C" {
# endif
#endif
#ifdef HAVE_PTHREAD_H
# define __USE_UNIX98
# include <pthread.h>
#endif
#ifdef WITH_PTHREAD
# if 0
# define RWLOCK_INIT(rwl, attr) pthread_mutex_init (rwl, attr)
# define RWLOCK_DESTROY(rwl) pthread_mutex_destroy (rwl)
# define RWLOCK_RDLOCK(rwl) pthread_mutex_lock (rwl)
# define RWLOCK_TRYRDLOCK(rwl) pthread_mutex_trylock (rwl)
# define RWLOCK_WRLOCK(rwl) pthread_mutex_lock (rwl)
# define RWLOCK_TRYWRLOCK(rwl) pthread_mutex_trylock (rwl)
# define RWLOCK_UNLOCK(rwl) pthread_mutex_unlock (rwl)
# else
# define RWLOCK_INIT(rwl, attr) pthread_rwlock_init (rwl, attr)
# define RWLOCK_DESTROY(rwl) pthread_rwlock_destroy (rwl)
# define RWLOCK_RDLOCK(rwl) pthread_rwlock_rdlock (rwl)
# define RWLOCK_TRYRDLOCK(rwl) pthread_rwlock_tryrdlock (rwl)
# define RWLOCK_WRLOCK(rwl) pthread_rwlock_wrlock (rwl)
# define RWLOCK_TRYWRLOCK(rwl) pthread_rwlock_trywrlock (rwl)
# define RWLOCK_UNLOCK(rwl) pthread_rwlock_unlock (rwl)
# endif
#else
# define RWLOCK_INIT(rwl, attr) 0
# define RWLOCK_DESTROY(rwl) 0
# define RWLOCK_RDLOCK(rwl) 0
# define RWLOCK_TRYRDLOCK(rwl) 0
# define RWLOCK_WRLOCK(rwl) 0
# define RWLOCK_TRYWRLOCK(rwl) 0
# define RWLOCK_UNLOCK(rwl) 0
# define flockfile(arg) 0
# define funlockfile(arg) 0
#endif
struct _monitor
{
#ifdef WITH_PTHREAD
pthread_rwlock_t lock;
#else
int lock;
#endif
void *owner;
};
#ifdef __cplusplus
}
#endif
......
......@@ -34,7 +34,7 @@ list_create (list_t *plist)
list = calloc (sizeof (*list), 1);
if (list == NULL)
return ENOMEM;
status = monitor_create (&(list->monitor), list);
status = monitor_create (&(list->monitor), 0, list);
if (status != 0)
{
free (list);
......@@ -72,7 +72,10 @@ int
list_append (list_t list, void *item)
{
struct list_data *ldata;
struct list_data *last = list->head.prev;
struct list_data *last;
if (list == NULL)
return EINVAL;
last = list->head.prev;
ldata = calloc (sizeof (*ldata), 1);
if (ldata == NULL)
return ENOMEM;
......@@ -91,7 +94,10 @@ int
list_prepend (list_t list, void *item)
{
struct list_data *ldata;
struct list_data *first = list->head.next;
struct list_data *first;
if (list == NULL)
return EINVAL;
first = list->head.next;
ldata = calloc (sizeof (*ldata), 1);
if (ldata == NULL)
return ENOMEM;
......@@ -111,7 +117,7 @@ list_is_empty (list_t list)
{
size_t n = 0;
list_count (list, &n);
return n;
return (n == 0);
}
int
......
......@@ -77,7 +77,7 @@ mailbox_create (mailbox_t *pmbox, const char *name)
/* Initialize the internal lock now, so the concrete mailbox
could use it. */
status = monitor_create (&(mbox->monitor), mbox);
status = monitor_create (&(mbox->monitor), 0, mbox);
if (status != 0)
{
mailbox_destroy (&mbox);
......@@ -360,3 +360,12 @@ mailbox_get_debug (mailbox_t mbox, debug_t *pdebug)
*pdebug = mbox->debug;
return 0;
}
int
mailbox_get_url (mailbox_t mbox, url_t *purl)
{
if (mbox == NULL || purl == NULL)
return EINVAL;
*purl = mbox->url;
return 0;
}
......
......@@ -73,7 +73,7 @@ mailer_create (mailer_t *pmailer, const char *name, int id)
if (mailer == NULL)
return ENOMEM;
status = monitor_create (&(mailer->monitor), mailer);
status = monitor_create (&(mailer->monitor), 0, mailer);
if (status != 0)
{
mailer_destroy (&mailer);
......
......@@ -35,13 +35,14 @@ static struct mailbox_entry _file_entry =
url_file_init, mailbox_file_init
};
mailbox_entry_t file_entry = &_file_entry;
extern struct folder_entry _fmbox_entry;
static struct _record _file_record =
{
MU_FILE_SCHEME,
&_file_entry, /* Mailbox entry. */
NULL, /* Mailer entry. */
NULL, /* Folder entry. */
&_fmbox_entry, /* Folder entry. */
0, /* Not malloc()ed. */
NULL, /* No need for an owner. */
NULL, /* is_scheme method. */
......@@ -63,7 +64,7 @@ static struct _record _path_record =
MU_PATH_SCHEME,
&_path_entry, /* Mailbox entry. */
NULL, /* Mailer entry. */
NULL, /* Folder entry. */
&_fmbox_entry, /* Folder entry. */
0, /* Not malloc()ed. */
NULL, /* No need for an owner. */
NULL, /* is_scheme method. */
......
......@@ -57,13 +57,14 @@ static struct mailbox_entry _mbox_entry =
url_mbox_init, mbox_init
};
mailbox_entry_t mbox_entry = &_mbox_entry;
extern struct folder_entry _fmbox_entry;
static struct _record _mbox_record =
{
MU_MBOX_SCHEME,
&_mbox_entry, /* Mailbox entry. */
NULL, /* Mailer entry. */
NULL, /* Folder entry. */
&_fmbox_entry, /* Folder entry. */
0, /* Not malloc()ed. */
NULL, /* No need for an owner. */
NULL, /* is_scheme method. */
......@@ -130,7 +131,7 @@ struct _mbox_data
{
MBOX_NO_STATE=0, MBOX_STATE_FROM, MBOX_STATE_DATE, MBOX_STATE_APPEND
} state ;
char *from;
char *sender;
char *date;
off_t off;
mailbox_t mailbox; /* Back pointer. */
......@@ -162,7 +163,7 @@ static int mbox_header_size (header_t, size_t *);
static int mbox_header_lines (header_t, size_t *);
static int mbox_body_size (body_t, size_t *);
static int mbox_body_lines (body_t, size_t *);
static int mbox_envelope_from (envelope_t, char *, size_t, size_t *);
static int mbox_envelope_sender (envelope_t, char *, size_t, size_t *);
static int mbox_envelope_date (envelope_t, char *, size_t, size_t *);
static void mbox_cleanup (void *);
......@@ -198,7 +199,8 @@ mbox_init (mailbox_t mailbox)
mud->name = calloc (name_len + 1, sizeof (char));
if (mud->name == NULL)
{
mbox_destroy (mailbox);
free (mud);
mailbox->data = NULL;
return ENOMEM;
}
url_get_path (mailbox->url, mud->name, name_len + 1, NULL);
......@@ -1032,7 +1034,7 @@ mbox_envelope_date (envelope_t envelope, char *buf, size_t len,
}
static int
mbox_envelope_from (envelope_t envelope, char *buf, size_t len,
mbox_envelope_sender (envelope_t envelope, char *buf, size_t len,
size_t *pnwrite)
{
message_t msg = envelope_get_owner (envelope);
......@@ -1174,7 +1176,7 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg)
message_destroy (&msg, mum);
return status;
}
envelope_set_from (envelope, mbox_envelope_from, msg);
envelope_set_sender (envelope, mbox_envelope_sender, msg);
envelope_set_date (envelope, mbox_envelope_date, msg);
message_set_envelope (msg, envelope, mum);
}
......@@ -1222,8 +1224,8 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
switch (mud->state)
{
case MBOX_NO_STATE:
mud->from = calloc (128, sizeof (char));
if (mud->from == NULL)
mud->sender = calloc (128, sizeof (char));
if (mud->sender == NULL)
{
locker_unlock (mailbox->locker);
monitor_unlock (mailbox->monitor);
......@@ -1232,8 +1234,8 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
mud->date = calloc (128, sizeof (char));
if (mud->date == NULL)
{
free (mud->from);
mud->from = NULL;
free (mud->sender);
mud->sender = NULL;
mud->state = MBOX_NO_STATE;
locker_unlock (mailbox->locker);
monitor_unlock (mailbox->monitor);
......@@ -1249,14 +1251,14 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
size_t len = 0;
envelope_t envelope;
message_get_envelope (msg, &envelope);
status = envelope_from (envelope, mud->from, 127, &len);
status = envelope_sender (envelope, mud->sender, 127, &len);
if (status != 0)
{
if (status != EAGAIN)
{
free (mud->from);
free (mud->sender);
free (mud->date);
mud->date = mud->from = NULL;
mud->date = mud->sender = NULL;
mud->state = MBOX_NO_STATE;
locker_unlock (mailbox->locker);
}
......@@ -1264,7 +1266,7 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
return status;
}
/* Nuke trailing newline. */
s = memchr (mud->from, nl, len);
s = memchr (mud->sender, nl, len);
if (s)
*s = '\0';
mud->state = MBOX_STATE_DATE;
......@@ -1282,9 +1284,9 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
{
if (status != EAGAIN)
{
free (mud->from);
free (mud->sender);
free (mud->date);
mud->date = mud->from = NULL;
mud->date = mud->sender = NULL;
mud->state = MBOX_NO_STATE;
locker_unlock (mailbox->locker);
}
......@@ -1298,7 +1300,7 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
/* Write the separator to the mailbox. */
stream_write (mailbox->stream, "From ", 5, size, &n);
size += n;
stream_write (mailbox->stream, mud->from, strlen (mud->from), size, &n);
stream_write (mailbox->stream, mud->sender, strlen (mud->sender), size, &n);
size += n;
stream_write (mailbox->stream, " ", 1, size, &n);
size += n;
......@@ -1306,9 +1308,9 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
size += n;
stream_write (mailbox->stream, &nl , 1, size, &n);
size += n;
free (mud->from);
free (mud->sender);
free (mud->date);
mud->from = mud->date = NULL;
mud->sender = mud->date = NULL;
mud->state = MBOX_STATE_APPEND;
}
......@@ -1327,9 +1329,9 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
{
if (status != EAGAIN)
{
free (mud->from);
free (mud->sender);
free (mud->date);
mud->date = mud->from = NULL;
mud->date = mud->sender = NULL;
mud->state = MBOX_NO_STATE;
locker_unlock (mailbox->locker);
}
......
......@@ -37,7 +37,7 @@ static int message_read (stream_t is, char *buf, size_t buflen,
static int message_write (stream_t os, const char *buf, size_t buflen,
off_t off, size_t *pnwrite);
static int message_get_fd (stream_t stream, int *pfd);
static int message_from (envelope_t envelope, char *buf, size_t len,
static int message_sender (envelope_t envelope, char *buf, size_t len,
size_t *pnwrite);
static int message_date (envelope_t envelope, char *buf, size_t len,
size_t *pnwrite);
......@@ -54,7 +54,7 @@ message_create (message_t *pmsg, void *owner)
msg = calloc (1, sizeof (*msg));
if (msg == NULL)
return ENOMEM;
status = monitor_create (&(msg->monitor), msg);
status = monitor_create (&(msg->monitor), 0, msg);
if (status != 0)
{
free (msg);
......@@ -355,7 +355,7 @@ message_get_envelope (message_t msg, envelope_t *penvelope)
monitor_unlock (msg->monitor);
return status;
}
envelope_set_from (envelope, message_from, msg);
envelope_set_sender (envelope, message_sender, msg);
envelope_set_date (envelope, message_date, msg);
msg->envelope = envelope;
}
......@@ -811,7 +811,7 @@ message_date (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
}
static int
message_from (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
message_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
{
message_t msg = envelope_get_owner (envelope);
header_t header = NULL;
......@@ -826,19 +826,19 @@ message_from (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
status = header_get_value (header, MU_HEADER_FROM, NULL, 0, &n);
if (status == 0 && n != 0)
{
char *from;
char *sender;
char *addr;
from = calloc (1, n + 1);
if (from == NULL)
sender = calloc (1, n + 1);
if (sender == NULL)
return ENOMEM;
addr = calloc (1, n + 1);
if (addr == NULL)
{
free (from);
free (sender);
return ENOMEM;
}
header_get_value (header, MU_HEADER_FROM, from, n + 1, NULL);
if (parseaddr (from, addr, n + 1) == 0)
header_get_value (header, MU_HEADER_FROM, sender, n + 1, NULL);
if (parseaddr (sender, addr, n + 1) == 0)
{
size_t i = strlen (addr);
n = (i > len) ? len : i;
......@@ -848,13 +848,13 @@ message_from (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
buf[n] = '\0';
}
free (addr);
free (from);
free (sender);
if (pnwrite)
*pnwrite = n;
return 0;
}
free (addr);
free (from);
free (sender);
}
else if (status == EAGAIN)
return status;
......
......@@ -17,27 +17,81 @@
#include <errno.h>
#include <stdlib.h>
#ifdef HAVE_PTHREAD_H
# define __USE_UNIX98
# include <pthread.h>
#endif
#include <monitor0.h>
#ifdef WITH_PTHREAD
pthread_mutex_t monitor_lock = PTHREAD_MUTEX_INITIALIZER;
#define STATIC_LOCK(m) pthread_mutex_lock(m)
#define STATIC_UNLOCK(m) pthread_mutex_unlock(m)
#else
#define STATIC_LOCK(m) 0
#define STATIC_UNLOCK(m) 0
int monitor_lock;
#endif
union _p_lock
{
#ifdef WITH_PTHREAD
# ifdef USE_RWLOCK
pthread_rwlock_t mutex;
# else
pthread_mutex_t mutex;
# endif
#endif
int dummy;
};
typedef union _p_lock *p_lock_t;
static int monitor_pthread_create (p_lock_t *);
static void monitor_pthread_destroy (p_lock_t *);
static int monitor_pthread_rdlock (p_lock_t);
static int monitor_pthread_wrlock (p_lock_t);
static int monitor_pthread_unlock (p_lock_t);
/* The idea was to have a general/portable object monitor_t.
The monitor_t object could have different implementation (on the fly ?)
of locking. Also the rest of the library would not have to know about
different threading implementation. So far we've pretty much hardcoded
the concrete implementation of monitor on pthread and read/write locks,
but changing to a different concrete implementation will not be hard if
the need arise.
For static initializers we take a small penality and since we have
a global static lock.
*/
int
monitor_create (monitor_t *pmonitor, void *owner)
monitor_create (monitor_t *pmonitor, int flags, void *owner)
{
monitor_t monitor;
int status = 0;
if (pmonitor == NULL)
return EINVAL;
monitor = calloc (1, sizeof (*monitor));
if (monitor == NULL)
return ENOMEM;
monitor->owner = owner;
status = RWLOCK_INIT (&(monitor->lock), NULL);
if (status != 0)
if (flags == MU_MONITOR_PTHREAD)
{
free (monitor);
return status;
int status = monitor_pthread_create ((p_lock_t *)&(monitor->data));
if (status != 0)
{
free (monitor);
return status;
}
}
monitor->owner = owner;
monitor->allocated = 1;
monitor->flags = flags;
*pmonitor = monitor;
return status;
return 0;
}
void *
......@@ -54,7 +108,8 @@ monitor_destroy (monitor_t *pmonitor, void *owner)
monitor_t monitor = *pmonitor;
if (monitor->owner == owner)
{
RWLOCK_DESTROY (&(monitor->lock));
if (monitor->flags == MU_MONITOR_PTHREAD)
monitor_pthread_destroy ((p_lock_t *)&(monitor->data));
}
free (monitor);
*pmonitor = NULL;
......@@ -66,7 +121,24 @@ monitor_rdlock (monitor_t monitor)
{
if (monitor)
{
return RWLOCK_RDLOCK (&(monitor->lock));
if (!monitor->allocated)
{
int status = STATIC_LOCK (&monitor_lock);
if (monitor->data == NULL)
{
if (monitor->flags == MU_MONITOR_PTHREAD)
status = monitor_pthread_create ((p_lock_t*)&(monitor->data));
if (status != 0)
{
STATIC_UNLOCK (&monitor_lock);
return status;
}
}
monitor->allocated = 1;
STATIC_UNLOCK (&monitor_lock);
}
if (monitor->flags == MU_MONITOR_PTHREAD)
return monitor_pthread_rdlock ((p_lock_t)monitor->data);
}
return 0;
}
......@@ -76,7 +148,24 @@ monitor_wrlock (monitor_t monitor)
{
if (monitor)
{
return RWLOCK_WRLOCK (&(monitor->lock));
if (!monitor->allocated)
{
int status = STATIC_LOCK (&monitor_lock);
if (monitor->data == NULL)
{
if (monitor->flags == MU_MONITOR_PTHREAD)
status = monitor_pthread_create ((p_lock_t *)&(monitor->data));
if (status != 0)
{
STATIC_UNLOCK (&monitor_lock);
return status;
}
}
monitor->allocated = 1;
STATIC_UNLOCK (&monitor_lock);
}
if (monitor->flags == MU_MONITOR_PTHREAD)
return monitor_pthread_wrlock ((p_lock_t)monitor->data);
}
return 0;
}
......@@ -86,7 +175,8 @@ monitor_unlock (monitor_t monitor)
{
if (monitor)
{
return RWLOCK_UNLOCK (&(monitor->lock));
if (monitor->flags == MU_MONITOR_PTHREAD)
return monitor_pthread_unlock ((p_lock_t)monitor->data);
}
return 0;
}
......@@ -104,3 +194,86 @@ monitor_notify (monitor_t monitor)
(void)monitor;
return ENOSYS;
}
/* Concrete Implementation of pthread base on rwlocks. */
#define USE_RWLOCK
#ifdef WITH_PTHREAD
# ifdef USE_RWLOCK
# define RWLOCK_INIT(rwl, attr) pthread_mutex_init (rwl, attr)
# define RWLOCK_DESTROY(rwl) pthread_mutex_destroy (rwl)
# define RWLOCK_RDLOCK(rwl) pthread_mutex_lock (rwl)
# define RWLOCK_TRYRDLOCK(rwl) pthread_mutex_trylock (rwl)
# define RWLOCK_WRLOCK(rwl) pthread_mutex_lock (rwl)
# define RWLOCK_TRYWRLOCK(rwl) pthread_mutex_trylock (rwl)
# define RWLOCK_UNLOCK(rwl) pthread_mutex_unlock (rwl)
# else
# define RWLOCK_INIT(rwl, attr) pthread_rwlock_init (rwl, attr)
# define RWLOCK_DESTROY(rwl) pthread_rwlock_destroy (rwl)
# define RWLOCK_RDLOCK(rwl) pthread_rwlock_rdlock (rwl)
# define RWLOCK_TRYRDLOCK(rwl) pthread_rwlock_tryrdlock (rwl)
# define RWLOCK_WRLOCK(rwl) pthread_rwlock_wrlock (rwl)
# define RWLOCK_TRYWRLOCK(rwl) pthread_rwlock_trywrlock (rwl)
# define RWLOCK_UNLOCK(rwl) pthread_rwlock_unlock (rwl)
# endif
#else
# define RWLOCK_INIT(rwl, attr) 0
# define RWLOCK_DESTROY(rwl) 0
# define RWLOCK_RDLOCK(rwl) 0
# define RWLOCK_TRYRDLOCK(rwl) 0
# define RWLOCK_WRLOCK(rwl) 0
# define RWLOCK_TRYWRLOCK(rwl) 0
# define RWLOCK_UNLOCK(rwl) 0
# define flockfile(arg) 0
# define funlockfile(arg) 0
#endif
static int
monitor_pthread_create (p_lock_t *plock)
{
int status;
p_lock_t lock = calloc (1, sizeof (*lock));
if (lock == NULL)
return ENOMEM;
status = RWLOCK_INIT (&(lock->mutex), NULL);
if (status != 0)
{
free (lock);
return status;
}
*plock = lock;
return 0;
}
static void
monitor_pthread_destroy (p_lock_t *plock)
{
p_lock_t lock = *plock;
if (lock)
{
RWLOCK_DESTROY (&(lock->mutex));
free (lock);
}
*plock = NULL;
}
static int
monitor_pthread_rdlock (p_lock_t lock)
{
return RWLOCK_RDLOCK (&(lock->mutex));
}
static int
monitor_pthread_wrlock (p_lock_t lock)
{
return RWLOCK_WRLOCK (&(lock->mutex));
}
static int
monitor_pthread_unlock (p_lock_t lock)
{
return RWLOCK_UNLOCK (&(lock->mutex));
}
......
......@@ -24,22 +24,42 @@
#include <errno.h>
#include <mailutils/iterator.h>
#include <mailutils/monitor.h>
#include <registrar0.h>
static list_t reg_list;
/* NOTE: We will leak here since the monitor and the registrar will never
be release. */
static list_t registrar_list;
struct _monitor registrar_monitor = MU_MONITOR_INITIALIZER;
int
registrar_get_list (list_t *plist)
{
int status = 0;
if (plist == NULL)
return EINVAL;
if (reg_list == NULL)
{
int status = list_create (&reg_list);
if (status != 0)
return status;
}
*plist = reg_list;
monitor_wrlock (&registrar_monitor);
if (registrar_list == NULL)
status = list_create (&registrar_list);
*plist = registrar_list;
monitor_unlock (&registrar_monitor);
return status;
}
int
registrar_record (record_t record)
{
list_t list;
registrar_get_list (&list);
return list_append (list, record);
}
int
unregistrar_record (record_t record)
{
list_t list;
registrar_get_list (&list);
list_remove (list, record);
return 0;
}
......@@ -53,8 +73,9 @@ record_is_scheme (record_t record, const char *scheme)
if (record->_is_scheme)
return record->_is_scheme (record, scheme);
if (record->scheme && strncasecmp (record->scheme, scheme,
strlen (record->scheme)) == 0)
if (scheme
&& record->scheme
&& strncasecmp (record->scheme, scheme, strlen (record->scheme)) == 0)
return 1;
return 0;
......