[pan2] https://bugzilla.gnome.org/show_bug.cgi?id=492449 https://bugzilla.gnome.org/show_bug.cgi?id=459908



commit 43fcde98e8d09df7dd7eac9037b59f899c262225
Author: Heinrich MÃlller <henmull src gnome org>
Date:   Tue May 1 13:49:58 2012 +0200

    https://bugzilla.gnome.org/show_bug.cgi?id=492449
    https://bugzilla.gnome.org/show_bug.cgi?id=459908

 configure.in                  |    3 ++-
 pan/data/article-cache.cc     |   23 ++++++++++++++---------
 pan/data/article-cache.h      |   15 ++++++++++++++-
 pan/data/cert-store.cc        |    2 +-
 pan/gui/group-prefs-dialog.cc |   10 +++++-----
 pan/gui/group-prefs-dialog.h  |    3 +++
 pan/gui/gui.cc                |    2 +-
 pan/tasks/decoder.cc          |    3 ++-
 pan/tasks/decoder.h           |    1 +
 pan/tasks/encoder.cc          |    3 ++-
 pan/tasks/encoder.h           |    1 +
 pan/tasks/health.h            |    7 +++++--
 pan/tasks/nntp-pool.cc        |    3 ++-
 pan/tasks/queue.cc            |   26 +++++++++++++++++++++-----
 pan/tasks/task-article.cc     |   10 ++++++++--
 pan/tasks/task-upload.cc      |    2 ++
 pan/tasks/task-xover.cc       |    1 +
 17 files changed, 85 insertions(+), 30 deletions(-)
---
diff --git a/configure.in b/configure.in
index 8810b33..85052a9 100644
--- a/configure.in
+++ b/configure.in
@@ -159,8 +159,9 @@ dnl GnuTLS support
 gnutls_msg=no
 AC_ARG_WITH(gnutls, AS_HELP_STRING([--with-gnutls],[enable GnuTLS support (normally: no)]), [want_gnutls=$withval], [want_gnutls=no])
 if test "x$want_gnutls" = "xyes" ; then
+  GNUTLS_VER=`echo pkg-config --modversion gnutls`	
   PKG_CHECK_MODULES([GNUTLS],[gnutls >= $GNUTLS_REQUIRED],
-  [gnutls_msg="yes >= $GNUTLS_REQUIRED"
+  [gnutls_msg="yes = $GNUTLS_VER"
   AC_DEFINE(HAVE_GNUTLS,[1],[GnuTLS support])],
   [gnutls_msg=no
   AC_MSG_RESULT(no)])
diff --git a/pan/data/article-cache.cc b/pan/data/article-cache.cc
index b1918a4..f8f89c8 100644
--- a/pan/data/article-cache.cc
+++ b/pan/data/article-cache.cc
@@ -213,13 +213,16 @@ ArticleCache :: get_filename (char * buf, int buflen, const Quark& mid) const
    return buf && *buf ? buf : 0;
 };
 
