/*
* queue.c: Based on Pan's queue.[ch]
*
* $Id: queue.c,v 1.22 2000/05/19 14:51:46 sc Exp $
*/
/* Copyright (C) 1999-2000 Sergey Chernikov (sc@ivvs.ul.ru)
*
* Authors: Sergey Chernikov <sc@ivvs.ul.ru>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "grn_consts.h"
#include <pthread.h>
#include <sys/time.h>
#include <errno.h>
#include <gnome.h>
#include "grn_vars.h"
#include "grn_misc.h"
#include "grn_util.h"
#include "grn_config.h"
#include "grn_news.h"
#include "tcp.h"
#include "smtp.h"
#include "queue.h"
#include "grn_nglist.h"
#include "grn_threadlist.h"
#include "grn_msgwin.h"
GSList *queue = NULL, *queue_last = NULL;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t qcond_m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t qcond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t groups_m = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t ogroup_m = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t omsg_m = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t pmsg_m = PTHREAD_MUTEX_INITIALIZER;
static gboolean grnq_run_download_grouplist(grnq_data *);
static gboolean grnq_run_download_msghdrlist(grnq_data *);
static gboolean grnq_run_download_article(grnq_data *);
static gboolean grnq_run_post_article(grnq_data *);
static gboolean grnq_run_grouplist_recalc(grnq_data *);
static gboolean grnq_run_threadlist_recalc(grnq_data *);
static gboolean grnq_run_send_message(grnq_data *);
static gboolean grnq_run_draw_grouplist(grnq_data *);
static gboolean grnq_run_draw_msglist(grnq_data *);
static gboolean grnq_run_draw_msglist1(grnq_data *);
static gboolean grnq_run_draw_article(grnq_data *);
void grnq_init(void)
{
pthread_create(&(GRN->tid_queue), NULL, (void *) &grnq_processing, NULL);
pthread_detach(GRN->tid_queue);
}
void grnq_append(grnq_data *qdata)
{
GSList *l;
l = g_slist_alloc();
l->data = qdata;
if (queue)
{
g_assert(queue_last);
g_slist_concat(queue_last, l);
queue_last = l;
}
else queue = queue_last = l;
}
void grnq_prepend(grnq_data *qdata)
{
if (queue_last) queue = g_slist_prepend(queue, qdata);
else queue_last = queue = g_slist_prepend(queue, qdata);
}
grnq_data *grnq_get_next(void)
{
grnq_data *qdata = NULL;
pthread_mutex_lock(&qlock);
if (queue)
{
qdata = (grnq_data *) queue->data;
queue = g_slist_remove_link(queue, queue);
if (queue == NULL) queue_last = NULL;
}
pthread_mutex_unlock(&qlock);
return qdata;
}
static grnq_data *grnq_get_next_ro(void)
{
grnq_data *qdata = NULL;
pthread_mutex_lock(&qlock);
if (queue)
qdata = (grnq_data *) queue->data;
pthread_mutex_unlock(&qlock);
return qdata;
}
void grnq_processing(void)
{
struct timeval now;
struct timespec timeout;
int retcode = 0;
grnq_data *qdata;
time_t last_run, current_time;
while (1)
{
pthread_mutex_lock(&qcond_m);
gettimeofday(&now, NULL);
timeout.tv_sec = now.tv_sec + 230;
timeout.tv_nsec = now.tv_usec * 1000;
retcode = pthread_cond_timedwait(&qcond, &qcond_m, &timeout);
if ((retcode == ETIMEDOUT) && (queue == NULL))
{
if (nntp_is_online(GRN->nntp_sock))
{
gchar *rc = NULL;
time(¤t_time);
if ((current_time - last_run) > 300) nntp_offline(GRN->nntp_sock); //! disconnect_timeout to prefs
else rc = nntp_send_noop(GRN->nntp_sock);
if (rc) grn_error(_("NNTP noop"), rc);
}
}
else {
pthread_mutex_unlock(&qcond_m);
while ((qdata = grnq_get_next())) grnq_run(qdata, grnq_get_next_ro());
pthread_mutex_lock(&qcond_m);
time(&last_run);
}
pthread_mutex_unlock(&qcond_m);
}
}
void grnq_free(grnq_data *qdata)
{
t_message *m;
g_assert(qdata);
switch (qdata->flags & 0x003F)
{
case GRNQ_DOWNLOAD_GROUPLIST:
break;
case GRNQ_DOWNLOAD_MSGHDRLIST:
break;
case GRNQ_DOWNLOAD_ARTICLE:
break;
case GRNQ_POST_ARTICLE:
m = (t_message *) qdata->data;
t_message_free(&m);
break;
case GRNQ_GROUPLIST_RECALC:
break;
case GRNQ_THREADLIST_RECALC:
break;
case GRNQ_SEND_MESSAGE:
m = (t_message *) qdata->data;
t_message_free(&m);
break;
case GRNQ_DRAW_GROUPLIST:
break;
case GRNQ_DRAW_MSGLIST:
case GRNQ_DRAW_MSGLIST1:
break;
case GRNQ_DRAW_ARTICLE:
break;
default:
g_error(_("Some strange behavior of grnq_free()"));
break;
}
g_free(qdata);
}
gboolean grnq_run(grnq_data *qdata, grnq_data *qdata_next)
{
gboolean rc = TRUE;
gint f1=0, f2=0;
g_assert(qdata);
f1 = qdata->flags & 0x003F;
if (qdata_next) f2 = qdata_next->flags & 0x003F;
if (f1 == f2)
switch (f1)
{
case GRNQ_THREADLIST_RECALC:
case GRNQ_GROUPLIST_RECALC:
grnq_free(qdata); return TRUE;
break;
default: ;
}
switch (f1)
{
case GRNQ_DOWNLOAD_GROUPLIST:
rc = grnq_run_download_grouplist(qdata);
break;
case GRNQ_DOWNLOAD_MSGHDRLIST:
rc = grnq_run_download_msghdrlist(qdata);
break;
case GRNQ_DOWNLOAD_ARTICLE:
rc = grnq_run_download_article(qdata);
break;
case GRNQ_POST_ARTICLE:
rc = grnq_run_post_article(qdata);
break;
case GRNQ_GROUPLIST_RECALC:
rc = grnq_run_grouplist_recalc(qdata);
break;
case GRNQ_THREADLIST_RECALC:
rc = grnq_run_threadlist_recalc(qdata);
break;
case GRNQ_SEND_MESSAGE:
rc = grnq_run_send_message(qdata);
break;
case GRNQ_DRAW_GROUPLIST:
rc = grnq_run_draw_grouplist(qdata);
break;
case GRNQ_DRAW_MSGLIST:
rc = grnq_run_draw_msglist(qdata);
break;
case GRNQ_DRAW_MSGLIST1:
rc = grnq_run_draw_msglist1(qdata);
break;
case GRNQ_DRAW_ARTICLE:
rc = grnq_run_draw_article(qdata);
break;
default:
g_error(_("Some strange behavior of grnq_run()"));
rc = FALSE;
break;
}
grnq_free(qdata);
return rc;
}
void grnq_purge(void)
{
GSList *p;
pthread_mutex_lock(&qlock);
for (p = queue; p; p=p->next) grnq_free((grnq_data *)p->data);
g_slist_free(queue);
queue = NULL; queue_last = NULL;
pthread_mutex_unlock(&qlock);
}
void grnq_add_download_grouplist(void)
{
grnq_data *qdata;
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_DOWNLOAD_GROUPLIST;
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_download_msghdrlist(grn_newsgroup *grp)
{
grnq_data *qdata;
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_DOWNLOAD_MSGHDRLIST;
qdata->data = grp;
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_download_article(t_message *msg)
{
grnq_data *qdata;
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_DOWNLOAD_ARTICLE;
qdata->data = msg;
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_post_article(t_message *msg)
{
grnq_data *qdata;
g_return_if_fail(msg != NULL);
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_POST_ARTICLE;
qdata->data = t_message_copy(msg);
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_grouplist_recalc(void)
{
grnq_data *qdata;
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_GROUPLIST_RECALC;
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_threadlist_recalc(GtkWidget *w)
{
grnq_data *qdata;
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_THREADLIST_RECALC;
qdata->data = w;
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_send_message(t_message *msg)
{
grnq_data *qdata;
g_return_if_fail(msg != NULL);
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_SEND_MESSAGE;
qdata->data = t_message_copy(msg);
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_draw_grouplist(void)
{
grnq_data *qdata;
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_DRAW_GROUPLIST;
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_draw_msglist(void)
{
grnq_data *qdata;
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_DRAW_MSGLIST;
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_draw_msglist1(void)
{
grnq_data *qdata;
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_DRAW_MSGLIST1;
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
void grnq_add_draw_article(t_message *msg)
{
grnq_data *qdata;
qdata = g_new(grnq_data, 1);
qdata->flags = GRNQ_DRAW_ARTICLE;
qdata->data = msg;
pthread_mutex_lock(&qlock);
queue = g_slist_append(queue, qdata);
pthread_mutex_unlock(&qlock);
pthread_mutex_lock(&qcond_m);
pthread_cond_broadcast(&qcond);
pthread_mutex_unlock(&qcond_m);
}
gboolean grnq_run_download_grouplist(grnq_data *qdata)
{
pthread_mutex_lock(&groups_m);
flags.open_grouplist = TRUE;
ng_list_download(FALSE);
flags.open_grouplist = FALSE;
pthread_mutex_unlock(&groups_m);
return TRUE;
}
gboolean grnq_run_download_msghdrlist(grnq_data *qdata)
{
GList *msglist=NULL;
gint total=0, first=0, last=0;
grn_newsgroup *grp = (grn_newsgroup *) qdata->data;
gchar *rc = NULL;
g_return_val_if_fail(grp != NULL, FALSE);
pthread_mutex_lock(&ogroup_m);
flags.open_group = TRUE;
if (GRN->msghdr_list) msghdrlist_free(&(GRN->msghdr_list));
grn_appbar_push(GRN->appbar, FALSE, _("Fetching article list for group %s..."), grp->name);
rc = nntp_connect(GRN->nntp_sock);
if (! rc)
{
if (grp->name)
rc = nntp_set_group(GRN->nntp_sock, grp->name, &total, &first, &last);
if (! rc)
{
msglist = nntp_get_msghdrlist(GRN->nntp_sock, total, first, last, grp, GRN->appbar);
if (msglist) GRN->msghdr_list = msglist;
else {
if (GRN->nntp_sock->error)
grn_error(_("Socket error"), GRN->nntp_sock->err_msg);
}
}
else grn_error(_("NNTP set group"), rc);
}
else grn_error(_("NNTP connect"), rc);
grn_appbar_pop(GRN->appbar);
grn_lock();
gnome_appbar_set_progress(GRN->appbar, 0);
grn_unlock();
flags.open_group = FALSE;
pthread_mutex_unlock(&ogroup_m);
return TRUE;
}
gboolean grnq_run_download_article(grnq_data *qdata)
{
t_message *msg = (t_message *) qdata->data;
g_return_val_if_fail(msg != NULL, FALSE);
pthread_mutex_lock(&omsg_m);
flags.open_article = TRUE;
nntp_download_article(msg);
flags.open_article = FALSE;
pthread_mutex_unlock(&omsg_m);
return TRUE;
}
gboolean grnq_run_post_article(grnq_data *qdata)
{
t_message *msg = (t_message *) qdata->data;
gchar *rc;
g_return_val_if_fail(msg != NULL, FALSE);
g_return_val_if_fail(msg->mh != NULL, FALSE);
g_return_val_if_fail(msg->mh->newsgroups != NULL, FALSE);
pthread_mutex_lock(&pmsg_m);
flags.post_article = TRUE;
grn_appbar_push(GRN->appbar, FALSE, _("Posting article to %s..."), msg->mh->newsgroups);
rc = nntp_connect(GRN->nntp_sock);
if (! rc)
{
rc = nntp_post_article(GRN->nntp_sock, msg);
if (rc) grn_error(_("NNTP post article"), rc);
}
else grn_error(_("NNTP connect"), rc);
grn_appbar_pop(GRN->appbar);
flags.post_article = FALSE;
pthread_mutex_unlock(&pmsg_m);
if (grn_prefs.cfms[6]) grn_info(_("Article posted succesfully"));
return TRUE;
}
gboolean grnq_run_grouplist_recalc(grnq_data *qdata)
{
pthread_mutex_lock(&groups_m);
if (GRN->grouplist) grouplist_recalc_unread(GRN->grouplist);
pthread_mutex_unlock(&groups_m);
return TRUE;
}
gboolean grnq_run_threadlist_recalc(grnq_data *qdata)
{
GtkWidget *w = (GtkWidget *) qdata->data;
grn_threadlist_stats *tls;
GList *msgs;
if (! w) return FALSE;
if ((! GTK_WIDGET_REALIZED(w)) || (! GTK_WIDGET_MAPPED(w)) ||
(! GTK_WIDGET_VISIBLE(w))) return FALSE;
tls = gtk_object_get_data(GTK_OBJECT(w), KEY_TL_STATS);
msgs = gtk_object_get_data(GTK_OBJECT(w), KEY_MSGLIST);
if ((! tls) || (! msgs)) return FALSE;
get_unread_tl_stats(msgs, tls);
show_tl_stats(tls);
return TRUE;
}
gboolean grnq_run_send_message(grnq_data *qdata)
{
t_message *msg = (t_message *) qdata->data;
gchar *rc;
grn_socket *sock;
g_return_val_if_fail(msg != NULL, FALSE);
g_return_val_if_fail(msg->mh != NULL, FALSE);
grn_appbar_push(GRN->appbar, FALSE, _("Sending message via SMTP..."));
sock = grn_socket_new();
rc = smtp_connect(sock);
if (! rc)
{
rc = smtp_send_message(sock, msg);
if (rc) grn_error(_("SMTP send message"), rc);
}
else grn_error(_("SMTP connect"), rc);
grn_socket_free(&sock);
grn_appbar_pop(GRN->appbar);
return TRUE;
}
gboolean grnq_run_draw_grouplist(grnq_data *qdata)
{
pthread_mutex_lock(&groups_m);
flags.open_grouplist = TRUE;
if (GRN->grouplist && GRN->ng_list)
grouplist_refresh(GRN->grouplist, GRN->ng_list);
flags.open_grouplist = FALSE;
pthread_mutex_unlock(&groups_m);
return TRUE;
}
gboolean grnq_run_draw_msglist(grnq_data *qdata)
{
pthread_mutex_lock(&ogroup_m);
flags.open_group = TRUE;
if (GRN->threadlist && GRN->msghdr_list)
threadlist_refresh(GRN->threadlist, GRN->msghdr_list, TRUE);
pthread_mutex_unlock(&ogroup_m);
flags.open_group = FALSE;
return TRUE;
}
gboolean grnq_run_draw_msglist1(grnq_data *qdata)
{
pthread_mutex_lock(&ogroup_m);
flags.open_group = TRUE;
if (GRN->threadlist && GRN->msghdr_list)
threadlist_refresh(GRN->threadlist, GRN->msghdr_list, FALSE);
flags.open_group = FALSE;
pthread_mutex_unlock(&ogroup_m);
return TRUE;
}
gboolean grnq_run_draw_article(grnq_data *qdata)
{
t_message *msg = (t_message *) qdata->data;
g_return_val_if_fail(msg != NULL, FALSE);
if (flags.open_article) return FALSE;
pthread_mutex_lock(&omsg_m);
flags.open_article = TRUE;
if (GRN->msgwin) msgwin_refresh(GRN->msgwin, msg);
flags.open_article = FALSE;
pthread_mutex_unlock(&omsg_m);
return TRUE;
}
syntax highlighted by Code2HTML, v. 0.9.1