summaryrefslogtreecommitdiff
path: root/libnautilus-private/nautilus-file-changes-queue.c
diff options
context:
space:
mode:
authorPavel Cisler <pavel@eazel.com>2000-04-18 03:13:56 +0000
committerPavel Cisler <pce@src.gnome.org>2000-04-18 03:13:56 +0000
commita49e9119f814b03eb1c10f8900ff01518c5d178f (patch)
treeb42c962b53044b04cd4607cc9e313af954765a16 /libnautilus-private/nautilus-file-changes-queue.c
parent4393e9621451887324cc7d2c101deb7f06439c8b (diff)
downloadnautilus-a49e9119f814b03eb1c10f8900ff01518c5d178f.tar.gz
This checkin requires new gnome-vfs.
2000-04-17 Pavel Cisler <pavel@eazel.com> This checkin requires new gnome-vfs. Plumbing for making copied/moved/deleted files show up update in their respective new locations. * libnautilus-extensions/nautilus-file-changes-queue.h * libnautilus-extensions/nautilus-file-changes-queue.c * libnautilus-extensions/Makefile.am Shared queue used by the copy engine to send update notification requests to NautilusDirectory during file copy/move/delete operations. * libnautilus-extensions/nautilus-directory-private.h: * libnautilus-extensions/nautilus-directory.c: (nautilus_directory_notify_files_added), (nautilus_directory_notify_files_removed), (nautilus_directory_notify_files_moved): Stub calls that will be hooked up to the NautilusDirectory notification calls to dispatch the notification updates. * src/file-manager/dfos-xfer.c: (sync_xfer_callback): New callback that gets called in the async copy engine context and produces change entries stuffing them into the file changes queue. * src/file-manager/dfos-xfer.c: (handle_xfer_ok): Added calls to the new nautilus_file_changes_consume_changes from the progress update callback. This callback is called in the user interface context and consumes the change entries from the file changes queue, sending them in chunks to be dispatched by to the individual Nautilus directory objects. * src/file-manager/dfos-xfer.c: (handle_xfer_ok): Updated to use new progress enum values. * src/file-manager/dfos-xfer.c: (update_xfer_callback): Renamed from sync_xfer_callback. * src/file-manager/dfos-xfer.c: (gnome_vfs_async_xfer): Pass in new sync_xfer_callback parameters.
Diffstat (limited to 'libnautilus-private/nautilus-file-changes-queue.c')
-rw-r--r--libnautilus-private/nautilus-file-changes-queue.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/libnautilus-private/nautilus-file-changes-queue.c b/libnautilus-private/nautilus-file-changes-queue.c
new file mode 100644
index 000000000..b69212601
--- /dev/null
+++ b/libnautilus-private/nautilus-file-changes-queue.c
@@ -0,0 +1,262 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-directory.h: Nautilus directory model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include "nautilus-file-changes-queue-private.h"
+#include "nautilus-directory-private.h"
+
+#ifdef G_THREADS_ENABLED
+#define MUTEX_LOCK(a) if ((a) != NULL) g_mutex_lock (a)
+#define MUTEX_UNLOCK(a) if ((a) != NULL) g_mutex_unlock (a)
+#else
+#define MUTEX_LOCK(a)
+#define MUTEX_UNLOCK(a)
+#endif
+
+static NautilusFileChangesQueue *file_changes_queue;
+
+static void
+nautilus_file_change_free (NautilusFileChange *change)
+{
+ g_free (change->from_uri);
+ g_free (change->to_uri);
+}
+
+static NautilusFileChangesQueue *
+nautilus_file_changes_queue_new (void)
+{
+ NautilusFileChangesQueue *result = g_new (NautilusFileChangesQueue, 1);
+ result->details = g_new0 (NautilusFileChangesQueueDetails, 1);
+
+#ifdef G_THREADS_ENABLED
+ result->details->mutex = g_mutex_new ();
+#endif
+ return result;
+}
+
+static NautilusFileChangesQueue *
+nautilus_file_changes_queue_get (void)
+{
+ if (file_changes_queue == NULL)
+ file_changes_queue = nautilus_file_changes_queue_new();
+
+ return file_changes_queue;
+}
+
+void
+nautilus_file_changes_queue_free (NautilusFileChangesQueue *queue)
+{
+ GList *p;
+ if (queue == NULL) {
+ return;
+ }
+
+#ifdef G_THREADS_ENABLED
+ /* if lock on a defunct mutext were defined (returning a failure)
+ * we would lock here
+ */
+#endif
+
+ for (p = queue->details->head; p != NULL; p = p->next) {
+ nautilus_file_change_free (p->data);
+ }
+ g_list_free (queue->details->head);
+
+#ifdef G_THREADS_ENABLED
+ g_mutex_free (queue->details->mutex);
+#endif
+ g_free (queue->details);
+ g_free (queue);
+}
+
+static void
+nautilus_file_changes_queue_add_common (NautilusFileChangesQueue *queue,
+ NautilusFileChange *new_item)
+{
+ /* enqueue the new queue item while locking down the list */
+ MUTEX_LOCK (queue->details->mutex);
+
+ queue->details->head = g_list_prepend (queue->details->head, new_item);
+ if (queue->details->tail == NULL)
+ queue->details->tail = queue->details->head;
+
+ MUTEX_UNLOCK (queue->details->mutex);
+}
+
+void
+nautilus_file_changes_queue_file_added (const char *uri)
+{
+ NautilusFileChange *new_item;
+ NautilusFileChangesQueue *queue;
+
+ queue = nautilus_file_changes_queue_get();
+ g_assert (queue);
+
+ new_item = g_new0 (NautilusFileChange, 1);
+ new_item->kind = CHANGE_FILE_ADDED;
+ new_item->from_uri = g_strdup (uri);
+ nautilus_file_changes_queue_add_common (queue, new_item);
+}
+
+void
+nautilus_file_changes_queue_file_removed (const char *uri)
+{
+ NautilusFileChange *new_item;
+ NautilusFileChangesQueue *queue;
+
+ queue = nautilus_file_changes_queue_get();
+ g_assert (queue);
+
+ new_item = g_new0 (NautilusFileChange, 1);
+ new_item->kind = CHANGE_FILE_REMOVED;
+ new_item->from_uri = g_strdup (uri);
+ nautilus_file_changes_queue_add_common (queue, new_item);
+}
+
+void
+nautilus_file_changes_queue_file_moved (const char *from, const char *to)
+{
+ NautilusFileChange *new_item;
+ NautilusFileChangesQueue *queue;
+
+ queue = nautilus_file_changes_queue_get();
+ g_assert (queue);
+
+ new_item = g_new (NautilusFileChange, 1);
+ new_item->kind = CHANGE_FILE_REMOVED;
+ new_item->from_uri = g_strdup (from);
+ new_item->to_uri = g_strdup (to);
+ nautilus_file_changes_queue_add_common (queue, new_item);
+}
+
+static NautilusFileChange *
+nautilus_file_changes_queue_get_change (NautilusFileChangesQueue *queue)
+{
+ GList *new_tail;
+ NautilusFileChange *result;
+
+ /* dequeue the tail item while locking down the list */
+ MUTEX_LOCK (queue->details->mutex);
+
+ if (queue->details->tail == NULL) {
+ result = NULL;
+ } else {
+ new_tail = queue->details->tail->prev;
+ result = queue->details->tail->data;
+ queue->details->head = g_list_remove_link (queue->details->head,
+ queue->details->tail);
+ queue->details->tail = new_tail;
+ }
+
+ MUTEX_UNLOCK (queue->details->mutex);
+
+ return result;
+}
+
+enum {
+ CONSUME_CHANGES_MAX_CHUNK = 10
+};
+
+/* go through changes in the change queue, send ones with the same kind
+ * in a list to the different nautilus_directory_notify calls
+ */
+void
+nautilus_file_changes_consume_changes (gboolean consume_all)
+{
+ NautilusFileChange *change;
+ GList *additions;
+ GList *deletions;
+ GList *moves;
+ URIPair *pair;
+ int kind;
+ int chunk_count;
+
+ additions = NULL;
+ deletions = NULL;
+ moves = NULL;
+ kind = CHANGE_FILE_INITIAL;
+
+ if (file_changes_queue == NULL)
+ return;
+
+ for (chunk_count = 0; ; chunk_count++) {
+ change = nautilus_file_changes_queue_get_change (file_changes_queue);
+
+
+ if (change == NULL
+ /* no changes left */
+ || change->kind != kind
+ /* all the changes we have are different that the new one */
+ || (!consume_all && chunk_count >= CONSUME_CHANGES_MAX_CHUNK)) {
+ /* we have reached the chunk maximum */
+
+
+ /* send changes we collected off */
+ if (additions != NULL) {
+ nautilus_directory_notify_files_added (additions);
+ additions = NULL;
+ }
+ if (deletions != NULL) {
+ nautilus_directory_notify_files_removed (deletions);
+ deletions = NULL;
+ }
+ if (moves != NULL) {
+ nautilus_directory_notify_files_moved (moves);
+ moves = NULL;
+ }
+ }
+
+ if (change == NULL) {
+ /* we are done */
+ break;
+ }
+
+
+ kind = change->kind;
+
+ /* add the new change to the list */
+ switch (kind) {
+ case CHANGE_FILE_ADDED:
+ additions = g_list_append (additions, change->from_uri);
+ break;
+
+ case CHANGE_FILE_REMOVED:
+ deletions = g_list_append (deletions, change->from_uri);
+ break;
+
+ case CHANGE_FILE_MOVED:
+ pair = g_new (URIPair, 1);
+ pair->from_uri = change->from_uri;
+ pair->to_uri = change->to_uri;
+ moves = g_list_append (moves, pair);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ change->from_uri = NULL;
+ change->to_uri = NULL;
+ }
+}
+