-bool
+ArticleCache :: CacheResponse
 ArticleCache :: add (const Quark& message_id, const StringView& article)
 {
   debug ("adding " << message_id << ", which is " << article.len << " bytes long");
 
-  pan_return_val_if_fail (!message_id.empty(), false);
-  pan_return_val_if_fail (!article.empty(), false);
+  CacheResponse res;
+  res.type = CACHE_IO_ERR;
+
+  pan_return_val_if_fail (!message_id.empty(), res);
+  pan_return_val_if_fail (!article.empty(), res);
 
   FILE * fp = 0;
   char filename[PATH_MAX];
@@ -230,18 +233,19 @@ ArticleCache :: add (const Quark& message_id, const StringView& article)
   {
       Log::add_err_va (_("Unable to save \"%s\" %s"),
                        filename, file::pan_strerror(errno));
-      return false;
+      res.type = CACHE_IO_ERR;
   }
   else
   {
     const size_t bytes_written (fwrite (article.str, sizeof(char), article.len, fp));
-    fclose (fp);
-
     if (bytes_written < article.len)
     {
       Log::add_err_va (_("Unable to save \"%s\" %s"),
                        filename, file::pan_strerror(errno));
-      return false;
+      if (errno ==  ENOSPC || errno == ENOMEM)
+      {
+          res.type = CACHE_DISK_FULL;
+      }
     }
     else
     {
@@ -254,10 +258,11 @@ ArticleCache :: add (const Quark& message_id, const StringView& article)
 
       _current_bytes += info._size;
       resize ();
+      res.type = CACHE_OK;
     }
+    fclose (fp);
   }
-
-  return true;
+  return res;
 }
 
 /***
diff --git a/pan/data/article-cache.h b/pan/data/article-cache.h
index a82c971..3f868b3 100644
--- a/pan/data/article-cache.h
+++ b/pan/data/article-cache.h
@@ -61,13 +61,26 @@ namespace pan
   {
     public:
 
+      enum CacheResponse_types
+      {
+        CACHE_IO_ERR,
+        CACHE_DISK_FULL,
+        CACHE_OK
+      };
+
+      struct CacheResponse
+      {
+        CacheResponse_types type;
+        std::string err; // perhaps use gerror here??
+      };
+
       ArticleCache (const StringView& path, const StringView& extension, size_t max_megs=10);
       ~ArticleCache ();
 
       typedef std::vector<Quark> mid_sequence_t;
 
       bool contains (const Quark& message_id) const;
-      bool add (const Quark& message_id, const StringView& article);
+      CacheResponse add (const Quark& message_id, const StringView& article);
       void reserve (const mid_sequence_t& mids);
       void release (const mid_sequence_t& mids);
       void resize ();
diff --git a/pan/data/cert-store.cc b/pan/data/cert-store.cc
index 812cdc8..35df7f3 100644
--- a/pan/data/cert-store.cc
+++ b/pan/data/cert-store.cc
@@ -201,7 +201,7 @@ namespace pan
     filelen = ftell (fp);
     fseek (fp, 0, SEEK_SET);
     buf = new char[filelen];
-    fread (buf, sizeof(char), filelen, fp);
+    size_t dummy (fread (buf, sizeof(char), filelen, fp)); // silence compiler
 
     gnutls_datum_t in;
     in.data = (unsigned char*)buf;
diff --git a/pan/gui/group-prefs-dialog.cc b/pan/gui/group-prefs-dialog.cc
index 2ad6338..88c8052 100644
--- a/pan/gui/group-prefs-dialog.cc
+++ b/pan/gui/group-prefs-dialog.cc
@@ -248,9 +248,11 @@ namespace
 
 GroupPrefsDialog :: GroupPrefsDialog (Data            & data,
                                       const quarks_v  & groups,
+                                      Prefs           & prefs,
                                       GroupPrefs      & group_prefs,
                                       GtkWindow       * parent_window):
   _groups (groups),
+  _prefs(prefs),
   _group_prefs (group_prefs)
 {
 
@@ -283,11 +285,9 @@ GroupPrefsDialog :: GroupPrefsDialog (Data            & data,
 
     w = _save_path = file_entry_new (_("Directory for Saving Attachments"));
     char * pch = g_build_filename (g_get_home_dir(), "News", NULL);
-    std::string dir;
-    if (groups.size() != 1)
-      dir = pch;
-    else
-      dir = _group_prefs.get_string (groups[0], "default-group-save-path", pch);
+    std::string dir (_prefs.get_string ("default-save-attachments-path", pch));
+    if (groups.size() == 1)
+      dir = _group_prefs.get_string (groups[0], "default-group-save-path", dir);
     g_free (pch);
     file_entry_set (w, dir.c_str());
 
diff --git a/pan/gui/group-prefs-dialog.h b/pan/gui/group-prefs-dialog.h
index d377165..d755eda 100644
--- a/pan/gui/group-prefs-dialog.h
+++ b/pan/gui/group-prefs-dialog.h
@@ -24,6 +24,7 @@
 #include <pan/data/data.h>
 #include "gtk-compat.h"
 #include "group-prefs.h"
+#include "prefs.h"
 
 namespace pan
 {
@@ -32,6 +33,7 @@ namespace pan
     public:
       GroupPrefsDialog (Data            & data,
                         const quarks_v  & groups,
+                        Prefs           & prefs,
                         GroupPrefs      & group_prefs,
                         GtkWindow       * parent_window);
 
@@ -40,6 +42,7 @@ namespace pan
 
     private:
       const quarks_v   _groups;
+      Prefs        & _prefs;
       GroupPrefs   & _group_prefs;
       GtkWidget    * _root;
       GtkWidget    * _charset;
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index 7e4d79e..b0abeb7 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -900,7 +900,7 @@ void GUI :: do_show_group_preferences_dialog ()
 {
   quarks_v groups(_group_pane->get_full_selection());
   if (!groups.empty()) {
-    GroupPrefsDialog * dialog = new GroupPrefsDialog (_data, groups, _group_prefs, get_window(_root));
+    GroupPrefsDialog * dialog = new GroupPrefsDialog (_data, groups, _prefs, _group_prefs, get_window(_root));
     gtk_widget_show (dialog->root());
   }
 }
diff --git a/pan/tasks/decoder.cc b/pan/tasks/decoder.cc
index bc09d16..6b35f8a 100644
--- a/pan/tasks/decoder.cc
+++ b/pan/tasks/decoder.cc
@@ -41,7 +41,8 @@ using namespace pan;
 
 Decoder :: Decoder (WorkerPool& pool):
   _worker_pool (pool),
-  _gsourceid (-1)
+  _gsourceid (-1),
+  health(OK)
 {
 }
 
diff --git a/pan/tasks/decoder.h b/pan/tasks/decoder.h
index b34b790..0814694 100644
--- a/pan/tasks/decoder.h
+++ b/pan/tasks/decoder.h
@@ -68,6 +68,7 @@ namespace pan
       typedef std::list<std::string> log_t;
       log_t log_severe, log_errors, log_infos, file_errors;
       bool mark_read;
+      Health health;
 
     protected: // inherited from WorkerPool::Worker
 
diff --git a/pan/tasks/encoder.cc b/pan/tasks/encoder.cc
index 918b407..887ef76 100644
--- a/pan/tasks/encoder.cc
+++ b/pan/tasks/encoder.cc
@@ -47,7 +47,8 @@ using namespace pan;
 
 Encoder :: Encoder (WorkerPool& pool):
   _worker_pool (pool),
-  _gsourceid (-1)
+  _gsourceid (-1),
+  health(OK)
 {}
 
 
diff --git a/pan/tasks/encoder.h b/pan/tasks/encoder.h
index 895360a..89eb821 100644
--- a/pan/tasks/encoder.h
+++ b/pan/tasks/encoder.h
@@ -72,6 +72,7 @@ namespace pan
 
       typedef std::list<std::string> log_t;
       log_t log_severe, log_errors, log_infos, file_errors;
+      Health health;
 
     protected: // inherited from WorkerPool::Worker
 
diff --git a/pan/tasks/health.h b/pan/tasks/health.h
index c661047..8e34c07 100644
--- a/pan/tasks/health.h
+++ b/pan/tasks/health.h
@@ -45,11 +45,14 @@ namespace pan
     ERR_COMMAND,
 
     /** The task has failed because of some local
-        environment problem, such as disk full.
+        environment problem.
         Further tasks are likely to fail for the
         same reason, so the queue should go offline
         until the user intervenes to fix the problem. */
