[pan2: 46/268] fixed bugs, implementing articlecache for uulib encoded files



commit 8fe83f5e927ae2bafff18443326579997c5794a1
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Tue May 31 10:17:30 2011 +0200

    fixed bugs, implementing articlecache for uulib encoded files

 pan/data-impl/data-impl.cc |   10 +++
 pan/data-impl/data-impl.h  |    5 +
 pan/data/Makefile.am       |    2 +
 pan/data/article.h         |    2 +-
 pan/general/file-util.cc   |   52 ++++--------
 pan/gui/gui.cc             |   18 ++---
 pan/gui/gui.h              |    4 +-
 pan/gui/pan-ui.h           |    1 -
 pan/gui/pan.cc             |   11 ++-
 pan/gui/post-ui.cc         |   90 +++++++++++----------
 pan/gui/post-ui.h          |   16 +++--
 pan/tasks/encoder.cc       |    4 +-
 pan/tasks/encoder.h        |    1 -
 pan/tasks/nzb.cc           |    8 +-
 pan/tasks/task-upload.cc   |  190 ++++++++++++++++++++++---------------------
 pan/tasks/task-upload.h    |   13 ++-
 uulib/uuencode.c           |    4 +-
 17 files changed, 224 insertions(+), 207 deletions(-)
---
diff --git a/pan/data-impl/data-impl.cc b/pan/data-impl/data-impl.cc
index 7300dd5..be96dae 100644
--- a/pan/data-impl/data-impl.cc
+++ b/pan/data-impl/data-impl.cc
@@ -49,11 +49,21 @@ namespace
     g_free (pch);
     return path;
   }
+
+  std::string get_encode_cache_path ()
+  {
+    char * pch (g_build_filename (file::get_pan_home().c_str(), "encode-cache", NULL));
+    file :: ensure_dir_exists (pch);
+    std::string path (pch);
+    g_free (pch);
+    return path;
+  }
 }
 
 DataImpl :: DataImpl (bool unit_test, int cache_megs, DataIO * io):
   ProfilesImpl (*io),
   _cache (get_cache_path(), cache_megs),
+//  _encode_cache (get_encode_cache_path(), cache_megs),
   _unit_test (unit_test),
   _data_io (io),
   _descriptions_loaded (false)
diff --git a/pan/data-impl/data-impl.h b/pan/data-impl/data-impl.h
index f794737..bb98592 100644
--- a/pan/data-impl/data-impl.h
+++ b/pan/data-impl/data-impl.h
@@ -35,6 +35,7 @@
 #include <pan/usenet-utils/scorefile.h>
 #include <pan/data/article.h>
 #include <pan/data/article-cache.h>
+#include <pan/data/encode-cache.h>
 #include <pan/data/data.h>
 #include <pan/tasks/queue.h>
 #include <pan/data-impl/data-io.h>
@@ -71,7 +72,11 @@ namespace pan
     public:
       virtual ArticleCache& get_cache () { return _cache; }
       virtual const ArticleCache& get_cache () const { return _cache; }
+
+//      virtual EncodeCache& get_encode_cache () { return _encode_cache; }
+//      virtual const EncodeCache& get_encode_cache () const { return _encode_cache; }
     private:
+//      EncodeCache _encode_cache;
       ArticleCache _cache;
 
     private:
diff --git a/pan/data/Makefile.am b/pan/data/Makefile.am
index 7c0f654..0c7e0f6 100644
--- a/pan/data/Makefile.am
+++ b/pan/data/Makefile.am
@@ -6,6 +6,7 @@ noinst_LIBRARIES = libdata.a
 
 libdata_a_SOURCES = \
  article.cc \
+ encode-cache.cc \
  article-cache.cc \
  data.cc \
  parts.cc \
@@ -13,6 +14,7 @@ libdata_a_SOURCES = \
 
 noinst_HEADERS = \
  article.h \
+ encode-cache.h \
  article-cache.h \
  data.h \
  defgroup.h \
