[yelp] libyelp: Auto-reload Mallard documents



commit f755aaf23e92a7211c50b8881b648c6f8b97939b
Author: Shaun McCance <shaunm gnome org>
Date:   Thu Jan 19 14:49:19 2012 -0500

    libyelp: Auto-reload Mallard documents

 libyelp/yelp-document.c         |   38 +++++++++++++++++-
 libyelp/yelp-document.h         |    2 +
 libyelp/yelp-mallard-document.c |   83 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 122 insertions(+), 1 deletions(-)
---
diff --git a/libyelp/yelp-document.c b/libyelp/yelp-document.c
index d6c0ff7..83605dd 100644
--- a/libyelp/yelp-document.c
+++ b/libyelp/yelp-document.c
@@ -479,8 +479,9 @@ yelp_document_set_page_id (YelpDocument *document,
 	    request->page_id = g_strdup (page_id);
 	    hash_slist_insert (document->priv->reqs_by_page_id, page_id, request);
 	}
-	if (reqs)
+	if (reqs) {
 	    hash_remove (document->priv->reqs_by_page_id, id);
+        }
     }
 
     if (page_id != NULL) {
@@ -863,6 +864,41 @@ document_request_page (YelpDocument         *document,
     return ret;
 }
 
+void
+yelp_document_clear_contents (YelpDocument *document)
+{
+    g_mutex_lock (document->priv->mutex);
+
+    if (document->priv->contents->null) {
+        str_unref (document->priv->contents->null);
+        document->priv->contents->null = NULL;
+    }
+    g_hash_table_remove_all (document->priv->contents->hash);
+
+    g_mutex_unlock (document->priv->mutex);
+}
+
+gchar **
+yelp_document_get_requests (YelpDocument *document)
+{
+    GList *reqs, *cur;
+    gchar **ret;
+    gint i;
+
+    g_mutex_lock (document->priv->mutex);
+
+    reqs = g_hash_table_get_keys (document->priv->reqs_by_page_id->hash);
+    ret = g_new0 (gchar*, g_list_length (reqs) + 1);
+    for (cur = reqs, i = 0; cur; cur = cur->next, i++) {
+        ret[i] = g_strdup ((gchar *) cur->data);
+    }
+    g_list_free (reqs);
+
+    g_mutex_unlock (document->priv->mutex);
+
+    return ret;
+}
+
 /******************************************************************************/
 
 const gchar *
diff --git a/libyelp/yelp-document.h b/libyelp/yelp-document.h
index 16fc8aa..3214dcf 100644
--- a/libyelp/yelp-document.h
+++ b/libyelp/yelp-document.h
@@ -85,6 +85,8 @@ gboolean          yelp_document_request_page   (YelpDocument         *document,
                                                 GCancellable         *cancellable,
                                                 YelpDocumentCallback  callback,
                                                 gpointer              user_data);
+void              yelp_document_clear_contents (YelpDocument         *document);
+gchar **          yelp_document_get_requests   (YelpDocument         *document);
 
 void              yelp_document_give_contents  (YelpDocument         *document,
                                                 const gchar          *page_id,
diff --git a/libyelp/yelp-mallard-document.c b/libyelp/yelp-mallard-document.c
index 5ce5f17..fbb9c30 100644
--- a/libyelp/yelp-mallard-document.c
+++ b/libyelp/yelp-mallard-document.c
@@ -104,6 +104,11 @@ static void           mallard_page_data_info    (MallardPageData      *page_data
                                                  xmlNodePtr            cache_node);
 static void           mallard_page_data_run     (MallardPageData      *page_data);
 static void           mallard_page_data_free    (MallardPageData      *page_data);
+static void           mallard_monitor_changed   (GFileMonitor         *monitor,
+                                                 GFile                *file,
+                                                 GFile                *other_file,
+                                                 GFileMonitorEvent     event_type,
+                                                 YelpMallardDocument  *mallard);
 
 static const char *   xml_node_get_icon         (xmlNodePtr            node);
 static gboolean       xml_node_is_ns_name       (xmlNodePtr            node,
@@ -130,6 +135,8 @@ struct _YelpMallardDocumentPrivate {
     xmlNsPtr       cache_ns;
     GHashTable    *pages_hash;
 
+    GFileMonitor **monitors;
+
     xmlXPathCompExprPtr  normalize;
 };
 
@@ -176,6 +183,17 @@ yelp_mallard_document_init (YelpMallardDocument *mallard)
 static void
 yelp_mallard_document_dispose (GObject *object)
 {
+    gint i;
+    YelpMallardDocumentPrivate *priv = GET_PRIV (object);
+
+    if (priv->monitors != NULL) {
+        for (i = 0; priv->monitors[i]; i++) {
+            g_object_unref (priv->monitors[i]);
+        }
+        g_free (priv->monitors);
+        priv->monitors = NULL;
+    }
+
     G_OBJECT_CLASS (yelp_mallard_document_parent_class)->dispose (object);
 }
 
@@ -188,6 +206,7 @@ yelp_mallard_document_finalize (GObject *object)
     g_mutex_free (priv->mutex);
     g_hash_table_destroy (priv->pages_hash);
 
+    xmlFreeDoc (priv->cache);
     if (priv->normalize)
         xmlXPathFreeCompExpr (priv->normalize);
 
@@ -202,6 +221,8 @@ yelp_mallard_document_new (YelpUri *uri)
     YelpMallardDocument *mallard;
     YelpMallardDocumentPrivate *priv;
     gchar *doc_uri;
+    gchar **path;
+    gint path_i;
 
     g_return_val_if_fail (uri != NULL, NULL);
 
@@ -216,6 +237,21 @@ yelp_mallard_document_new (YelpUri *uri)
     yelp_document_set_page_id ((YelpDocument *) mallard, NULL, "index");
     yelp_document_set_page_id ((YelpDocument *) mallard, "index", "index");
 
+    path = yelp_uri_get_search_path (uri);
+    priv->monitors = g_new0 (GFileMonitor*, g_strv_length (path) + 1);
+    for (path_i = 0; path[path_i]; path_i++) {
+        GFile *file;
+        file = g_file_new_for_path (path[path_i]);
+        priv->monitors[path_i] = g_file_monitor (file,
+                                                 G_FILE_MONITOR_SEND_MOVED,
+                                                 NULL, NULL);
+        g_signal_connect (priv->monitors[path_i], "changed",
+                          G_CALLBACK (mallard_monitor_changed),
+                          mallard);
+        g_object_unref (file);
+    }
+    g_strfreev (path);
+
     return (YelpDocument *) mallard;
 }
 
@@ -1069,3 +1105,50 @@ mallard_index (YelpDocument *document)
     priv->index_running = TRUE;
 }
 
+static void
+mallard_monitor_changed (GFileMonitor         *monitor,
+                         GFile                *file,
+                         GFile                *other_file,
+                         GFileMonitorEvent     event_type,
+                         YelpMallardDocument  *mallard)
+{
+    gchar **ids;
+    gint i;
+    xmlNodePtr cur;
+    YelpMallardDocumentPrivate *priv = GET_PRIV (mallard);
+
+    /* Exiting the thinking thread would require a fair amount of retooling.
+       For now, we'll just fail to auto-reload if that's still happening.
+    */
+    if (priv->thread_running)
+        return;
+
+    g_mutex_lock (priv->mutex);
+
+    g_hash_table_remove_all (priv->pages_hash);
+    g_object_set (mallard, "indexed", FALSE, NULL);
+
+    ids = yelp_document_get_requests (YELP_DOCUMENT (mallard));
+    for (i = 0; ids[i]; i++) {
+        priv->pending = g_slist_prepend (priv->pending, ids[i]);
+    }
+    g_free (ids);
+
+    yelp_document_clear_contents (YELP_DOCUMENT (mallard));
+
+    xmlFreeDoc (priv->cache);
+    priv->cache = xmlNewDoc (BAD_CAST "1.0");
+    priv->cache_ns = xmlNewNs (NULL, BAD_CAST MALLARD_NS, BAD_CAST "mal");
+    cur = xmlNewDocNode (priv->cache, priv->cache_ns, BAD_CAST "cache", NULL);
+    xmlDocSetRootElement (priv->cache, cur);
+    priv->cache_ns->next = cur->nsDef;
+    cur->nsDef = priv->cache_ns;
+
+    priv->state = MALLARD_STATE_THINKING;
+    priv->thread_running = TRUE;
+    g_object_ref (mallard);
+    priv->thread = g_thread_create ((GThreadFunc) mallard_think,
+                                    mallard, FALSE, NULL);
+
+    g_mutex_unlock (priv->mutex);
+}



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