-    ERR_LOCAL
+    ERR_LOCAL,
+
+    /** Handle disk full by setting the queue offline */
+    ERR_NOSPACE
   };
 }
 
diff --git a/pan/tasks/nntp-pool.cc b/pan/tasks/nntp-pool.cc
index 1de2594..40e6010 100644
--- a/pan/tasks/nntp-pool.cc
+++ b/pan/tasks/nntp-pool.cc
@@ -136,10 +136,11 @@ NNTP_Pool :: check_in (NNTP * nntp, Health health)
   if (it != _pool_items.end())
   {
     const bool bad_connection = (health == ERR_NETWORK);
+    const bool nospace = (health == ERR_NOSPACE);
     int active, idle, pending, max;
     get_counts (active, idle, pending, max);
     const bool too_many = (pending + active) > max;
-    const bool discard = bad_connection || too_many;
+    const bool discard = bad_connection || too_many || nospace;
 
     --_active_count;
 
diff --git a/pan/tasks/queue.cc b/pan/tasks/queue.cc
index 05a833f..133470a 100644
--- a/pan/tasks/queue.cc
+++ b/pan/tasks/queue.cc
@@ -301,11 +301,16 @@ Queue :: process_task (Task * task)
     debug ("stopped");
     task->stop();
   }
-  else if ((state._health == ERR_COMMAND) || (state._health == ERR_LOCAL))
+  else if (state._health == ERR_COMMAND || state._health == ERR_LOCAL)
   {
     debug ("fail");
     // do nothing
   }
+  else if (state._health==ERR_NOSPACE)
+  {
+    debug ("no space");
+    set_online(false);
+  }
   else if (state._work == Task::WORKING)
   {
     debug ("working");
@@ -316,7 +321,7 @@ Queue :: process_task (Task * task)
     TaskUpload* t = dynamic_cast<TaskUpload*>(task);
     if (t)
       give_task_an_upload_slot(t);
-
+    // todo multihtreading for taskarticle
 //    TaskArticle* t2 = dynamic_cast<TaskArticle*>(task);
 //    if (t2)
 //      give_task_a_download_slot(t2);
@@ -361,7 +366,6 @@ Queue :: process_task (Task * task)
 
     give_task_a_connection (task, nntp);
   }
