[gnome-documents] pdf: implement a simple cache for converted OpenOffice files
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents] pdf: implement a simple cache for converted OpenOffice files
- Date: Tue, 23 Aug 2011 14:39:23 +0000 (UTC)
commit 505cd20483a204bd486d4fdefdc64e35501674d9
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Tue Aug 23 09:26:53 2011 -0400
pdf: implement a simple cache for converted OpenOffice files
src/lib/gd-pdf-loader.c | 185 ++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 167 insertions(+), 18 deletions(-)
---
diff --git a/src/lib/gd-pdf-loader.c b/src/lib/gd-pdf-loader.c
index 5847512..a7cd2b5 100644
--- a/src/lib/gd-pdf-loader.c
+++ b/src/lib/gd-pdf-loader.c
@@ -48,6 +48,11 @@ typedef struct {
gchar *pdf_path;
GPid unoconv_pid;
GDataDownloadStream *stream;
+
+ guint64 pdf_cache_mtime;
+ guint64 original_file_mtime;
+
+ gboolean unlink_cache;
} PdfLoadJob;
struct _GdPdfLoaderPrivate {
@@ -129,7 +134,9 @@ pdf_load_job_free (PdfLoadJob *job)
g_free (job->uri);
if (job->pdf_path != NULL) {
- g_unlink (job->pdf_path);
+ if (job->unlink_cache)
+ g_unlink (job->pdf_path);
+
g_free (job->pdf_path);
}
@@ -153,6 +160,7 @@ pdf_load_job_new (GSimpleAsyncResult *result,
retval->cancellable = g_object_ref (cancellable);
retval->uri = g_strdup (uri);
retval->unoconv_pid = -1;
+ retval->unlink_cache = FALSE;
return retval;
}
@@ -411,6 +419,61 @@ pdf_load_job_from_google_documents (PdfLoadJob *job)
}
static void
+openoffice_set_mtime_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PdfLoadJob *job = user_data;
+ GError *error = NULL;
+ GFileInfo *out_info = NULL;
+
+ g_file_set_attributes_finish (G_FILE (source), res, &out_info, &error);
+
+ if (error != NULL) {
+ /* just emit a warning here; setting the mtime is a precaution
+ * against the cache file being externally modified after it has been
+ * created, which is unlikely. Invalidate the cache immediately after
+ * loading the file in this case.
+ */
+ job->unlink_cache = TRUE;
+
+ g_warning ("Cannot set mtime on the cache file; cache will not be valid "
+ "after the file has been viewed. Error: %s", error->message);
+ g_error_free (error);
+ }
+
+ if (out_info != NULL)
+ g_object_unref (out_info);
+
+ pdf_load_job_from_pdf (job);
+}
+
+static void
+pdf_load_job_openoffice_set_attributes (PdfLoadJob *job)
+{
+ GFileInfo *info;
+ GFile *file;
+
+ /* make the file private */
+ g_chmod (job->pdf_path, 0600);
+
+ file = g_file_new_for_path (job->pdf_path);
+ info = g_file_info_new ();
+
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ job->original_file_mtime);
+ g_file_set_attributes_async (file, info,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ job->cancellable,
+ openoffice_set_mtime_ready_cb,
+ job);
+
+ g_object_unref (info);
+ g_object_unref (file);
+}
+
+static void
unoconv_child_watch_cb (GPid pid,
gint status,
gpointer user_data)
@@ -429,16 +492,14 @@ unoconv_child_watch_cb (GPid pid,
return;
}
- pdf_load_job_from_pdf (job);
+ pdf_load_job_openoffice_set_attributes (job);
}
static void
-pdf_load_job_from_openoffice (PdfLoadJob *job)
+pdf_load_job_openoffice_refresh_cache (PdfLoadJob *job)
{
- gchar *doc_path, *pdf_path, *tmp_name, *tmp_path;
+ gchar *doc_path, *cmd;
GFile *file;
- gchar *cmd;
-
gint argc;
GPid pid;
gchar **argv = NULL;
@@ -449,23 +510,14 @@ pdf_load_job_from_openoffice (PdfLoadJob *job)
doc_path = g_file_get_path (file);
g_object_unref (file);
- tmp_name = g_strdup_printf ("gnome-documents-%d.pdf", getpid ());
- tmp_path = g_build_filename (g_get_user_cache_dir (), "gnome-documents", NULL);
- job->pdf_path = pdf_path =
- g_build_filename (tmp_path, tmp_name, NULL);
- g_mkdir_with_parents (tmp_path, 0700);
-
/* call into the unoconv executable to convert the OpenOffice document
* to the temporary PDF.
*/
- cmd = g_strdup_printf ("unoconv -f pdf -o %s %s", pdf_path, doc_path);
-
- g_free (doc_path);
- g_free (tmp_name);
- g_free (tmp_path);
-
+ cmd = g_strdup_printf ("unoconv -f pdf -o %s %s", job->pdf_path, doc_path);
g_shell_parse_argv (cmd, &argc, &argv, &error);
+
g_free (cmd);
+ g_free (doc_path);
if (error != NULL) {
pdf_load_job_complete_error (job, error);
@@ -491,6 +543,103 @@ pdf_load_job_from_openoffice (PdfLoadJob *job)
}
static void
+openoffice_cache_query_info_original_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PdfLoadJob *job = user_data;
+ GError *error = NULL;
+ GFileInfo *info;
+ guint64 mtime;
+
+ info = g_file_query_info_finish (G_FILE (source), res, &error);
+
+ if (error != NULL) {
+ /* try to create the cache anyway - if the source file
+ * is really not readable we'll fail again soon.
+ */
+ pdf_load_job_openoffice_refresh_cache (job);
+
+ g_error_free (error);
+ return;
+ }
+
+ job->original_file_mtime = mtime =
+ g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+ g_object_unref (info);
+
+ if (mtime > job->pdf_cache_mtime)
+ pdf_load_job_openoffice_refresh_cache (job);
+ else
+ /* load the cached file */
+ pdf_load_job_from_pdf (job);
+}
+
+static void
+openoffice_cache_query_info_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ PdfLoadJob *job = user_data;
+ GError *error = NULL;
+ GFileInfo *info;
+ GFile *original_file;
+
+ info = g_file_query_info_finish (G_FILE (source), res, &error);
+
+ if (error != NULL) {
+ /* create/invalidate cache */
+ pdf_load_job_openoffice_refresh_cache (job);
+
+ g_error_free (error);
+ return;
+ }
+
+ job->pdf_cache_mtime =
+ g_file_info_get_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ original_file = g_file_new_for_uri (job->uri);
+ g_file_query_info_async (original_file,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ job->cancellable,
+ openoffice_cache_query_info_original_ready_cb,
+ job);
+
+ g_object_unref (original_file);
+ g_object_unref (info);
+}
+
+static void
+pdf_load_job_from_openoffice (PdfLoadJob *job)
+{
+ gchar *pdf_path, *tmp_name, *tmp_path;
+ GFile *cache_file;
+
+ tmp_name = g_strdup_printf ("gnome-documents-%d.pdf", g_str_hash (job->uri));
+ tmp_path = g_build_filename (g_get_user_cache_dir (), "gnome-documents", NULL);
+ job->pdf_path = pdf_path =
+ g_build_filename (tmp_path, tmp_name, NULL);
+
+ g_mkdir_with_parents (tmp_path, 0700);
+
+ cache_file = g_file_new_for_path (pdf_path);
+ g_file_query_info_async (cache_file,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ job->cancellable,
+ openoffice_cache_query_info_ready_cb,
+ job);
+
+ g_free (tmp_name);
+ g_free (tmp_path);
+ g_object_unref (cache_file);
+}
+
+static void
query_info_ready_cb (GObject *obj,
GAsyncResult *res,
gpointer user_data)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]