diff --git a/pan/data/article.h b/pan/data/article.h
index 0d905b9..dc57ba2 100644
--- a/pan/data/article.h
+++ b/pan/data/article.h
@@ -31,7 +31,7 @@ namespace pan
 {
   /**
    * A Usenet article, either single-part or multipart.
-   * 
+   *
    * To lessen the memory footprint of large binaries groups,
    * Pan folds multipart posts into a single Article object.
    * Only minimal information for any one part is kept
diff --git a/pan/general/file-util.cc b/pan/general/file-util.cc
index 2d650d6..bfe70a8 100644
--- a/pan/general/file-util.cc
+++ b/pan/general/file-util.cc
@@ -60,50 +60,30 @@ file :: get_uulib_path()
   return path;
 }
 
-/// TODO perhaps implement another cache for uulib files ??
 // delete cached files to avoid "disk full" problems
 void
 file :: uulib_cache_clear ()
 {
-  DIR *dp;
-  struct dirent *ep;
-  struct stat st;
-  const char * dir = get_uulib_path().c_str();
-  std::cerr<<"opening dir : "<<dir<<std::endl;
-  dp = opendir (dir);
-  if (dp != NULL)
-  {
-    while (ep = readdir (dp))
-    {
-      stat(ep->d_name, &st);
-      if (S_ISDIR(st.st_mode) == 0) {
-        std::cerr<<"deleting file :"<<ep->d_name<<"\n";
-        unlink(ep->d_name);
-      }
-    }
-    (void) closedir (dp);
-  } else
-    std::cerr<<"error clearing uulib cache!\n";
-}
-
-//  void clear_cached_range (const char* file)
+//  DIR *dp;
+//  struct dirent *ep;
+//  struct stat st;
+//  const char * dir = get_uulib_path().c_str();
+//  std::cerr<<"opening dir : "<<dir<<std::endl;
+//  dp = opendir (dir);
+//  if (dp != NULL)
 //  {
-//    DIR *dp;
-//    struct dirent *ep;
-//    struct stat st;
-//    const char * dir = file :: get_uulib_path().c_str();
-//    dp = opendir (dir);
-//    if (dp != NULL)
+//    while (ep = readdir (dp))
 //    {
-//      while (ep = readdir (dp))
-//      {
-//        stat(ep->d_name, &st);
-//        if (S_ISDIR(st.st_mode) == 0 && strstr(file,ep->d_name))
-//          unlink(ep->d_name);
+//      stat(ep->d_name, &st);
+//      if (S_ISDIR(st.st_mode) == 0) {
+//        std::cerr<<"deleting file :"<<ep->d_name<<"\n";
+//        unlink(ep->d_name);
 //      }
-//      (void) closedir (dp);
 //    }
-//  }
+//    (void) closedir (dp);
+//  } else
+//    std::cerr<<"error clearing uulib cache!\n";
+}
 
 std::string
 file :: get_pan_home ()
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index 5350434..beb1180 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -165,10 +165,11 @@ namespace
 }
 
 
-GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, Prefs& prefs, GroupPrefs& group_prefs):
+GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, /*EncodeCache& encode_cache, */Prefs& prefs, GroupPrefs& group_prefs):
   _data (data),
   _queue (queue),
   _cache (cache),
+//  _encode_cache (encode_cache),
   _prefs (prefs),
   _group_prefs (group_prefs),
   _root (gtk_vbox_new (FALSE, 0)),