-  debug("end loop");
 }
 
 /***
@@ -401,7 +405,8 @@ Queue :: find_first_task_needing_server (const Quark& server)
 {
   foreach (TaskSet, _tasks, it) {
     const Task::State& state ((*it)->get_state ());
-    if  (((state._health != ERR_COMMAND) && (state._health != ERR_LOCAL))
+    if  (state._health != ERR_COMMAND && state._health != ERR_LOCAL
+      && state._health != ERR_NOSPACE
       && (state._work == Task::NEED_NNTP)
       && (state._servers.count(server))
       && (!_stopped.count (*it))
@@ -722,7 +727,8 @@ Queue :: check_in (NNTP * nntp, Health nntp_health)
 
   if ((nntp_health != ERR_NETWORK)
     && _is_online
-    && ((state._health != ERR_COMMAND) && (state._health != ERR_LOCAL))
+    && state._health != ERR_COMMAND && state._health != ERR_LOCAL
+    && state._health != ERR_NOSPACE
     && (state._work == Task::NEED_NNTP)
     && !_removing.count(task)
     && state._servers.count(nntp->_server)
@@ -744,6 +750,10 @@ Queue :: check_in (NNTP * nntp, Health nntp_health)
     if (state._health == ERR_LOCAL)
       fire_queue_error ("");
 
+    // tell if we reached the end of disk space
+    if (state._health == ERR_NOSPACE)
+      fire_queue_error (_("No space left on device."));
+
     // return the nntp to the pool
     const Quark& servername (nntp->_server);
     NNTP_Pool& pool (get_pool (servername));
@@ -769,6 +779,9 @@ Queue :: check_in (Decoder* decoder UNUSED, Task* task)
   if (state._health == ERR_LOCAL)
     fire_queue_error ("");
 
+  if (state._health == ERR_NOSPACE)
+    fire_queue_error (_("No space left on device."));
+
   // pass our worker thread on to another task
   Task * next = find_first_task_needing_decoder ();
   if (next && (next!=task))
@@ -793,6 +806,9 @@ Queue :: check_in (Encoder* encoder UNUSED, Task* task)
   if (state._health == ERR_LOCAL)
     fire_queue_error ("");
 
+  if (state._health == ERR_NOSPACE)
+    fire_queue_error (_("No space left on device."));
+
   // pass our worker thread on to another task
   Task * next = find_first_task_needing_encoder ();
   if (next && (next!=task))
diff --git a/pan/tasks/task-article.cc b/pan/tasks/task-article.cc
index 71e883d..50f0f55 100644
--- a/pan/tasks/task-article.cc
+++ b/pan/tasks/task-article.cc
@@ -295,8 +295,11 @@ TaskArticle :: on_nntp_done  (NNTP             * nntp,
 
   if (health == OK) { // if download succeeded, save it in the cache
     const StringView view (&it->buf.front(), it->buf.size());
-    if (!_cache.add (it->message_id, view))
-      health = ERR_LOCAL;
+    ArticleCache::CacheResponse res (_cache.add (it->message_id, view));
+    if (ArticleCache::CACHE_OK != res.type)
+      health = res.type == ArticleCache::CACHE_DISK_FULL ? ERR_NOSPACE : ERR_LOCAL;
+      if (health == ERR_NOSPACE)
+        _state.set_health (ERR_NOSPACE);
   }
 
   // std::cerr << LINE_ID << ' ' << it->message_id << " from " << nntp->_server << ": health " << health << std::endl;
@@ -308,6 +311,7 @@ TaskArticle :: on_nntp_done  (NNTP             * nntp,
       break;
 
     case ERR_NETWORK: // if the network is bad...
+    case ERR_NOSPACE: // if there's no space, try again, but pause the queue!
     case ERR_LOCAL: // ...or if we got it but couldn't save it
       it->reset ();
       break;
@@ -392,6 +396,8 @@ TaskArticle :: on_worker_done (bool cancelled)
     if (!_decoder->log_errors.empty())
       set_error (_decoder->log_errors.front());
 
+    _state.set_health(_decoder->health);
+
     if (!_decoder->log_severe.empty())
       _state.set_health (ERR_LOCAL);
     else {
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
index 3b66406..0a59025 100644
--- a/pan/tasks/task-upload.cc
+++ b/pan/tasks/task-upload.cc
@@ -433,6 +433,8 @@ TaskUpload :: on_worker_done (bool cancelled)
         _needed.clear(); //update_work will then set the status to complete
     }
 
+    _state.set_health(_encoder->health);
+
     if (!_encoder->log_severe.empty())
       _state.set_health (ERR_LOCAL);
     else
diff --git a/pan/tasks/task-xover.cc b/pan/tasks/task-xover.cc
index 2482a25..34a5a69 100644
--- a/pan/tasks/task-xover.cc
+++ b/pan/tasks/task-xover.cc
@@ -179,6 +179,7 @@ TaskXOver :: use_nntp (NNTP* nntp)
 ****
 ***/
 
+///TODO show low and high in UI (is this already there?)
 void
 TaskXOver :: on_nntp_group (NNTP          * nntp,
                             const Quark   & group,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]