Commit 18406256 18406256a580340a70c9f5ef452f7b79621529d8 by Alain Magloire

Making the library more thread aware. This is an attempt to be Cancel-safe

or at least cancel friendly.
1 parent 06aea14d
......@@ -21,13 +21,39 @@
#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 <misc.h>
#include <folder0.h>
#ifdef WITH_PTHREAD
static pthread_mutex_t slock = PTHREAD_MUTEX_INITIALIZER;
#endif
/* Internal folder list. */
static list_t known_folder_list;
static int is_known_folder (url_t, folder_t *);
static int is_same_scheme (url_t, url_t);
static int is_same_user (url_t, url_t);
static int is_same_path (url_t, url_t);
static int is_same_host (url_t, url_t);
static int is_same_port (url_t, url_t);
/* A folder could be a remote one, IMAP, or local, a spool directory
like $HOME/Mail etc .. We maintain a known list of folder to
not generate multiple folder of the same URL. Meaning when
folder_create () is call we'll check if we already have a
folder for that URL and return the same, if not we create a new one.
The downside, the algo to detect the same URL is very weak, and
they maybe cases where you want a different folder for the same
URL, there is not easy way to do this. */
int
folder_create (folder_t *pfolder, const char *name)
{
......@@ -41,7 +67,7 @@ folder_create (folder_t *pfolder, const char *name)
if (pfolder == NULL)
return EINVAL;
/* Look in the registrar, for a match */
/* Look in the registrar list(iterator), for a match */
registrar_get_list (&list);
status = iterator_create (&iterator, list);
if (status != 0)
......@@ -67,38 +93,63 @@ folder_create (folder_t *pfolder, const char *name)
url_t url = NULL;
folder_t folder = NULL;
/* Allocate memory for mbox. */
folder = calloc (1, sizeof (*folder));
if (folder == NULL)
return ENOMEM;
/* Initialize the internal lock, now so the concrete mailbox
could use it. */
status = RWLOCK_INIT (&(folder->rwlock), NULL);
if (status != 0)
{
folder_destroy (&folder);
return status;
}
/* Parse the url, it may be a bad one and we should bailout if this
failed. */
if ((status = url_create (&url, name)) != 0
if ((status = url_create (&url, name) != 0)
|| (status = entry->_url_init (url)) != 0)
{
folder_destroy (&folder);
return status;
#ifdef WITH_PTHREAD
pthread_mutex_lock (&slock);
#endif
/* 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
return 0;
}
folder->url = url;
#ifdef WITH_PTHREAD
else
pthread_mutex_unlock (&slock);
#endif
/* Create a new folder. */
/* Allocate memory for folder. */
folder = calloc (1, sizeof (*folder));
if (folder != NULL)
{
folder->url = url;
/* Initialize the internal lock, now so the concrete
folder could use it. */
status = monitor_create (&(folder->monitor), folder);
if (status == 0)
{
/* Create the concrete folder type. */
status = entry->_folder_init (folder);
if (status == 0)
{
*pfolder = folder;
folder->ref++;
/* Put on the internal list of known folders. */
list_append (known_folder_list, folder);
}
}
/* Something went wrong, destroy the object. */
if (status != 0)
{
folder_destroy (&folder);
if (folder->monitor)
monitor_destroy (&(folder->monitor), folder);
if (folder->url)
url_destroy (&(folder->url));
free (folder);
}
}
else
*pfolder = folder;
}
else
status = ENOENT;
......@@ -113,13 +164,26 @@ folder_destroy (folder_t *pfolder)
{
folder_t folder = *pfolder;
int destroy_lock = 0;
monitor_t monitor = folder->monitor;
size_t reference;
monitor_wrlock (monitor);
#ifdef WITH_PTHREAD
pthread_rwlock_t rwlock = folder->rwlock;
pthread_mutex_lock (&slock);
#endif
RWLOCK_WRLOCK (&(rwlock));
if (folder_decremente (folder) == 0)
{
RWLOCK_UNLOCK (&(rwlock));
folder->ref--;
reference = folder->ref;
/* Remove the folder from the list of known folder. */
if (reference == 0)
list_remove (known_folder_list, folder);
}
#ifdef WITH_PHTREAD
pthread_mutex_unlock (&slock);
#endif
if (reference == 0)
{
monitor_unlock (monitor);
destroy_lock = 1;
/* Notify the observers. */
if (folder->observable)
......@@ -129,7 +193,7 @@ folder_destroy (folder_t *pfolder)
}
if (folder->_destroy)
folder->_destroy (folder);
RWLOCK_WRLOCK (&(rwlock));
monitor_wrlock (monitor);
if (folder->ticket)
ticket_destroy (&(folder->ticket), folder);
if (folder->authority)
......@@ -140,9 +204,9 @@ folder_destroy (folder_t *pfolder)
url_destroy (&(folder->url));
free (folder);
}
RWLOCK_UNLOCK (&(rwlock));
monitor_unlock (monitor);
if (destroy_lock)
RWLOCK_DESTROY (&(rwlock));
monitor_destroy (&monitor, folder);
*pfolder = NULL;
}
}
......@@ -281,10 +345,144 @@ folder_delete_mailbox (folder_t folder, const char *name)
return folder->_delete_mailbox (folder, name);
}
int
folder_decremente (folder_t folder)
static int is_known_folder (url_t url, folder_t *pfolder)
{
if (folder && folder->_decremente)
return folder->_decremente (folder);
return (folder->ref--);
int ret = 0;
folder_t folder = NULL;
iterator_t iterator;
if (url == NULL || pfolder == NULL)
return ret;
if (iterator_create (&iterator, known_folder_list) != 0)
return ret;
for (iterator_first (iterator); !iterator_is_done (iterator);
iterator_next (iterator))
{
iterator_current (iterator, (void **)&folder);
/* Check if the same URL type. */
if (folder && folder->url
&& is_same_scheme (url, folder->url)
&& is_same_user (url, folder->url)
&& is_same_path (url, folder->url)
&& is_same_host (url, folder->url)
&& is_same_port (url, folder->url))
{
ret = 1;
break;
}
}
iterator_destroy (&iterator);
return ret;
}
static int
is_same_scheme (url_t url1, url_t url2)
{
int i = 0, j = 0;
char *s1, *s2;
int ret = 1;
url_get_scheme (url1, NULL, 0, &i);
url_get_scheme (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_scheme (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_scheme (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
static int
is_same_user (url_t url1, url_t url2)
{
int i = 0, j = 0;
char *s1, *s2;
int ret = 0;
url_get_user (url1, NULL, 0, &i);
url_get_user (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_user (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_user (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
static int
is_same_path (url_t url1, url_t url2)
{
int i = 0, j = 0;
char *s1, *s2;
int ret = 0;
url_get_path (url1, NULL, 0, &i);
url_get_path (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_path (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_path (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
static int
is_same_host (url_t url1, url_t url2)
{
int i = 0, j = 0;
char *s1, *s2;
int ret = 0;
url_get_host (url1, NULL, 0, &i);
url_get_host (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_host (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_host (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
static int
is_same_port (url_t url1, url_t url2)
{
long p1 = 0, p2 = 0;
url_get_port (url1, &p1);
url_get_port (url2, &p2);
return (p1 == p2);
}
......
......@@ -22,14 +22,10 @@
# include <dmalloc.h>
#endif
#ifdef HAVE_PTHREAD_H
# define __USE_UNIX98 /* ?? */
# include <pthread.h>
#endif
#include <sys/types.h>
#include <stdio.h>
#include <mailutils/monitor.h>
#include <mailutils/folder.h>
#ifdef __cplusplus
......@@ -52,15 +48,12 @@ struct _folder
observable_t observable;
debug_t debug;
stream_t stream;
monitor_t monitor;
url_t url;
int flags;
size_t ref;
size_t uid;
#ifdef WITH_PTHREAD
pthread_rwlock_t rwlock;
#endif
/* Back pointer to the specific mailbox */
void *data;
......@@ -73,13 +66,8 @@ struct _folder
int (*_close) __P ((folder_t));
int (*_list) __P ((folder_t, list_t *));
int (*_delete_mailbox) __P ((folder_t, const char *));
int (*_decremente) __P ((folder_t));
};
/* To manipulate mailbox rwlock. */
extern int folder_rdlock __P ((folder_t));
extern int folder_wrlock __P ((folder_t));
extern int folder_unlock __P ((folder_t));
#ifdef __cplusplus
}
......
......@@ -22,13 +22,10 @@
# include <dmalloc.h>
#endif
#ifdef HAVE_PTHREAD_H
# define __USE_UNIX98 /* ?? */
# include <pthread.h>
#endif
#include <sys/types.h>
#include <mailutils/list.h>
#include <sys/types.h>
#include <mailutils/monitor.h>
#ifndef __P
......@@ -54,9 +51,7 @@ struct _list
{
struct list_data head;
size_t count;
#ifdef WITH_PTHREAD
pthread_rwlock_t rwlock;
#endif
monitor_t monitor;
};
......
......@@ -30,6 +30,7 @@
#include <sys/types.h>
#include <stdio.h>
#include <mailutils/monitor.h>
#include <mailutils/mailbox.h>
#include <mailutils/folder.h>
......@@ -57,10 +58,7 @@ struct _mailbox
url_t url;
folder_t folder;
int flags;
#ifdef WITH_PTHREAD
pthread_rwlock_t rwlock;
#endif
monitor_t monitor;
/* Back pointer to the specific mailbox */
void *data;
......@@ -86,11 +84,6 @@ struct _mailbox
};
/* To manipulate mailbox rwlock. */
extern int mailbox_rdlock __P ((mailbox_t));
extern int mailbox_wrlock __P ((mailbox_t));
extern int mailbox_unlock __P ((mailbox_t));
#define MAILBOX_NOTIFY(mbox, type) \
if (mbox->observer) observer_notify (mbox->observer, type)
......
/* 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 General Library 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. */
#ifndef _MONITOR0_H
#define _MONITOR0_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <mailutils/monitor.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __P
# if __STDC__
# define __P(x) x
# else
# define __P(x)
# 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
#endif /* _MONITOR0_H */
......@@ -22,7 +22,6 @@
#include <errno.h>
#include <stdlib.h>
#include <misc.h>
#include <list0.h>
int
......@@ -35,7 +34,7 @@ list_create (list_t *plist)
list = calloc (sizeof (*list), 1);
if (list == NULL)
return ENOMEM;
status = RWLOCK_INIT (&(list->rwlock), NULL);
status = monitor_create (&(list->monitor), list);
if (status != 0)
{
free (list);
......@@ -55,15 +54,15 @@ list_destroy (list_t *plist)
list_t list = *plist;
struct list_data *current;
struct list_data *previous;
RWLOCK_WRLOCK (&(list->rwlock));
monitor_wrlock (list->monitor);
for (current = list->head.next; current != &(list->head);)
{
previous = current;
current = current->next;
free (previous);
}
RWLOCK_UNLOCK (&(list->rwlock));
RWLOCK_DESTROY (&(list->rwlock));
monitor_unlock (list->monitor);
monitor_destroy (&(list->monitor), list);
free (list);
*plist = NULL;
}
......@@ -78,13 +77,13 @@ list_append (list_t list, void *item)
if (ldata == NULL)
return ENOMEM;
ldata->item = item;
RWLOCK_WRLOCK (&(list->rwlock));
monitor_wrlock (list->monitor);
ldata->next = &(list->head);
ldata->prev = list->head.prev;
last->next = ldata;
list->head.prev = ldata;
list->count++;
RWLOCK_UNLOCK (&(list->rwlock));
monitor_unlock (list->monitor);
return 0;
}
......@@ -97,13 +96,13 @@ list_prepend (list_t list, void *item)
if (ldata == NULL)
return ENOMEM;
ldata->item = item;
RWLOCK_WRLOCK (&(list->rwlock));
monitor_wrlock (list->monitor);
ldata->prev = &(list->head);
ldata->next = list->head.next;
first->prev = ldata;
list->head.next = ldata;
list->count++;
RWLOCK_UNLOCK (&(list->rwlock));
monitor_unlock (list->monitor);
return 0;
}
......@@ -130,7 +129,7 @@ list_remove (list_t list, void *item)
struct list_data *current, *previous;
if (list == NULL)
return EINVAL;
RWLOCK_WRLOCK (&(list->rwlock));
monitor_wrlock (list->monitor);
for (previous = &(list->head), current = list->head.next;
current != &(list->head); previous = current, current = current->next)
{
......@@ -140,11 +139,11 @@ list_remove (list_t list, void *item)
current->next->prev = previous;
free (current);
list->count--;
RWLOCK_UNLOCK (&(list->rwlock));
monitor_unlock (list->monitor);
return 0;
}
}
RWLOCK_UNLOCK (&(list->rwlock));
monitor_unlock (list->monitor);
return ENOENT;
}
......@@ -155,17 +154,17 @@ list_get (list_t list, size_t index, void **pitem)
size_t count;
if (list == NULL || pitem == NULL)
return EINVAL;
RWLOCK_RDLOCK (&(list->rwlock));
monitor_rdlock (list->monitor);
for (current = list->head.next, count = 0; current != &(list->head);
current = current->next, count++)
{
if (count == index)
{
*pitem = current->item;
RWLOCK_UNLOCK (&(list->rwlock));
monitor_unlock (list->monitor);
return 0;
}
}
RWLOCK_UNLOCK (&(list->rwlock));
monitor_unlock (list->monitor);
return ENOENT;
}
......
......@@ -22,10 +22,8 @@
#include <stdlib.h>
#include <errno.h>
#include <mailutils/locker.h>
#include <mailutils/iterator.h>
#include <mailutils/registrar.h>
#include <misc.h>
#include <mailbox0.h>
/* The Mailbox Factory.
......@@ -77,9 +75,9 @@ mailbox_create (mailbox_t *pmbox, const char *name)
if (mbox == NULL)
return ENOMEM;
/* Initialize the internal lock, now so the concrete mailbox
/* Initialize the internal lock now, so the concrete mailbox
could use it. */
status = RWLOCK_INIT (&(mbox->rwlock), NULL);
status = monitor_create (&(mbox->monitor), mbox);
if (status != 0)
{
mailbox_destroy (&mbox);
......@@ -117,9 +115,7 @@ mailbox_destroy (mailbox_t *pmbox)
if (pmbox && *pmbox)
{
mailbox_t mbox = *pmbox;
#ifdef WITH_PTHREAD
pthread_rwlock_t rwlock = mbox->rwlock;
#endif
monitor_t monitor = mbox->monitor;
/* Notify the observers. */
if (mbox->observable)
......@@ -132,7 +128,7 @@ mailbox_destroy (mailbox_t *pmbox)
if (mbox->_destroy)
mbox->_destroy (mbox);
RWLOCK_WRLOCK (&(rwlock));
monitor_wrlock (monitor);
/* Nuke the stream and close it */
if (mbox->stream)
......@@ -161,8 +157,8 @@ mailbox_destroy (mailbox_t *pmbox)
free (mbox);
*pmbox = NULL;
RWLOCK_UNLOCK (&(rwlock));
RWLOCK_DESTROY (&(rwlock));
monitor_unlock (monitor);
monitor_destroy (&monitor, mbox);
}
}
......@@ -317,7 +313,7 @@ mailbox_set_stream (mailbox_t mbox, stream_t stream)
int
mailbox_get_stream (mailbox_t mbox, stream_t *pstream)
{
if (mbox == NULL || pstream == NULL)
if (mbox == NULL || pstream)
return EINVAL;
*pstream = mbox->stream;
return 0;
......@@ -364,42 +360,3 @@ mailbox_get_debug (mailbox_t mbox, debug_t *pdebug)
*pdebug = mbox->debug;
return 0;
}
/* Mailbox Internal Locks. Put the name of the functions in parenteses To make
sure it will not be redefine by a macro. If the flags was non-blocking we
should not block on the lock, so we try with pthread_rwlock_try*lock(). */
int
(mailbox_rdlock) (mailbox_t mbox)
{
#ifdef WITH_PTHREAD
int err = (mbox->flags & MU_STREAM_NONBLOCK) ?
RWLOCK_TRYRDLOCK (&(mbox->rwlock)) :
RWLOCK_RDLOCK (&(mbox->rwlock)) ;
if (err != 0 && err != EDEADLK)
return err;
#endif
return 0;
}
int
(mailbox_wrlock) (mailbox_t mbox)
{
#ifdef WITH_PTHREAD
int err = (mbox->flags & MU_STREAM_NONBLOCK) ?
RWLOCK_TRYWRLOCK (&(mbox->rwlock)) :
RWLOCK_WRLOCK (&(mbox->rwlock)) ;
if (err != 0 && err != EDEADLK)
return err;
#endif
return 0;
}
int
(mailbox_unlock) (mailbox_t mbox)
{
#ifdef WITH_PTHREAD
return RWLOCK_UNLOCK (&(mbox->rwlock));
#else
return 0;
#endif
}
......
......@@ -191,17 +191,17 @@ do \
do \
{ \
int bailing = 0; \
mailbox_unlock (mbox); \
monitor_unlock (mbox->monitor); \
if (mbox->observable) \
bailing = observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD); \
if (bailing != 0) \
{ \
if (pcount) \
*pcount = (mud)->messages_count; \
mbox_unlock (mbox); \
locker_unlock (mbox->locker); \
return EINTR; \
} \
mailbox_wrlock (mbox); \
monitor_wrlock (mbox->monitor); \
} while (0);
/* Notification MBX_PROGRESS
......@@ -215,7 +215,7 @@ do \
{ \
{ \
int bailing = 0; \
mailbox_unlock (mbox); \
monitor_unlock (mbox->monitor); \
mud->messages_count--; \
if (mbox->observable) \
bailing = observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS); \
......@@ -223,11 +223,11 @@ do \
{ \
if (pcount) \
*pcount = (mud)->messages_count; \
mbox_unlock (mbox); \
locker_unlock (mbox->locker); \
return EINTR; \
} \
mud->messages_count++; \
mailbox_wrlock (mbox); \
monitor_wrlock (mbox->monitor); \
} \
} while (0)
......@@ -243,16 +243,16 @@ do \
m = realloc ((mud)->umessages, num * sizeof (*m)); \
if (m == NULL) \
{ \
mbox_unlock (mbox); \
mailbox_unlock (mbox); \
locker_unlock (mbox->locker); \
monitor_unlock (mbox->monitor); \
return ENOMEM; \
} \
(mud)->umessages = m; \
(mud)->umessages[num - 1] = calloc (1, sizeof (*(mum))); \
if ((mud)->umessages[num - 1] == NULL) \
{ \
mbox_unlock (mbox); \
mailbox_unlock (mbox); \
locker_unlock (mbox->locker); \
monitor_unlock (mbox->monitor); \
return ENOMEM; \
} \
(mud)->umessages_count = num; \
......@@ -282,17 +282,23 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
return EINVAL;
/* Grab the lock. */
mailbox_wrlock (mailbox);
monitor_wrlock (mailbox->monitor);
#ifdef WITH_PTHREAD
/* read() is cancellation point since we're doing a potentially
long operation. Lets make sure we clean the state. */
pthread_cleanup_push (mbox_cleanup, (void *)mailbox);
#endif
/* Save the timestamp and size. */
status = stream_size (mailbox->stream, &(mud->size));
if (status != 0)
{
mailbox_unlock (mailbox);
monitor_unlock (mailbox->monitor);
return status;
}
mbox_lock (mailbox, MU_LOCKER_RDLOCK);
locker_lock (mailbox->locker, MU_LOCKER_RDLOCK);
/* Seek to the starting point. */
if (mud->umessages && msgno > 0 && mud->messages_count > 0
......@@ -376,7 +382,7 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
/* Every 50 mesgs update the lock, it should be every minute. */
if ((mud->messages_count % 50) == 0)
mbox_touchlock (mailbox);
locker_touchlock (mailbox->locker);
/* Ping them every 1000 lines. */
if (do_notif)
......@@ -392,9 +398,13 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
if (do_notif)
DISPATCH_ADD_MSG(mailbox, mud);
}
mbox_unlock (mailbox);
if (pcount)
*pcount = mud->messages_count;
mailbox_unlock (mailbox);
locker_unlock (mailbox->locker);
monitor_unlock (mailbox->monitor);
#ifdef WITH_PTHREAD
pthread_cleanup_pop (0);
#endif
return status;
}
......
......@@ -189,7 +189,7 @@ struct _pop_data
#define CHECK_BUSY(mbox, mpd, function, identity) \
do \
{ \
int err = mailbox_wrlock (mbox); \
int err = monitor_wrlock (mbox->monitor); \
if (err != 0) \
return err; \
if ((mpd->func && mpd->func != function) \
......@@ -198,7 +198,7 @@ do \
mpd->id = 0; \
mpd->func = pop_open; \
mpd->state = POP_NO_STATE; \
mailbox_unlock (mbox); \
monitor_unlock (mbox->monitor); \
err = pop_open (mbox, mbox->flags); \
if (err != 0) \
{ \
......@@ -209,7 +209,7 @@ do \
{ \
mpd->id = (size_t)identity; \
mpd->func = func; \
mailbox_unlock (mbox); \
monitor_unlock (mbox->monitor); \
} \
} \
while (0)
......@@ -301,7 +301,7 @@ pop_destroy (mailbox_t mbox)
{
pop_data_t mpd = mbox->data;
size_t i;
mailbox_wrlock (mbox);
monitor_wrlock (mbox->monitor);
/* Destroy the pop messages and ressources associated to them. */
for (i = 0; i < mpd->pmessages_count; i++)
{
......@@ -320,7 +320,7 @@ pop_destroy (mailbox_t mbox)
free (mpd->pmessages);
free (mpd);
mbox->data = NULL;
mailbox_unlock (mbox);
monitor_unlock (mbox->monitor);
}
}
......@@ -545,12 +545,12 @@ pop_close (mailbox_t mbox)
return EINVAL;
/* CHECK_BUSY (mbox, mpd, func, 0); */
mailbox_wrlock (mbox);
monitor_wrlock (mbox->monitor);
if (mpd->func && mpd->func != func)
mpd->state = POP_NO_STATE;
mpd->id = 0;
mpd->func = func;
mailbox_unlock (mbox);
monitor_unlock (mbox->monitor);
/* Ok boys, it's a wrap: UPDATE State. */
switch (mpd->state)
......@@ -625,7 +625,7 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
if (pmsg == NULL || mpd == NULL)
return EINVAL;
mailbox_rdlock (mbox);
monitor_rdlock (mbox->monitor);
/* See if we have already this message. */
for (i = 0; i < mpd->pmessages_count; i++)
{
......@@ -634,12 +634,12 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
if (mpd->pmessages[i]->num == msgno)
{
*pmsg = mpd->pmessages[i]->message;
mailbox_unlock (mbox);
monitor_unlock (mbox->monitor);
return 0;
}
}
}
mailbox_unlock (mbox);
monitor_unlock (mbox->monitor);
mpm = calloc (1, sizeof (*mpm));
if (mpm == NULL)
......@@ -724,7 +724,7 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
message_set_uidl (msg, pop_uidl, mpm);
/* Add it to the list. */
mailbox_wrlock (mbox);
monitor_wrlock (mbox->monitor);
{
pop_message_t *m ;
m = realloc (mpd->pmessages, (mpd->pmessages_count + 1)*sizeof (*m));
......@@ -732,14 +732,14 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
{
message_destroy (&msg, mpm);
free (mpm);
mailbox_unlock (mbox);
monitor_unlock (mbox->monitor);
return ENOMEM;
}
mpd->pmessages = m;
mpd->pmessages[mpd->pmessages_count] = mpm;
mpd->pmessages_count++;
}
mailbox_unlock (mbox);
monitor_unlock (mbox->monitor);
/* Save The message. */
*pmsg = mpm->message = msg;
......
......@@ -21,6 +21,8 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <mailutils/message.h>
#include <mailutils/stream.h>
......@@ -463,9 +465,9 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
return 0;
message_get_stream(mime->mtp_parts[mime->cur_part]->msg, &msg_stream);
} else {
body_t body;
message_get_body(mime->mtp_parts[mime->cur_part]->msg, &body);
body_get_stream(body, &msg_stream);
body_t b;
message_get_body(mime->mtp_parts[mime->cur_part]->msg, &b);
body_get_stream(b, &msg_stream);
}
ret = stream_read(msg_stream, buf, buflen, mime->part_offset, &part_nbytes );
len += part_nbytes;
......
/* 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 General Library 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. */
#include <errno.h>
#include <stdlib.h>
#include <monitor0.h>
int
monitor_create (monitor_t *pmonitor, 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)
{
free (monitor);
return status;
}
*pmonitor = monitor;
return status;
}
void *
monitor_get_owner (monitor_t monitor)
{
return (monitor == NULL) ? NULL : monitor->owner;
}
void
monitor_destroy (monitor_t *pmonitor, void *owner)
{
if (pmonitor && *pmonitor)
{
monitor_t monitor = *pmonitor;
if (monitor->owner == owner)
{
RWLOCK_DESTROY (&(monitor->lock));
}
free (monitor);
*pmonitor = NULL;
}
}
int
monitor_rdlock (monitor_t monitor)
{
if (monitor)
{
return RWLOCK_RDLOCK (&(monitor->lock));
}
return 0;
}
int
monitor_wrlock (monitor_t monitor)
{
if (monitor)
{
return RWLOCK_WRLOCK (&(monitor->lock));
}
return 0;
}
int
monitor_unlock (monitor_t monitor)
{
if (monitor)
{
return RWLOCK_UNLOCK (&(monitor->lock));
}
return 0;
}
int
monitor_wait (monitor_t monitor)
{
(void)monitor;
return ENOSYS;
}
int
monitor_notify (monitor_t monitor)
{
(void)monitor;
return ENOSYS;
}