@@ -186,10 +187,6 @@ GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, Prefs& prefs, GroupPr
   _taskbar (0)
 {
 
-  //clear uulib encode cache
-  ///TODO perhaps remember by crc32-ptr and then assign already saved parts??
-//  file :: uulib_cache_clear();
-
   char * filename = g_build_filename (file::get_pan_home().c_str(), "pan.ui", NULL);
   if (!gtk_ui_manager_add_ui_from_file (_ui_manager, filename, NULL))
     gtk_ui_manager_add_ui_from_string (_ui_manager, fallback_ui_file, -1, NULL);
@@ -1125,7 +1122,7 @@ void GUI :: do_supersede_article ()
   g_object_unref (content_object);
   g_object_unref (stream);
 
-  PostUI * post = PostUI :: create_window (_root, _data, _queue, _data, _data, new_message, _prefs, _group_prefs);
+  PostUI * post = PostUI :: create_window (_root, _data, _queue, _data, _data, new_message, _prefs, _group_prefs, _cache);
   if (post)
   {
     gtk_widget_show_all (post->root());
@@ -1188,7 +1185,7 @@ void GUI :: do_cancel_article ()
   g_object_unref (stream);
   g_free (cancel_message);
 
-  PostUI * post = PostUI :: create_window (_root, _data, _queue, _data, _data, cancel, _prefs, _group_prefs);
+  PostUI * post = PostUI :: create_window (_root, _data, _queue, _data, _data, cancel, _prefs, _group_prefs, _cache);
   if (post)
   {
     gtk_widget_show_all (post->root());
@@ -1222,6 +1219,7 @@ void GUI :: do_delete_article ()
 void GUI :: do_clear_article_cache ()
 {
   _cache.clear ();
+//  _encode_cache.clear();
 }
 
 void GUI :: do_mark_article_read ()
@@ -1269,7 +1267,7 @@ GUI :: do_post ()
   g_mime_message_set_mime_part (message, GMIME_OBJECT(part));
   g_object_unref (part);
 
-  PostUI * post = PostUI :: create_window (_root, _data, _queue, _data, _data, message, _prefs, _group_prefs);
+  PostUI * post = PostUI :: create_window (_root, _data, _queue, _data, _data, message, _prefs, _group_prefs, _cache);
   if (post)
     gtk_widget_show_all (post->root());
   g_object_unref (message);
@@ -1279,7 +1277,7 @@ void GUI :: do_followup_to ()
 {
   GMimeMessage * message = _body_pane->create_followup_or_reply (false);
   if (message) {
-    PostUI * post = PostUI :: create_window(_root, _data, _queue, _data, _data, message, _prefs, _group_prefs);
+    PostUI * post = PostUI :: create_window(_root, _data, _queue, _data, _data, message, _prefs, _group_prefs, _cache);
     if (post)
       gtk_widget_show_all (post->root());
     g_object_unref (message);
@@ -1289,7 +1287,7 @@ void GUI :: do_reply_to ()
 {
   GMimeMessage * message = _body_pane->create_followup_or_reply (true);
   if (message) {
-    PostUI * post = PostUI :: create_window (_root, _data, _queue, _data, _data, message, _prefs, _group_prefs);
+    PostUI * post = PostUI :: create_window (_root, _data, _queue, _data, _data, message, _prefs, _group_prefs, _cache);
     if (post)
       gtk_widget_show_all (post->root());
     g_object_unref (message);
diff --git a/pan/gui/gui.h b/pan/gui/gui.h
index 4706ed3..e266ca7 100644
--- a/pan/gui/gui.h
+++ b/pan/gui/gui.h
@@ -22,6 +22,7 @@
 #include <pan/general/log.h>
 #include <pan/general/progress.h>
 #include <pan/data/article-cache.h>
+#include <pan/data/encode-cache.h>
 #include <pan/tasks/queue.h>
 #include <pan/gui/group-pane.h>
 #include <pan/gui/action-manager.h>
@@ -57,7 +58,7 @@ namespace pan
     private Prefs::Listener
   {
     public:
-      GUI (Data& data, Queue&, ArticleCache&, Prefs&, GroupPrefs&);
+      GUI (Data& data, Queue&, ArticleCache&, /*EncodeCache&,*/ Prefs&, GroupPrefs&);
       virtual ~GUI ();
       GtkWidget* root () { return _root; }
 
@@ -193,6 +194,7 @@ namespace pan
       Data& _data;
       Queue& _queue;
       ArticleCache& _cache;
+//      EncodeCache& _encode_cache;
       Prefs& _prefs;
       GroupPrefs& _group_prefs;
 
diff --git a/pan/gui/pan-ui.h b/pan/gui/pan-ui.h
index 29dcb4b..47c7ab5 100644
--- a/pan/gui/pan-ui.h
+++ b/pan/gui/pan-ui.h
@@ -52,7 +52,6 @@ namespace pan
     virtual void do_clear_body_pane () = 0;
     virtual void do_read_selected_article () = 0;
     virtual void do_read_more () = 0;
-//    virtual void do_binpost () = 0;
     virtual void do_read_less () = 0;
     virtual void do_read_next_unread_group () = 0;
     virtual void do_read_next_group () = 0;
diff --git a/pan/gui/pan.cc b/pan/gui/pan.cc
index 4c31ff8..366be58 100644
--- a/pan/gui/pan.cc
+++ b/pan/gui/pan.cc
@@ -128,6 +128,7 @@ namespace
   }
 
   void run_pan_in_window (ArticleCache  & cache,
+//                          EncodeCache   & encode_cache,
                           Data          & data,
                           Queue         & queue,
                           Prefs         & prefs,
@@ -137,7 +138,7 @@ namespace
     {
       const gulong delete_cb_id =  g_signal_connect (window, "delete-event", G_CALLBACK(delete_event_cb), 0);
 
-      GUI gui (data, queue, cache, prefs, group_prefs);
+      GUI gui (data, queue, cache, /*encode_cache,*/ prefs, group_prefs);
       gtk_container_add (GTK_CONTAINER(window), gui.root());
       gtk_widget_show (GTK_WIDGET(window));
 
@@ -316,6 +317,8 @@ main (int argc, char *argv[])
     const int cache_megs = prefs.get_int ("cache-size-megs", 10);
     DataImpl data (false, cache_megs);
     ArticleCache& cache (data.get_cache ());
+//    EncodeCache& encode_cache (data.get_encode_cache());
+
     if (nzb && data.get_servers().empty()) {
       std::cerr << _("Please configure Pan's news servers before using it as an nzb client.") << std::endl;
        return 0;
@@ -386,13 +389,15 @@ main (int argc, char *argv[])
       gtk_window_set_resizable (GTK_WINDOW(window), true);
       gtk_window_set_default_icon (pixbuf);
       g_object_unref (pixbuf);
-      run_pan_in_window (cache, data, queue, prefs, group_prefs, GTK_WINDOW(window));
+      run_pan_in_window (cache, /*encode_cache,*/ data, queue, prefs, group_prefs, GTK_WINDOW(window));
     }
 
     worker_pool.cancel_all_silently ();
 
-    if (prefs.get_flag("clear-article-cache-on-shutdown", false))
+    if (prefs.get_flag("clear-article-cache-on-shutdown", false)) {
       cache.clear ();
+//      encode_cache.clear();
+    }
   }
 
   g_mime_shutdown ();
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index 18a4ea2..1e3ab86 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -804,7 +804,7 @@ PostUI :: maybe_post_message (GMimeMessage * message)
     _post_task->add_listener (this);
     _queue.add_task (_post_task, Queue::TOP);
   } else {
-     foreach_const (tasks_set, _file_queue_tasks, it)
+     foreach_const (tasks_v, _file_queue_tasks, it)
         _queue.add_task (*it, Queue::BOTTOM);
      close_window(true); // dont wait for the upload queue
   }
@@ -1969,7 +1969,7 @@ namespace
   {
 
     TaskUpload* fd(0);
-    gtk_tree_model_get (model, iter, 0, &fd, -1);
+    gtk_tree_model_get (model, iter, 1, &fd, -1);
     if (fd)
       g_object_set (renderer, "text", fd->basename().c_str(), NULL);
   }
@@ -2000,17 +2000,17 @@ PostUI :: create_filequeue_tab ()
   gtk_box_pack_start (GTK_BOX(vbox), buttons, false, false, 0);
   gtk_box_pack_start (GTK_BOX(vbox), gtk_hseparator_new(), false, false, 0);
 
-  list_store = gtk_list_store_new (2, G_TYPE_POINTER, G_TYPE_UINT);
+  list_store = gtk_list_store_new (3, G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_UINT);
   w = _filequeue_store = gtk_tree_view_new_with_model (GTK_TREE_MODEL(list_store));
 
   // add columns
   renderer = gtk_cell_renderer_text_new ();
-  gtk_tree_view_insert_column_with_data_func(
-            GTK_TREE_VIEW(w), 0, (_("Filename")), renderer,
-            render_filename, 0, 0);
+  GtkTreeView * t = GTK_TREE_VIEW(w);
+  gtk_tree_view_insert_column_with_attributes (t, 0,(_("No.")),renderer,"text", 0,NULL);
   renderer = gtk_cell_renderer_text_new ();
-  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w), 1,
-                          (_("Size (kB)")),renderer,"text", 1,NULL);
+  gtk_tree_view_insert_column_with_data_func(t, 1, (_("Filename")), renderer, render_filename, 0, 0);
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (t, 2, (_("Size (kB)")),renderer,"text", 2,NULL);
 
   // connect signals for popup menu
   g_signal_connect (w, "popup-menu", G_CALLBACK(on_popup_menu), this);
@@ -2029,7 +2029,6 @@ PostUI :: create_filequeue_tab ()
   gtk_container_add (GTK_CONTAINER(w), _filequeue_store);
   gtk_box_pack_start (GTK_BOX(vbox), w, true, true, 0);
 
-
   return vbox;
 }
 
@@ -2273,34 +2272,39 @@ void
 PostUI :: get_selected_files_foreach (GtkTreeModel *model, GtkTreePath *, GtkTreeIter *iter, gpointer list_g)
 {
   TaskUpload* file(0);
-  gtk_tree_model_get (model, iter, 0, &file, -1);
-  static_cast<tasks_set*>(list_g)->insert (file);
+  gtk_tree_model_get (model, iter, 1, &file, -1);
+  static_cast<tasks_v*>(list_g)->push_back (file);
 }
 
-tasks_set
+tasks_v
 PostUI :: get_selected_files () const
 {
-  tasks_set tasks;
+  tasks_v tasks;
   GtkTreeView * view (GTK_TREE_VIEW (_filequeue_store));
   GtkTreeSelection * sel (gtk_tree_view_get_selection (view));
   gtk_tree_selection_selected_foreach (sel, get_selected_files_foreach, &tasks);
   return tasks;
 }
 
+/// TODO debug!
 void
 PostUI :: remove_files (void)
 {
-  tasks_set tasks = get_selected_files();
-  tasks_set::iterator nit;
-  for (nit = tasks.begin(); nit != tasks.end();nit, ++nit)
-    {
-       delete (*nit);
-      _file_queue_tasks.erase(*nit);
-    }
+  tasks_v tasks = get_selected_files();
+
+  tasks_v::iterator nit;
+  for (nit = tasks.begin(); nit != tasks.end(); ++nit)
+  {
+    TaskUpload * ptr(*nit);
+    _file_queue_tasks.remove(*nit);
+    delete (ptr);
+  }
+  std::cerr<<"tasks size: "<<_file_queue_tasks.size()<<std::endl;
   update_filequeue_tab();
 }
 
 
+
 void
 PostUI :: move_up (void)
 {
@@ -2363,15 +2367,16 @@ PostUI :: update_filequeue_tab()
 
   gtk_list_store_clear(store);
 
-  tasks_set::iterator it = _file_queue_tasks.begin();
+  tasks_v::iterator it = _file_queue_tasks.begin();
 
-  int i(0);
-  for (; it != _file_queue_tasks.end(); ++it )
+  int i(1);
+  for (; it != _file_queue_tasks.end(); ++it, ++i)
   {
     gtk_list_store_append (store, &iter);
     gtk_list_store_set (store, &iter,
-                      0, ((TaskUpload*)*it),
-                      1, ((TaskUpload*)*it)->get_byte_count()/1024,
+                      0, i,
+                      1, ((TaskUpload*)*it),
+                      2, ((TaskUpload*)*it)->get_byte_count()/1024,
                       -1);
   }
   _file_queue_empty = (_file_queue_tasks.empty());
@@ -2392,7 +2397,7 @@ void
 PostUI :: select_parts ()
 {
 
-  tasks_set set(get_selected_files());
+  tasks_v set(get_selected_files());
   _upload_ptr = *set.begin();
 
   if (!_upload_ptr) return;
@@ -2453,13 +2458,15 @@ PostUI :: PostUI (GtkWindow    * parent,
                   Profiles     & profiles,
                   GMimeMessage * message,
                   Prefs        & prefs,
-                  GroupPrefs   & group_prefs):
+                  GroupPrefs   & group_prefs,
+                  ArticleCache & cache):
   _data (data),
   _queue (queue),
   _gs (gs),
   _profiles (profiles),
   _prefs (prefs),
   _group_prefs (group_prefs),
+  _cache (cache),
   _root (0),
   _from_combo (0),
   _subject_entry (0),
@@ -2529,7 +2536,8 @@ PostUI :: create_window (GtkWidget    * parent,
                          Profiles     & profiles,
                          GMimeMessage * message,
                          Prefs        & prefs,
-                         GroupPrefs   & group_prefs)
+                         GroupPrefs   & group_prefs,
+                         ArticleCache & cache)
 {
   // can't post without a profile...
   if (!profiles.has_profiles())
@@ -2550,11 +2558,11 @@ PostUI :: create_window (GtkWidget    * parent,
       return 0;
   }
 
-  return new PostUI (0, data, queue, gs, profiles, message, prefs, group_prefs);
+  return new PostUI (0, data, queue, gs, profiles, message, prefs, group_prefs, cache);
 }
 
 void
-PostUI :: prompt_user_for_queueable_files (tasks_set& queue, GtkWindow * parent, const Prefs& prefs)
+PostUI :: prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, const Prefs& prefs)
 {
   const Profile profile (get_current_profile ());
   GMimeMessage * message (new_message_from_ui (POSTING));
@@ -2580,15 +2588,20 @@ PostUI :: prompt_user_for_queueable_files (tasks_set& queue, GtkWindow * parent,
 	if (response == GTK_RESPONSE_ACCEPT) {
 		GSList * tmp_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER (w));
 		if (_file_queue_empty) _file_queue_empty=!_file_queue_empty;
+
 		GSList * cur = g_slist_nth (tmp_list,0);
+
     GMimeMessage* msg = new_message_from_ui(POSTING);
+
     char * tmp;
     tmp = (char*)g_mime_object_get_header ((GMimeObject*)msg, "Subject");
     std::string subject= std::string(tmp ? tmp : "");
+
     std::string author;
     profile.get_from_header (author);
+
     quarks_t groups;
-    const char * text = gtk_entry_get_text (GTK_ENTRY(_groups_entry));
+    char * text = (char*)gtk_entry_get_text (GTK_ENTRY(_groups_entry));
     StringView line(text), groupname;
     while (line.pop_token (groupname, ',')) {
       groupname.trim ();
@@ -2600,22 +2613,15 @@ PostUI :: prompt_user_for_queueable_files (tasks_set& queue, GtkWindow * parent,
     for (; cur; cur = cur->next, ++i)
 		{
 		  TaskUpload* tmp = new TaskUpload(std::string((const char*)cur->data),
-                               profile.posting_server,
-                               groups, subject, author, 0,
+                               profile.posting_server,  _cache,
+                               groups, subject, author, 0, 0,
                                TaskUpload::YENC);
-		  _file_queue_tasks.insert(tmp);
-      TaskUpload::Needed tmp2;
-      const int parts = (int) (((long)tmp->get_byte_count() + (4000*128-1)) / (4000*128));
-      for (int j=1; j<=parts; ++j)
-      {
-        tmp2.partial = true;
-        tmp2.partno = j;
-        tmp->needed().insert(needed_p(j,tmp2));
-      }
+		  _file_queue_tasks.push_back(tmp);
 		}
   	g_slist_free (tmp_list);
   }
 	gtk_widget_destroy (w);
+  g_object_unref (G_OBJECT(message));
 	update_filequeue_tab();
 }
 
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index 1973d68..2f7d76b 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -25,6 +25,7 @@
 #include <pan/general/progress.h>
 #include <pan/tasks/queue.h>
 #include <pan/usenet-utils/text-massager.h>
+#include <pan/data/article-cache.h>
 #include "group-prefs.h"
 
 namespace pan
@@ -35,7 +36,7 @@ namespace pan
   class Queue;
 
 
-  typedef std::set<TaskUpload*> tasks_set;
+  typedef std::list<TaskUpload*> tasks_v;
 
   /**
    * Dialog for posting new messages Pan's GTK GUI.
@@ -45,13 +46,13 @@ namespace pan
   {
     public:
       static PostUI* create_window (GtkWidget*, Data&, Queue&, GroupServer&, Profiles&,
-                                    GMimeMessage*, Prefs&, GroupPrefs&);
+                                    GMimeMessage*, Prefs&, GroupPrefs&, ArticleCache&);
 
-      void prompt_user_for_queueable_files (tasks_set& queue, GtkWindow * parent, const Prefs& prefs);
+      void prompt_user_for_queueable_files (tasks_v& queue, GtkWindow * parent, const Prefs& prefs);
 
     protected:
       PostUI (GtkWindow*, Data&, Queue&, GroupServer&, Profiles&,
-              GMimeMessage*, Prefs&, GroupPrefs&);
+              GMimeMessage*, Prefs&, GroupPrefs&, ArticleCache&);
     public:
       ~PostUI ();
 
@@ -144,7 +145,7 @@ namespace pan
 
       /* binpost */
       bool _file_queue_empty;
-      tasks_set _file_queue_tasks;
+      tasks_v _file_queue_tasks;
 
     private:
       void add_actions (GtkWidget* box);
@@ -184,12 +185,15 @@ namespace pan
       static gboolean group_entry_changed_idle (gpointer);
       static void group_entry_changed_cb (GtkEditable*, gpointer);
 
+    protected:
+      ArticleCache& _cache;
+
     public:
       void set_spellcheck_enabled (bool);
       void spawn_editor_dead(char *);
 
     public:
-      tasks_set  get_selected_files () const;
+      tasks_v  get_selected_files () const;
 
     private:
       static void get_selected_files_foreach (GtkTreeModel*,
diff --git a/pan/tasks/encoder.cc b/pan/tasks/encoder.cc
index 57c5fa1..2333b63 100644
--- a/pan/tasks/encoder.cc
+++ b/pan/tasks/encoder.cc
@@ -102,7 +102,7 @@ Encoder :: do_work()
       log_errors.push_back(_("Error initializing uulib")); // log error
     } else {
       UUSetMsgCallback (this, uu_log);
-      UUSetBusyCallback (this, uu_busy_poll, 100);
+      UUSetBusyCallback (this, uu_busy_poll, 200);
 
       g_snprintf(buf,bufsz,"%s/%s.%d", uulib.c_str(), basename.c_str(), cnt);
       outfile = fopen(buf,"wb");
@@ -115,7 +115,6 @@ Encoder :: do_work()
                                (char*)author.c_str(), (char*)subject.c_str(),
                                0);
 
-        _end:
         if (outfile) fclose(outfile);
         if (res != UURET_CONT) break;
         g_snprintf(buf,bufsz,"%s/%s.%d", uulib.c_str(), basename.c_str(), ++cnt);
@@ -196,7 +195,6 @@ Encoder :: uu_busy_poll (void * d, uuprogress *p)
   self->mut.lock();
     self->percent = self->get_percentage(*p);
     self->current_file = p->curfile;
-    self->total_parts = p->numparts;
   self->mut.unlock();
 
   return self->was_cancelled(); // returning true tells uulib to abort
diff --git a/pan/tasks/encoder.h b/pan/tasks/encoder.h
index e31afa4..142c46c 100644
--- a/pan/tasks/encoder.h
+++ b/pan/tasks/encoder.h
@@ -90,7 +90,6 @@ namespace pan
       Mutex mut;
       volatile double percent;
       std::string current_file; // the current file we are decoding, with path
-      int total_parts;
 
       static void uu_log(void *thiz, char *message, int severity);
       double get_percentage (const uuprogress& p) const;
diff --git a/pan/tasks/nzb.cc b/pan/tasks/nzb.cc
index 8eb5d32..fcb5428 100644
--- a/pan/tasks/nzb.cc
+++ b/pan/tasks/nzb.cc
@@ -180,11 +180,11 @@ namespace
     else if (!strcmp (element_name, "upload"))
     {
       debug("adding taskupload from nzb.\n");
-      TaskUpload* tmp = new TaskUpload (mc.path, const_cast<const Quark&>(mc.posting_server),
-                          mc.groups, mc.a.subject.to_string(), mc.a.author.to_string(), 0, TaskUpload::YENC);
-       //update needed struct
+      TaskUpload::needed_t tmp2;
       foreach (TaskUpload::needed_t, mc.needed_parts, it)
-        tmp->needed().insert(*it);
+        tmp2.insert(*it);
+      TaskUpload* tmp = new TaskUpload (mc.path, const_cast<const Quark&>(mc.posting_server), mc.cache,
+                          mc.groups, mc.a.subject.to_string(), mc.a.author.to_string(), &tmp2, 0, TaskUpload::YENC);
       mc.tasks.push_back (tmp);
     }
   }
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
index 0f62983..5107025 100644
--- a/pan/tasks/task-upload.cc
+++ b/pan/tasks/task-upload.cc
@@ -64,13 +64,13 @@ namespace
 }
 
 
-namespace
-{
-  void delete_cache(const TaskUpload::Needed& n)
-  {
-    unlink(n.filename.c_str());
-  }
-}
+//namespace
+//{
+//  void delete_cache(const TaskUpload::Needed& n)
+//  {
+//    unlink(n.filename.c_str());
+//  }
+//}
 
 /***
 ****
@@ -78,15 +78,18 @@ namespace
 
 TaskUpload :: TaskUpload ( const std::string         & filename,
                            const Quark               & server,
+                           ArticleCache              & cache,
                            quarks_t                  & groups,
                            std::string                 subject,
                            std::string                 author,
+                           needed_t                  * imported,
                            Progress::Listener        * listener,
                            const TaskUpload::EncodeMode  enc):
   Task ("UPLOAD", get_description(filename.c_str())),
   _filename(filename),
   _basename (g_path_get_basename(filename.c_str())),
   _server(server),
+  _cache(cache),
   _groups(groups),
   _subject (subject),
   _author(author),
@@ -97,33 +100,77 @@ TaskUpload :: TaskUpload ( const std::string         & filename,
   if (listener != 0)
     add_listener (listener);
 
+  needed_t& tmp = *imported;
+  if (imported)
+    foreach (needed_t, tmp, nit)
+      _needed.insert(*nit);
+
   struct stat sb;
   stat(filename.c_str(),&sb);
   _bytes = sb.st_size;
+
+  build_needed_tasks(imported);
   update_work ();
 }
 
 void
+TaskUpload :: build_needed_tasks(bool imported)
+{
+
+  _total_parts = (int) (((long)get_byte_count() + (4000*128-1)) / (4000*128));
+  TaskUpload::Needed tmp;
+  char buf[2048];
+  struct stat sb;
+  const char* uulib = file::get_uulib_path().c_str();
+  mid_sequence_t names;
+  int cnt(0);
+
+  for (int i=1;i<=_total_parts; ++i)
+  {
+    if (imported)
+    {
+      needed_t::iterator it = _needed.find(i);
+      if (it == _needed.end())
+        continue;
+    }
+    tmp.partno = i;
+    g_snprintf(buf,sizeof(buf),"%s/%s.%d", uulib, _basename.c_str(), i);
+    tmp.filename = buf;
+    tmp.partial = false;
+    tmp.nntp = 0;
+    stat(buf, &sb);
+    tmp.bytes = (unsigned long)sb.st_size;
+    _needed.insert(std::pair<int,Needed>(i,tmp));
+    ++cnt;
+  }
+  _needed_parts = cnt;
+
+  // reserve cache
+  _cache.reserve (names);
+}
+
+void
 TaskUpload :: update_work (NNTP* checkin_pending)
 {
 
   int working(0);
-  foreach (needed_t, _needed, nit) {
+  foreach (needed_t, _needed, nit)
+  {
     Needed& n (nit->second);
     if (n.nntp && n.nntp!=checkin_pending)
       ++working;
   }
 
-  if (!_encoder && !_encoder_has_run )
+  if (!_encoder && !_encoder_has_run)
   {
     _state.set_need_encoder();
-  } else if(working )
+  } else if(working)
   {
     _state.set_working();
   } else if (_encoder_has_run && !_needed.empty())
   {
     _state.set_need_nntp(_server);
-  } else if (_needed.empty() && _encoder_has_run )
+  } else if (_needed.empty())
   {
     _state.set_completed();
     set_finished(OK);
@@ -139,9 +186,15 @@ TaskUpload :: use_nntp (NNTP * nntp)
 {
 
   Needed * needed (0);
-  for (needed_t::iterator it(_needed.begin()), end(_needed.end()); !needed && it!=end; ++it)
-    if (it->second.nntp==0)
-      needed = &it->second;
+  foreach (needed_t, _needed, nit)
+  {
+      if (nit->second.nntp==0)
+      {
+        needed = &nit->second;
+        break;
+      }
+  }
+
 
   if (!needed)
   {
@@ -151,13 +204,15 @@ TaskUpload :: use_nntp (NNTP * nntp)
   else
   {
     needed->nntp = nntp;
-    set_status_va (_("Uploading \"%s\" - Part %d of %d"), _basename.c_str(), needed->partno, _total_parts);
+
+    set_status_va (_("Uploading %s - Part %d of %d"), _basename.c_str(), needed->partno, _total_parts);
+
     std::stringstream tmp;
     std::ifstream in(needed->filename.c_str(), std::ifstream::in);
-    char tmp_char;
-    while (in.good()) {
-      tmp << (tmp_char=(char) in.get());
-    }
+    if (in.bad())
+      debug("error with stream!!!\n");
+    while (in.good())
+      tmp << (char) in.get();
     in.close();
     nntp->post(StringView(tmp.str()), this);
     update_work ();
@@ -169,13 +224,14 @@ TaskUpload :: use_nntp (NNTP * nntp)
 ***/
 
 void
-TaskUpload :: on_nntp_line  (NNTP               * nntp,
-                              const StringView   & line_in)
+TaskUpload :: on_nntp_line (NNTP * nntp,
+                              const StringView & line_in)
 {}
 
+
 void
-TaskUpload :: on_nntp_done  (NNTP             * nntp,
-                             Health             health,
+TaskUpload :: on_nntp_done (NNTP * nntp,
+                             Health health,
                              const StringView & response)
 {
 
@@ -184,16 +240,20 @@ TaskUpload :: on_nntp_done  (NNTP             * nntp,
     if (it->second.nntp == nntp)
       break;
 
+  bool post_ok(false);
   switch (health)
   {
     case OK:
+      _needed.erase (it);
+      post_ok = true;
+      increment_step(1);
       break;
-    /* if the connection was aborted with SIGPIPE, let this error silently by and
-     * let GIOSocket code handle this */
     case ERR_NETWORK:
-      std::cerr<<"err network!\n";
-      it->second.reset();
-      goto _end;
+      _state.set_need_nntp(nntp->_server);
+      break;
+    case ERR_COMMAND:
+      _needed.erase (it);
+      break;
   }
 
   switch (atoi(response.str))
@@ -203,13 +263,10 @@ TaskUpload :: on_nntp_done  (NNTP             * nntp,
       this->stop();
       break;
     case POSTING_FAILED:
-      Log :: add_err_va (_("Posting of file %s failed: %s"), _basename.c_str(), response.str);
+      Log :: add_err_va (_("Posting failed: %s"), response.str);
       break;
     case ARTICLE_POSTED_OK:
-      delete_cache(it->second);
-      _needed.erase (it);
-      increment_step(1);
-      if (_needed.empty())
+      if (_needed.empty() && post_ok)
         Log :: add_info_va(_("Posting of file %s succesful: %s"),
                _basename.c_str(), response.str);
       break;
@@ -217,12 +274,9 @@ TaskUpload :: on_nntp_done  (NNTP             * nntp,
       // lockout for 120 secs, but try
       _state.set_need_nntp(nntp->_server);
       break;
-    default:
-      Log :: add_err_va (_("Got unknown response code: %s"),response.str);
-      break;
   }
 
-  _end:
+
   update_work(nntp);
   check_in (nntp, health);
 
@@ -237,7 +291,7 @@ TaskUpload :: get_bytes_remaining () const
 {
   unsigned long bytes (0);
   foreach_const (needed_t, _needed, it)
-    bytes += it->second.bytes;
+    bytes += (unsigned long)it->second.bytes;
   return bytes;
 }
 
@@ -255,7 +309,7 @@ TaskUpload :: use_encoder (Encoder* encoder)
   std::string groups;
   quarks_t::iterator it = _groups.begin();
   int i(0);
-  for (; it != _groups.end(); ++it, ++i)
+  for (; it != _groups.end(); it, ++it, ++i)
   {
     if (i<_groups.size()&& i>0 && _groups.size()>1) groups += ",";
     groups += (*it).to_string();
@@ -267,8 +321,8 @@ TaskUpload :: use_encoder (Encoder* encoder)
 void
 TaskUpload :: stop ()
 {
-//  if (_encoder)
-//      _encoder->cancel();
+  if (_encoder)
+      _encoder->cancel();
 }
 
 // called in the main thread by WorkerPool
@@ -290,63 +344,13 @@ TaskUpload :: on_worker_done (bool cancelled)
     foreach_const(Encoder::log_t, _encoder->log_infos, it)
       Log :: add_info(it->c_str());
 
-    int num_errors = _encoder->log_severe.size() +
-                     _encoder->log_errors.size();
-
     if (!_encoder->log_errors.empty())
       set_error (_encoder->log_errors.front());
 
-    if (num_errors>0)
-    {
-      /* stop state if encoder has encountered errors */
-      _state.set_completed ();
-      set_finished(ERR_LOCAL);
-    }
-    else
     {
-      set_step (100);
+      set_step (0);
+      init_steps(_needed_parts);
       _encoder_has_run = true;
-      _total_parts = _encoder->total_parts;
-      /*enqueue all parts into the global needed_t list.
-        update_work will then assign a pointer to the begin
-        which will be used for an nntp upload.
-        on nntp_done, the list is decreased by one member
-       */
-      Needed n;
-      char buf[2048];
-      struct stat sb;
-
-      int total(0);
-      /* not found: skip, we don't need that part
-         found: if (partial) then assign the needed values
-      */
-      for (int i=1; i<=_total_parts; ++i)
-      {
-        needed_t::iterator it = _needed.find(i);
-        if (it == _needed.end())
-          continue;
-        else if (it->second.partial)
-        {
-          n.partno = i;
-          g_snprintf(buf,sizeof(buf),"%s/%s.%d",
-                   file::get_uulib_path().c_str(),
-                   _basename.c_str(), i);
-          n.filename = buf;
-          stat(buf, &sb);
-          n.bytes = sb.st_size;
-        }
-          ++total;
-      }
-
-      if (total==0)
-      {
-        _state.set_completed();
-        set_finished(OK);
-      } else
-      {
-        init_steps (_total_parts);
-        set_step (total);
-      }
     }
   }
 
diff --git a/pan/tasks/task-upload.h b/pan/tasks/task-upload.h
index edd309c..95d899e 100644
--- a/pan/tasks/task-upload.h
+++ b/pan/tasks/task-upload.h
@@ -48,6 +48,8 @@ namespace pan
   {
     public:
 
+      typedef std::vector<Quark> mid_sequence_t;
+
       struct Needed {
         std::string filename;
         unsigned long bytes;
@@ -70,9 +72,11 @@ namespace pan
       // life cycle
       TaskUpload ( const std::string         & filename,
                    const Quark               & server,
+                   ArticleCache              & cache,
                    quarks_t                  & groups,
                    std::string                 subject,
                    std::string                 author,
+                   needed_t                  * imported=0,
                    Progress::Listener        * listener= 0,
                    TaskUpload::EncodeMode enc= YENC);
       virtual ~TaskUpload ();
@@ -105,7 +109,7 @@ namespace pan
       void on_worker_done (bool cancelled);
 
     protected:
-      const Quark _server;
+      Quark _server;
 
     private: // implementation
       friend class Encoder;
@@ -118,11 +122,12 @@ namespace pan
       TaskUpload::EncodeMode _encode_mode;
       quarks_t _groups;
       std::string _subject, _author;
-      int _total_parts; // filled in by encoder
+      int _total_parts, _needed_parts;
       unsigned long _bytes;
       Mutex mut;
-      int _pos_in_queue;
-      char* _tmp;   // for g_path etc...
+      ArticleCache& _cache;
+
+      void build_needed_tasks(bool);
 
     private:
       needed_t       _needed;
diff --git a/uulib/uuencode.c b/uulib/uuencode.c
index b57e389..2f53c8b 100644
--- a/uulib/uuencode.c
+++ b/uulib/uuencode.c
@@ -1545,9 +1545,9 @@ UUE_PrepSingleExt (FILE *outfile, FILE *infile,
 
   if (encoding == YENC_ENCODED) {
     if (subject)
-      sprintf (subline, "%s \"%s\" (1/1)", subject, oname);
+      sprintf (subline, "%s \"%s\"", subject, oname);
     else
-      sprintf (subline, "%s (1/1)", oname);
+      sprintf (subline, "%s ", oname);
   }
   else {
     if (subject)



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