Author: abrander
Date: 2009-08-10 19:06:02 +0200 (Mon, 10 Aug 2009)
New Revision: 2616

Modified:
   trunk/src/gtk-interface.c
   trunk/src/rs-photo.c
   trunk/src/rs-preload.c
   trunk/src/rs-preload.h
   trunk/src/rs-store.c
Log:
Changed preloader to only cache binary file data (using the OS cache) and 
removed preloader checkbox from preferences.

Modified: trunk/src/gtk-interface.c
===================================================================
--- trunk/src/gtk-interface.c   2009-08-09 17:28:54 UTC (rev 2615)
+++ trunk/src/gtk-interface.c   2009-08-10 17:06:02 UTC (rev 2616)
@@ -37,7 +37,6 @@
 #include "filename.h"
 #include "rs-store.h"
 #include "rs-preview-widget.h"
-#include "rs-preload.h"
 #include "rs-photo.h"
 #include "rs-external-editor.h"
 #include "rs-actions.h"
@@ -353,17 +352,6 @@
        }
 }
 
-static void
-gui_preference_preload_changed(GtkToggleButton *togglebutton, gpointer 
user_data)
-{
-       if (togglebutton->active)
-               rs_preload_set_maximum_memory(200*1024*1024);
-       else
-               rs_preload_set_maximum_memory(0);
-
-       return;
-}
-
 typedef struct {
        GtkWidget *example_label;
        GtkWidget *event;
@@ -563,7 +551,6 @@
        GtkWidget *local_cache_check;
        GtkWidget *system_theme_check;
        GtkWidget *load_gdk_check;
-       GtkWidget *preload_check;
        GtkWidget *show_filenames;
 
 /*
@@ -640,11 +627,6 @@
        load_gdk_check = checkbox_from_conf(CONF_LOAD_GDK, _("Load 8 bit photos 
(jpeg, png, etc)"), FALSE);
        gtk_box_pack_start (GTK_BOX (preview_page), load_gdk_check, FALSE, 
TRUE, 0);
 
-       preload_check = checkbox_from_conf(CONF_PRELOAD, _("Preload photos"), 
FALSE);
-       gtk_box_pack_start (GTK_BOX (preview_page), preload_check, FALSE, TRUE, 
0);
-       g_signal_connect ((gpointer) preload_check, "toggled",
-               G_CALLBACK (gui_preference_preload_changed), rs);
-
 /*
        batch_page = gtk_vbox_new(FALSE, 4);
        gtk_container_set_border_width (GTK_CONTAINER (batch_page), 6);
@@ -1138,15 +1120,6 @@
 
        gtk_widget_show_all (rs->window);
 
-       {
-               gboolean preload = FALSE;
-               rs_conf_get_boolean(CONF_PRELOAD, &preload);
-               if (preload)
-                       rs_preload_set_maximum_memory(200*1024*1024);
-               else
-                       rs_preload_set_maximum_memory(0);
-       }
-
        if (argc > 1)
        {
                gchar *path;

Modified: trunk/src/rs-photo.c
===================================================================
--- trunk/src/rs-photo.c        2009-08-09 17:28:54 UTC (rev 2615)
+++ trunk/src/rs-photo.c        2009-08-10 17:06:02 UTC (rev 2616)
@@ -20,7 +20,6 @@
 #include <rawstudio.h>
 #include "rs-photo.h"
 #include "rs-cache.h"
-#include "rs-preload.h"
 
 static void rs_photo_class_init (RS_PHOTOClass *klass);
 
@@ -516,25 +515,16 @@
        RSSettingsMask mask;
        gint i;
 
-       /* Try preloaded first! */
-       photo = rs_get_preloaded(filename);
-       if (photo)
-               return photo;
-
-       /* If photo not found in cache, try to load it */
-       if (!photo)
+       image = rs_filetype_load(filename);
+       if (image)
        {
-               image = rs_filetype_load(filename);
-               if (image)
-               {
-                       photo = rs_photo_new();
+               photo = rs_photo_new();
 
-                       /* Set filename */
-                       photo->filename = g_strdup(filename);
+               /* Set filename */
+               photo->filename = g_strdup(filename);
 
-                       /* Set input image */
-                       photo->input = image;
-               }
+               /* Set input image */
+               photo->input = image;
        }
 
        /* If photo available, read & process metadata */

Modified: trunk/src/rs-preload.c
===================================================================
--- trunk/src/rs-preload.c      2009-08-09 17:28:54 UTC (rev 2615)
+++ trunk/src/rs-preload.c      2009-08-10 17:06:02 UTC (rev 2616)
@@ -16,286 +16,89 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
  */
-
-#include <gtk/gtk.h>
-#include <glib.h>
+#if __gnu_linux__
+#define _GNU_SOURCE
+#include <fcntl.h>
+#endif /* __gnu_linux__ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "rs-preload.h"
-#include "rs-photo.h"
 
-#define PRELOAD_DEBUG if (0) printf
+static GAsyncQueue *queue = NULL;
 
-static void rs_preload(const gchar *filename);
-
-static GThreadPool *pool = NULL;
-
-/* Which images are "near" the current image */
-static GStaticMutex near_lock = G_STATIC_MUTEX_INIT;
-static GList *near = NULL;
-
-/* The queue - to be processed */
-static GStaticMutex queue_lock = G_STATIC_MUTEX_INIT;
-static GList *queue = NULL;
-
-/* Which images are currently preloaded */
-static GStaticMutex preloaded_lock = G_STATIC_MUTEX_INIT;
-
-static GList *preloaded = NULL; /* RS_PRELOADED * */
-static size_t preloaded_memory_in_use = 0;
-
-/* The queue - to be processed */
-static GStaticMutex average_size_lock = G_STATIC_MUTEX_INIT;
-static size_t average_size = 0;
-
-/* The maximum amount of memory to use in bytes */
-static size_t max_memory = 0; /* The maximum memory to use for preload cache */
-
-/**
- * Searches in a GList of strings
- */
-static gint
-g_list_str_equal(gconstpointer a, gconstpointer b)
+static gpointer
+worker(gpointer data)
 {
-       if (!(a&&b)) return -1;
-       return !g_str_equal(a, b);
-}
+       gchar *filename;
+       gint fd;
+       struct stat st;
 
-/**
- * Searches for a specific filename in a GList of RS_PRELOADED *
- */
-static gint
-g_list_find_filename(gconstpointer a, gconstpointer b)
-{
-       if (!(a&&b)) return -1;
-       return !g_str_equal((RS_PHOTO(a))->filename, b);
-}
+       while (1)
+       {
+               data = g_async_queue_pop(queue);
+               if (data == NULL)
+                       continue;
 
-/**
- * Removes exactly one image from preload-cache, trying to keep images that 
are "near"
- */
-static void
-_remove_one_image()
-{
-       gint len, pos;
-       RS_PHOTO *photo = NULL;
-       GList *remove = NULL;
-       GList *l;
+               filename = data;
+               fd = open(filename, O_RDONLY);
 
-       len = g_list_length(preloaded);
-       pos = len-1;
-
-       /* Try to find the last cached - NOT in near list */
-       while (pos >= 0)
-       {
-               l = g_list_nth(preloaded, pos);
-               photo = l->data;
-               if(!(g_list_find_custom(near, photo->filename, 
g_list_str_equal)))
+               if (fd > 0)
                {
-                       PRELOAD_DEBUG("\033[34m[NOT NEAR] ");
-                       remove = l;
-                       break;
-               }
-               pos--;
-       }
-
-       /* If all are near, pick the one farest away */
-       if (!remove)
-       {
-               len = g_list_length(near);
-               pos = len-1;
-               while(pos >= 0)
-               {
-                       if((l = g_list_find_custom(preloaded, 
g_list_nth_data(near, pos), g_list_find_filename)))
+                       stat(filename, &st);
+                       if (st.st_size > 0)
                        {
-                               PRELOAD_DEBUG("\033[34m[NEAR] ");
-                               remove = l;
-                               break;
+#if __gnu_linux__
+                               readahead(fd, 0, st.st_size);
+#else
+                               gint bytes_read = 0;
+                               gchar *tmp = g_new(gchar, st.st_size);
+                               while(bytes_read < st.st_size)
+                                       bytes_read += read(fd, tmp, 
st.st_size-bytes_read);
+                               g_free(tmp);
+#endif /* __gnu_linux__ */
                        }
-                       pos--;
+                       close(fd);
                }
-       }
 
-       if (remove)
-       {
-               photo = remove->data;
-               PRELOAD_DEBUG("Removed %s\033[0m\n", photo->filename);
-
-               preloaded_memory_in_use -= 
rs_image16_get_footprint(photo->input);
-
-               g_object_unref(photo);
-
-               preloaded = g_list_remove_link(preloaded, remove);
-               g_list_free(remove);
+               g_free(data);
        }
+       return NULL;
 }
 
 static void
-worker_thread(gpointer data, gpointer bogus)
+init()
 {
-       gchar *filename = (gchar *) data;
-       RS_PHOTO *photo = NULL;
+       static GStaticMutex lock = G_STATIC_MUTEX_INIT;
 
-       photo = rs_photo_load_from_file(filename);
-       if (photo)
+       g_static_mutex_lock(&lock);
+       if (queue == NULL)
        {
-               GList *q = NULL;
-               size_t footprint = rs_image16_get_footprint(photo->input);
-               PRELOAD_DEBUG("\033[34mPreloading %s\033[0m\n", filename);
-
-               g_static_mutex_lock(&queue_lock);
-               g_static_mutex_lock(&preloaded_lock);
-
-               while((preloaded_memory_in_use + footprint) > max_memory)
-                       _remove_one_image();
-               preloaded_memory_in_use += footprint;
-
-               /* Move from queue to preloaded */
-               if ((q = g_list_find_custom(queue, filename, g_list_str_equal)))
-                       queue = g_list_remove_link(queue, q);
-               preloaded = g_list_prepend(preloaded, photo);
-
-               g_static_mutex_unlock(&preloaded_lock);
-               g_static_mutex_unlock(&queue_lock);
-
-               /* Calculate average image size */
-               g_static_mutex_lock(&average_size_lock);
-               if (average_size == 0)
-                       average_size = footprint;
-               else
-                       average_size = (average_size+footprint+1)/2;
-               g_static_mutex_unlock(&average_size_lock);
+               queue = g_async_queue_new_full(g_free);
+               g_thread_create_full(worker, NULL, 0, FALSE, FALSE, 
G_THREAD_PRIORITY_LOW, NULL);
        }
-       PRELOAD_DEBUG("\033[33m[%zd/%zdMB used] [%d tasks unprocessed] [%zdMB 
avg]\033[0m\n", preloaded_memory_in_use/(1024*1024), max_memory/(1024*1024), 
g_thread_pool_unprocessed(pool), average_size/(1024*1024));
+       g_static_mutex_unlock(&lock);
 }
 
 /**
- * Remove all images from near list, this should be called before populating 
near
+ * Empty the current queue
  */
-void
-rs_preload_near_remove_all()
+extern void
+rs_preload_cancel_all()
 {
-       /* Clear the "near" array, will be filled by rs_preload_near_add() */
-       g_static_mutex_lock(&near_lock);
-       if (near)
-       {
-               g_list_foreach(near, (GFunc) g_free, NULL);
-               g_list_free(near);
-               near = NULL;
-       }
-       g_static_mutex_unlock(&near_lock);
-}
+       init();
 
-/**
- * Add a near image, near images will be free'ed last,
- * rs_preload_near_remove_all() should be called first, to empty the list
- */ 
-void
-rs_preload_near_add(const gchar *filename)
-{
-       if (max_memory == 0) return;
-       g_static_mutex_lock(&near_lock);
-       near = g_list_prepend(near, g_strdup(filename));
-       g_static_mutex_unlock(&near_lock);
-       rs_preload(filename);
+       while(g_async_queue_try_pop(queue));
 }
 
 /**
- * Preload a file
- * @param filename The file to preload
+ * Preloads a file - this will add file content to the OS cache
+ * @param filename A filename to preload
  */
-static void
+void
 rs_preload(const gchar *filename)
 {
-       if (max_memory == 0) return;
+       init();
 
-       g_static_mutex_lock(&queue_lock);
-       g_static_mutex_lock(&preloaded_lock);
-       if ((!g_list_find_custom(queue, filename, g_list_str_equal))
-               && (!g_list_find_custom(preloaded, filename, 
g_list_find_filename)))
-       {
-               queue = g_list_prepend(queue, g_strdup(filename));
-               g_thread_pool_push(pool, g_strdup(filename), NULL);
-       }
-       g_static_mutex_unlock(&preloaded_lock);
-       g_static_mutex_unlock(&queue_lock);
+       g_async_queue_push(queue, g_strdup(filename));
 }
-
-/**
- * Get a preloaded photo
- * @param filename A filename
- * @return The new RS_PHOTO or NULL if not preloaded
- */
-RS_PHOTO *
-rs_get_preloaded(const gchar *filename)
-{
-       RS_PHOTO *photo = NULL;
-
-       if (max_memory == 0) return NULL;
-
-       if (filename)
-       {
-               GList *l;
-               g_static_mutex_lock(&preloaded_lock);
-               if ((l = g_list_find_custom(preloaded, filename, 
g_list_find_filename)))
-               {
-                       PRELOAD_DEBUG("\033[32m%s preloaded\033[0m\n", 
filename);
-                       photo = g_object_ref(l->data);
-               }
-               else
-                       PRELOAD_DEBUG("\033[31m%s NOT preloaded\033[0m\n", 
filename);
-               g_static_mutex_unlock(&preloaded_lock);
-       }
-
-       return photo;
-}
-
-/**
- * Get a qualified guess about how many photos we would like to have marked as
- * near
- * @return A number of photos to mark as near
- */
-gint
-rs_preload_get_near_count()
-{
-       /* Defaults to 2, this should not saturate anyone */
-       gint near = 2;
-
-       if (max_memory == 0) return 0;
-
-       g_static_mutex_lock(&average_size_lock);
-       if (average_size > 0)
-               near = ((max_memory*2)/3)/average_size-1;
-       g_static_mutex_unlock(&average_size_lock);
-
-       /* Bigger is not always better! */
-       if (near > 3)
-               near = 3;
-
-       PRELOAD_DEBUG("near: %d\n", near);
-
-       return near;
-}
-
-/**
- * Set the maximum amount of memory to be used for preload buffer
- * @param max A value in bytes, everything below 100MB will be interpreted as 0
- */
-void
-rs_preload_set_maximum_memory(size_t max)
-{
-       if (max < (100*1024*1024))
-               max = 0;
-       max_memory = max;
-
-       /* Initialize thread pool */
-       if ((max_memory > 0) && (!pool))
-               pool = g_thread_pool_new(worker_thread, NULL, 2, TRUE, NULL);
-
-       g_static_mutex_lock(&queue_lock);
-       g_static_mutex_lock(&preloaded_lock);
-
-       while(preloaded_memory_in_use > max_memory)
-               _remove_one_image();
-
-       g_static_mutex_unlock(&preloaded_lock);
-       g_static_mutex_unlock(&queue_lock);
-}

Modified: trunk/src/rs-preload.h
===================================================================
--- trunk/src/rs-preload.h      2009-08-09 17:28:54 UTC (rev 2615)
+++ trunk/src/rs-preload.h      2009-08-10 17:06:02 UTC (rev 2616)
@@ -19,44 +19,19 @@
 
 #ifndef RS_PRELOAD_H
 #define RS_PRELOAD_H
-#include "application.h"
+#include <glib.h>
 
 /**
- * Empty the near list
+ * Empty the current queue
  */
 extern void
-rs_preload_near_remove_all();
+rs_preload_cancel_all();
 
 /**
- * Add a filename to the near list, the near list is a previous or following
- * number of photos, given by rs_preload_get_near_count() from the currently
- * selected image
- * @param filename A filename
+ * Preloads a file - this will add file content to the OS cache
+ * @param filename A filename to preload
  */
 extern void
-rs_preload_near_add(const gchar *filename);
+rs_preload(const gchar *filename);
 
-/**
- * Get a preloaded photo
- * @param filename A filename
- * @return The new RS_PHOTO or NULL if not preloaded
- */
-extern RS_PHOTO *
-rs_get_preloaded(const gchar *filename);
-
-/**
- * Get a qualified guess about how many photos we would like to have marked as
- * near
- * @return A number of photos to mark as near
- */
-extern gint
-rs_preload_get_near_count();
-
-/**
- * Set the maximum amount of memory to be used for preload buffer
- * @param max A value in bytes, everything below 100MB will be interpreted as 0
- */
-void
-rs_preload_set_maximum_memory(size_t max);
-
 #endif /* RS_PRELOAD_H */

Modified: trunk/src/rs-store.c
===================================================================
--- trunk/src/rs-store.c        2009-08-09 17:28:54 UTC (rev 2615)
+++ trunk/src/rs-store.c        2009-08-10 17:06:02 UTC (rev 2616)
@@ -358,22 +358,20 @@
        gchar *filename;
        gtk_tree_model_get(model, iter, FULLNAME_COLUMN, &filename, -1);
 
-       rs_preload_near_add(filename);
+       rs_preload(filename);
 }
 
 static void
 predict_preload(RSStore *store, gboolean initial)
 {
        GList *selected = NULL;
-       gint n, near;
+       gint n, near = 5;
        GtkTreeIter iter;
        GtkIconView *iconview = GTK_ICON_VIEW(store->current_iconview);
        GtkTreePath *path, *next, *prev;
        GtkTreeModel *model = gtk_icon_view_get_model (iconview);
 
-       near = rs_preload_get_near_count();
-       if (near < 1) return;
-       rs_preload_near_remove_all();
+       rs_preload_cancel_all();
 
        /* Get a list of selected icons */
        selected = gtk_icon_view_get_selected_items(iconview);


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to