View | Details | Raw Unified | Return to bug 114710
Collapse All | Expand All

(-)libgnomevfs/gnome-vfs-async-job-map.c (-119 / +51 lines)
Lines 21-26 Link Here
21
   Author: Pavel Cisler <pavel@eazel.com> */
21
   Author: Pavel Cisler <pavel@eazel.com> */
22
22
23
#include <config.h>
23
#include <config.h>
24
#include <string.h>
25
#include <sys/time.h>
26
#include <glib/gprintf.h>
24
#include "gnome-vfs-async-job-map.h"
27
#include "gnome-vfs-async-job-map.h"
25
28
26
#include "gnome-vfs-job.h"
29
#include "gnome-vfs-job.h"
Lines 34-45 static int async_job_map_locked = 0; Link Here
34
static gboolean async_job_map_shutting_down;
37
static gboolean async_job_map_shutting_down;
35
static GHashTable *async_job_map;
38
static GHashTable *async_job_map;
36
39
37
/* callback map bits guarded by this lock */
40
static void
38
static GStaticMutex async_job_callback_map_lock = G_STATIC_MUTEX_INIT;
41
fmq_log (const char *str, ...)
39
static GHashTable *async_job_callback_map;
42
{
40
static guint async_job_callback_map_next_id;
43
#if 0
44
	va_list args;
45
	GThread *thread;
46
	struct timeval tv;
47
	double sec;
48
49
	va_start (args, str);
50
51
	thread = g_thread_self ();
41
52
42
void async_job_callback_map_destroy (void);
53
	gettimeofday (&tv, NULL);
54
	sec = tv.tv_sec + ((double) tv.tv_usec / 1e6);
55
56
	g_fprintf (stderr, "Thread %p time %.16g: ", thread, sec);
57
	g_vfprintf (stderr, str, args);
58
	g_fprintf (stderr, "\n");
59
60
	va_end (args);
61
#endif
62
}
43
63
44
void 
64
void 
45
_gnome_vfs_async_job_map_init (void)
65
_gnome_vfs_async_job_map_init (void)
Lines 92-97 _gnome_vfs_async_job_map_remove_job (Gno Link Here
92
	g_assert (async_job_map);
112
	g_assert (async_job_map);
93
113
94
	g_hash_table_remove (async_job_map, job->job_handle);
114
	g_hash_table_remove (async_job_map, job->job_handle);
115
	fmq_log ("_gnome_vfs_async_job_map_remove_job(): REMOVING job %p with handle %p from async_job_map",
116
		 job,
117
		 job->job_handle);
95
	
118
	
96
	_gnome_vfs_async_job_map_unlock ();
119
	_gnome_vfs_async_job_map_unlock ();
97
}
120
}
Lines 108-114 gnome_vfs_async_job_map_destroy (void) Link Here
108
	async_job_map = NULL;
131
	async_job_map = NULL;
109
}
132
}
110
133
111
gboolean 
134
void
112
_gnome_vfs_async_job_completed (GnomeVFSAsyncHandle *handle)
135
_gnome_vfs_async_job_completed (GnomeVFSAsyncHandle *handle)
113
{
136
{
114
	GnomeVFSJob *job;
137
	GnomeVFSJob *job;
Lines 123-128 _gnome_vfs_async_job_completed (GnomeVFS Link Here
123
	job = _gnome_vfs_async_job_map_get_job (handle);
146
	job = _gnome_vfs_async_job_map_get_job (handle);
124
	if (job != NULL) {
147
	if (job != NULL) {
125
		g_hash_table_remove (async_job_map, handle);
148
		g_hash_table_remove (async_job_map, handle);
149
		fmq_log ("_gnome_vfs_async_job_completed(): REMOVING job %p with handle %p from async_job_map",
150
			 job,
151
			 handle);
126
	}
152
	}
127
	
153
	
128
	if (async_job_map_shutting_down && g_hash_table_size (async_job_map) == 0) {
154
	if (async_job_map_shutting_down && g_hash_table_size (async_job_map) == 0) {
Lines 131-138 _gnome_vfs_async_job_completed (GnomeVFS Link Here
131
	}
157
	}
132
	
158
	
133
	_gnome_vfs_async_job_map_unlock ();
159
	_gnome_vfs_async_job_map_unlock ();
134
	
135
	return job != NULL;
136
}
160
}
137
161
138
void
162
void
Lines 155-162 _gnome_vfs_async_job_map_shutdown (void) Link Here
155
179
156
	/* The last expiring job will delete the hash table. */
180
	/* The last expiring job will delete the hash table. */
157
	_gnome_vfs_async_job_map_unlock ();
181
	_gnome_vfs_async_job_map_unlock ();
158
	
159
	async_job_callback_map_destroy ();
160
}
182
}
161
183
162
void 
184
void 
Lines 179-300 _gnome_vfs_async_job_map_assert_locked ( Link Here
179
	g_assert (async_job_map_locked);
201
	g_assert (async_job_map_locked);
180
}
202
}
181
203
182
void 
204
void
183
_gnome_vfs_async_job_callback_valid (guint     callback_id,
205
_gnome_vfs_async_job_cancel_job (GnomeVFSJob *job)
184
				    gboolean *valid,
185
				    gboolean *cancelled)
186
{
187
	GnomeVFSNotifyResult *notify_result;
188
	
189
	g_static_mutex_lock (&async_job_callback_map_lock);
190
	
191
	if (async_job_callback_map == NULL) {
192
		g_assert (async_job_map_shutting_down);
193
		*valid = FALSE;
194
		*cancelled = FALSE;
195
	}
196
197
	notify_result = (GnomeVFSNotifyResult *) g_hash_table_lookup
198
		(async_job_callback_map, GUINT_TO_POINTER (callback_id));
199
	
200
	*valid = notify_result != NULL;
201
	*cancelled = notify_result != NULL && notify_result->cancelled;
202
203
	g_static_mutex_unlock (&async_job_callback_map_lock);
204
}
205
206
gboolean 
207
_gnome_vfs_async_job_add_callback (GnomeVFSJob *job, GnomeVFSNotifyResult *notify_result)
208
{
206
{
209
	gboolean cancelled;
207
	GnomeVFSOp *op;
210
208
	GnomeVFSAsyncHandle *job_handle;
211
	g_static_mutex_lock (&async_job_callback_map_lock);
212
213
	g_assert (!async_job_map_shutting_down);
214
	
215
	/* Assign a unique id to each job callback. Use unique IDs instead of the
216
	 * notify_results pointers to avoid aliasing problems.
217
	 */
218
	notify_result->callback_id = ++async_job_callback_map_next_id;
219
220
	JOB_DEBUG (("adding callback %d ", notify_result->callback_id));
221
222
	if (async_job_callback_map == NULL) {
223
		/* First job, allocate a new hash table. */
224
		async_job_callback_map = g_hash_table_new (NULL, NULL);
225
	}
226
209
227
	/* we are using async_job_callback_map_lock to ensure atomicity of
210
	g_assert (job != NULL);
228
	 * checking/clearing job->cancelled and adding/cancelling callbacks
229
	 */
230
	cancelled = job->cancelled;
231
	
232
	if (!cancelled) {
233
		g_hash_table_insert (async_job_callback_map, GUINT_TO_POINTER (notify_result->callback_id),
234
			notify_result);
235
	}
236
	g_static_mutex_unlock (&async_job_callback_map_lock);
237
	
238
	return !cancelled;
239
}
240
211
241
void 
212
	g_mutex_lock (job->job_lock);
242
_gnome_vfs_async_job_remove_callback (guint callback_id)
243
{
244
	g_assert (async_job_callback_map != NULL);
245
213
246
	JOB_DEBUG (("removing callback %d ", callback_id));
214
	job_handle = job->job_handle;
247
	g_static_mutex_lock (&async_job_callback_map_lock);
248
215
249
	g_hash_table_remove (async_job_callback_map, GUINT_TO_POINTER (callback_id));
216
	/* Move the current op to the list of pending canceled ops */
250
217
251
	g_static_mutex_unlock (&async_job_callback_map_lock);
218
	g_assert (job->op != NULL);
252
}
219
	op = job->op;
220
	op->canceled = TRUE;
253
221
254
static void
222
	job->op = NULL;
255
callback_map_cancel_one (gpointer key, gpointer value, gpointer user_data)
223
	job->canceled_ops = g_slist_append (job->canceled_ops, op);
256
{
257
	GnomeVFSNotifyResult *notify_result;
258
	
259
	notify_result = (GnomeVFSNotifyResult *) value;
260
	
261
	if (notify_result->job_handle == (GnomeVFSAsyncHandle *)user_data) {
262
		JOB_DEBUG (("cancelling callback %u - job %u cancelled",
263
			    GPOINTER_TO_UINT (key),
264
			    GPOINTER_TO_UINT (user_data)));
265
		notify_result->cancelled = TRUE;
266
	}
267
}
268
224
269
void
225
	fmq_log ("MAIN: _gnome_vfs_async_job_cancel_job_and_callbacks(): job_handle %p, job %p, op %p, and set its job->op->canceled to TRUE",
270
_gnome_vfs_async_job_cancel_job_and_callbacks (GnomeVFSAsyncHandle *job_handle, GnomeVFSJob *job)
226
		 job->job_handle,
271
{
227
		 job,
272
	g_static_mutex_lock (&async_job_callback_map_lock);
228
		 op,
229
		 "and set its job->op->canceled to TRUE");
273
	
230
	
274
	if (job != NULL) {
231
	g_mutex_unlock (job->job_lock);
275
		job->cancelled = TRUE;
276
	}
277
	
278
	if (async_job_callback_map == NULL) {
279
		JOB_DEBUG (("job %u, no callbacks scheduled yet",
280
			    GPOINTER_TO_UINT (job_handle)));
281
	} else {
282
		g_hash_table_foreach (async_job_callback_map,
283
				      callback_map_cancel_one, job_handle);
284
	}
285
286
	g_static_mutex_unlock (&async_job_callback_map_lock);
287
}
288
289
void
290
async_job_callback_map_destroy (void)
291
{
292
	g_static_mutex_lock (&async_job_callback_map_lock);
293
294
	if (async_job_callback_map) {
295
		g_hash_table_destroy (async_job_callback_map);
296
		async_job_callback_map = NULL;
297
	}
298
299
	g_static_mutex_unlock (&async_job_callback_map_lock);
300
}
232
}
(-)libgnomevfs/gnome-vfs-async-job-map.h (-10 / +3 lines)
Lines 32-54 Link Here
32
/* async job map calls */
32
/* async job map calls */
33
void		 _gnome_vfs_async_job_map_init		  	(void);
33
void		 _gnome_vfs_async_job_map_init		  	(void);
34
void	     	 _gnome_vfs_async_job_map_shutdown	  	(void);
34
void	     	 _gnome_vfs_async_job_map_shutdown	  	(void);
35
gboolean     	 _gnome_vfs_async_job_completed 	  	  	(GnomeVFSAsyncHandle		*handle);
35
void     	 _gnome_vfs_async_job_completed			(GnomeVFSAsyncHandle		*handle);
36
void 		 _gnome_vfs_async_job_map_add_job  	  	(GnomeVFSJob			*job);
36
void 		 _gnome_vfs_async_job_map_add_job  	  	(GnomeVFSJob			*job);
37
void 		 _gnome_vfs_async_job_map_remove_job  	  	(GnomeVFSJob			*job);
37
void 		 _gnome_vfs_async_job_map_remove_job  	  	(GnomeVFSJob			*job);
38
GnomeVFSJob	*_gnome_vfs_async_job_map_get_job	  	(const GnomeVFSAsyncHandle	*handle);
38
GnomeVFSJob	*_gnome_vfs_async_job_map_get_job	  	(const GnomeVFSAsyncHandle	*handle);
39
39
40
void		 _gnome_vfs_async_job_map_assert_locked	  	(void);
40
void		 _gnome_vfs_async_job_map_assert_locked	  	(void);
41
void		 _gnome_vfs_async_job_map_lock	  	  	(void);
41
void		 _gnome_vfs_async_job_map_lock	  	  	(void);
42
void		 _gnome_vfs_async_job_map_unlock	  	  	(void);
42
void		 _gnome_vfs_async_job_map_unlock		(void);
43
43
44
/* async job callback map calls */
44
/* async job callback map calls */
45
void		 _gnome_vfs_async_job_callback_valid		(guint				 callback_id,
45
void		 _gnome_vfs_async_job_cancel_job		(GnomeVFSJob 			*job);
46
								 gboolean			*valid,
47
								 gboolean			*cancelled);
48
gboolean	 _gnome_vfs_async_job_add_callback		(GnomeVFSJob			*job,
49
							  	 GnomeVFSNotifyResult		*notify_result);
50
void		 _gnome_vfs_async_job_remove_callback		(guint			 	 callback_id);
51
void		 _gnome_vfs_async_job_cancel_job_and_callbacks	(GnomeVFSAsyncHandle		*job_handle,
52
								 GnomeVFSJob 			*job);
53
46
54
#endif
47
#endif
(-)libgnomevfs/gnome-vfs-async-ops.c (-88 / +51 lines)
Lines 22-27 Link Here
22
   Author: Ettore Perazzoli <ettore@comm2000.it> */
22
   Author: Ettore Perazzoli <ettore@comm2000.it> */
23
23
24
#include <config.h>
24
#include <config.h>
25
#include <string.h>
26
#include <sys/time.h>
27
#include <glib/gprintf.h>
25
28
26
#include "gnome-vfs-async-ops.h"
29
#include "gnome-vfs-async-ops.h"
27
#include "gnome-vfs-async-job-map.h"
30
#include "gnome-vfs-async-job-map.h"
Lines 32-37 Link Here
32
#include <glib/gstrfuncs.h>
35
#include <glib/gstrfuncs.h>
33
#include <unistd.h>
36
#include <unistd.h>
34
37
38
static void
39
fmq_log (const char *str, ...)
40
{
41
#if 0
42
	va_list args;
43
	GThread *thread;
44
	struct timeval tv;
45
	double sec;
46
47
	va_start (args, str);
48
49
	thread = g_thread_self ();
50
51
	gettimeofday (&tv, NULL);
52
	sec = tv.tv_sec + ((double) tv.tv_usec / 1e6);
53
54
	g_fprintf (stderr, "Thread %p time %.16g: ", thread, sec);
55
	g_vfprintf (stderr, str, args);
56
	g_fprintf (stderr, "\n");
57
58
	va_end (args);
59
#endif
60
}
61
35
/**
62
/**
36
 * gnome_vfs_async_cancel:
63
 * gnome_vfs_async_cancel:
37
 * @handle: handle of the async operation to be cancelled
64
 * @handle: handle of the async operation to be cancelled
Lines 69-84 gnome_vfs_async_cancel (GnomeVFSAsyncHan Link Here
69
	_gnome_vfs_async_job_map_lock ();
96
	_gnome_vfs_async_job_map_lock ();
70
97
71
	job = _gnome_vfs_async_job_map_get_job (handle);
98
	job = _gnome_vfs_async_job_map_get_job (handle);
72
	if (job == NULL) {
99
73
		JOB_DEBUG (("job %u - job no longer exists", GPOINTER_TO_UINT (handle)));
100
	fmq_log ("MAIN: gnome_vfs_async_cancel() for vfs_handle %p, corresponding job %p",
74
		/* have to cancel the callbacks because they still can be pending */
101
		 handle,
75
		_gnome_vfs_async_job_cancel_job_and_callbacks (handle, NULL);
102
		 job);
76
	} else {
103
104
	if (job == NULL)
105
		g_warning ("The job for handle %p no longer exists", handle);
106
	else {
107
		g_mutex_lock (job->job_lock);
108
		if (job->op == NULL)
109
			g_error ("The job for handle %p is not running; cannot cancel it", handle);
110
		g_mutex_unlock (job->job_lock);
111
77
		/* Cancel the job in progress. OK to do outside of job->job_lock,
112
		/* Cancel the job in progress. OK to do outside of job->job_lock,
78
		 * job lifetime is protected by _gnome_vfs_async_job_map_lock.
113
		 * job lifetime is protected by _gnome_vfs_async_job_map_lock.
79
		 */
114
		 */
80
		_gnome_vfs_job_module_cancel (job);
115
		_gnome_vfs_job_module_cancel (job);
81
		_gnome_vfs_async_job_cancel_job_and_callbacks (handle, job);
116
		_gnome_vfs_async_job_cancel_job (job);
82
	}
117
	}
83
118
84
	_gnome_vfs_async_job_map_unlock ();
119
	_gnome_vfs_async_job_map_unlock ();
Lines 529-561 gnome_vfs_async_close (GnomeVFSAsyncHand Link Here
529
	g_return_if_fail (handle != NULL);
564
	g_return_if_fail (handle != NULL);
530
	g_return_if_fail (callback != NULL);
565
	g_return_if_fail (callback != NULL);
531
566
532
	for (;;) {
567
	_gnome_vfs_async_job_map_lock ();
533
		_gnome_vfs_async_job_map_lock ();
568
	job = _gnome_vfs_async_job_map_get_job (handle);
534
		job = _gnome_vfs_async_job_map_get_job (handle);
569
	if (job == NULL) {
535
		if (job == NULL) {
570
		g_warning ("trying to close a non-existing handle");
536
			g_warning ("trying to read a non-existing handle");
537
			_gnome_vfs_async_job_map_unlock ();
538
			return;
539
		}
540
541
		if (job->op->type != GNOME_VFS_OP_READ &&
542
		    job->op->type != GNOME_VFS_OP_WRITE) {
543
			_gnome_vfs_job_set (job, GNOME_VFS_OP_CLOSE,
544
					   (GFunc) callback, callback_data);
545
			_gnome_vfs_job_go (job);
546
			_gnome_vfs_async_job_map_unlock ();
547
			return;
548
		}
549
		/* Still reading, wait a bit, cancel should be pending.
550
		 * This mostly handles a race condition that can happen
551
		 * on a dual CPU machine where a cancel stops a read before
552
		 * the read thread picks up and a close then gets scheduled
553
		 * on a new thread. Without this the job op type would be
554
		 * close for both threads and two closes would get executed
555
		 */
556
		_gnome_vfs_async_job_map_unlock ();
571
		_gnome_vfs_async_job_map_unlock ();
557
		g_usleep (100);
572
		return;
558
	}
573
	}
574
575
	_gnome_vfs_job_set (job, GNOME_VFS_OP_CLOSE,
576
			    (GFunc) callback, callback_data);
577
	_gnome_vfs_job_go (job);
578
	_gnome_vfs_async_job_map_unlock ();
559
}
579
}
560
580
561
/**
581
/**
Lines 1199-1258 gnome_vfs_async_file_control (GnomeVFSAs Link Here
1199
	_gnome_vfs_job_go (job);
1219
	_gnome_vfs_job_go (job);
1200
	_gnome_vfs_async_job_map_unlock ();
1220
	_gnome_vfs_async_job_map_unlock ();
1201
}
1221
}
1202
1203
#ifdef OLD_CONTEXT_DEPRECATED
1204
1205
guint
1206
gnome_vfs_async_add_status_callback (GnomeVFSAsyncHandle *handle,
1207
				     GnomeVFSStatusCallback callback,
1208
				     gpointer user_data)
1209
{
1210
	GnomeVFSJob *job;
1211
	guint result;
1212
	
1213
	g_return_val_if_fail (handle != NULL, 0);
1214
	g_return_val_if_fail (callback != NULL, 0);
1215
1216
	_gnome_vfs_async_job_map_lock ();
1217
	job = _gnome_vfs_async_job_map_get_job (handle);
1218
1219
	if (job->op != NULL || job->op->context != NULL) {
1220
		g_warning ("job or context not found");
1221
		_gnome_vfs_async_job_map_unlock ();
1222
		return 0;
1223
	}
1224
1225
	result = gnome_vfs_message_callbacks_add
1226
		(gnome_vfs_context_get_message_callbacks (job->op->context),
1227
		 callback, user_data);
1228
	_gnome_vfs_async_job_map_unlock ();
1229
	
1230
	return result;
1231
}
1232
1233
void
1234
gnome_vfs_async_remove_status_callback (GnomeVFSAsyncHandle *handle,
1235
					guint callback_id)
1236
{
1237
	GnomeVFSJob *job;
1238
1239
	g_return_if_fail (handle != NULL);
1240
	g_return_if_fail (callback_id > 0);
1241
1242
	_gnome_vfs_async_job_map_lock ();
1243
	job = _gnome_vfs_async_job_map_get_job (handle);
1244
1245
	if (job->op != NULL || job->op->context != NULL) {
1246
		g_warning ("job or context not found");
1247
		_gnome_vfs_async_job_map_unlock ();
1248
		return;
1249
	}
1250
1251
	gnome_vfs_message_callbacks_remove
1252
		(gnome_vfs_context_get_message_callbacks (job->op->context),
1253
		 callback_id);
1254
1255
	_gnome_vfs_async_job_map_unlock ();
1256
}
1257
1258
#endif /* OLD_CONTEXT_DEPRECATED */
(-)libgnomevfs/gnome-vfs-job-queue.c (-27 / +64 lines)
Lines 22-27 Link Here
22
   Author: László Péter <laca@ireland.sun.com> */
22
   Author: László Péter <laca@ireland.sun.com> */
23
23
24
#include <config.h>
24
#include <config.h>
25
#include <sys/time.h>
26
#include <glib/gprintf.h>
25
#include "gnome-vfs-job-queue.h"
27
#include "gnome-vfs-job-queue.h"
26
#include "gnome-vfs-job-slave.h"
28
#include "gnome-vfs-job-slave.h"
27
#include <libgnomevfs/gnome-vfs-job-limit.h>
29
#include <libgnomevfs/gnome-vfs-job-limit.h>
Lines 77-84 typedef struct JobQueueKey { Link Here
77
	int priority;
79
	int priority;
78
} JobQueueKey;
80
} JobQueueKey;
79
81
82
static void
83
fmq_log (const char *str, ...)
84
{
85
#if 0
86
	va_list args;
87
	GThread *thread;
88
	struct timeval tv;
89
	double sec;
90
91
	va_start (args, str);
92
93
	thread = g_thread_self ();
94
95
	gettimeofday (&tv, NULL);
96
	sec = tv.tv_sec + ((double) tv.tv_usec / 1e6);
97
98
	g_fprintf (stderr, "Thread %p time %.16g: ", thread, sec);
99
	g_vfprintf (stderr, str, args);
100
	g_fprintf (stderr, "\n");
101
102
	va_end (args);
103
#endif
104
}
105
80
static int
106
static int
81
key_compare (gconstpointer cast_to_key1, gconstpointer cast_to_key2, gpointer user_data)
107
key_compare (gconstpointer cast_to_key1, gconstpointer cast_to_key2)
82
{
108
{
83
	JobQueueKey *key1 = (JobQueueKey *)cast_to_key1;
109
	JobQueueKey *key1 = (JobQueueKey *)cast_to_key1;
84
	JobQueueKey *key2 = (JobQueueKey *)cast_to_key2;
110
	JobQueueKey *key2 = (JobQueueKey *)cast_to_key2;
Lines 100-115 key_compare (gconstpointer cast_to_key1, Link Here
100
	return key1->job_id - key2->job_id;
126
	return key1->job_id - key2->job_id;
101
}
127
}
102
128
103
static void
104
value_destroy (gpointer cast_to_job)
105
{
106
	_gnome_vfs_job_destroy ((GnomeVFSJob *)cast_to_job);
107
}
108
109
static JobQueueType *
129
static JobQueueType *
110
job_queue_new (void)
130
job_queue_new (void)
111
{
131
{
112
	return g_tree_new_full (key_compare, NULL, g_free, value_destroy);
132
	return g_tree_new (key_compare);
113
}
133
}
114
134
115
static void
135
static void
Lines 120-132 job_queue_destroy (void) Link Here
120
}
140
}
121
141
122
static void
142
static void
123
job_queue_add (GnomeVFSJob *job)
143
job_queue_add (GnomeVFSOp *op, int priority)
124
{
144
{
125
	JobQueueKey *key = g_new (JobQueueKey, 1);
145
	JobQueueKey *key = g_new (JobQueueKey, 1);
126
	key->job_id = ++job_id;
146
	key->job_id = ++job_id;
127
	key->priority = job->priority;
147
	key->priority = priority;
128
148
129
	g_tree_insert (job_queue, key, job);
149
	g_tree_insert (job_queue, key, op);
130
#ifdef QUEUE_DEBUG
150
#ifdef QUEUE_DEBUG
131
	job_queue_length++;
151
	job_queue_length++;
132
#endif
152
#endif
Lines 135-154 job_queue_add (GnomeVFSJob *job) Link Here
135
static int
155
static int
136
find_first_value (gpointer key, gpointer value, gpointer data)
156
find_first_value (gpointer key, gpointer value, gpointer data)
137
{
157
{
138
	*((GnomeVFSJob **)data) = value;
158
	*((GnomeVFSOp **)data) = value;
139
	return TRUE;
159
	return TRUE;
140
}
160
}
141
161
142
static GnomeVFSJob *
162
static GnomeVFSOp *
143
job_queue_get_first (void)
163
job_queue_get_first (void)
144
{
164
{
145
	GnomeVFSJob *job = NULL;
165
	GnomeVFSOp *op = NULL;
146
166
147
	if (job_queue) {
167
	if (job_queue) {
148
		g_tree_foreach (job_queue, find_first_value, &job);
168
		g_tree_foreach (job_queue, find_first_value, &op);
149
	}
169
	}
150
170
151
	return job;
171
	return op;
152
}
172
}
153
173
154
static int
174
static int
Lines 262-268 job_can_start (int priority) Link Here
262
void
282
void
263
_gnome_vfs_job_queue_run (void)
283
_gnome_vfs_job_queue_run (void)
264
{
284
{
265
	GnomeVFSJob *job_to_run;
285
	GnomeVFSOp *op_to_run;
266
286
267
	g_static_mutex_lock (&job_queue_lock);
287
	g_static_mutex_lock (&job_queue_lock);
268
288
Lines 271-280 _gnome_vfs_job_queue_run (void) Link Here
271
		 running_job_count,
291
		 running_job_count,
272
		 job_queue_length));
292
		 job_queue_length));
273
293
274
	job_to_run = job_queue_get_first ();
294
	op_to_run = job_queue_get_first ();
275
	if (job_to_run != NULL) {
295
	if (op_to_run != NULL) {
276
		/* The queue is not empty */
296
		int priority;
277
		if (job_can_start (job_to_run->priority)) {
297
298
		priority = op_to_run->job->priority;
299
300
		if (job_can_start (priority)) {
278
			running_job_count++;
301
			running_job_count++;
279
			job_queue_delete_first ();
302
			job_queue_delete_first ();
280
			Q_DEBUG (("taking a %2d priority job from the queue;"
303
			Q_DEBUG (("taking a %2d priority job from the queue;"
Lines 283-289 _gnome_vfs_job_queue_run (void) Link Here
283
				 running_job_count,
306
				 running_job_count,
284
				 job_queue_length));
307
				 job_queue_length));
285
			g_static_mutex_unlock (&job_queue_lock);
308
			g_static_mutex_unlock (&job_queue_lock);
286
			_gnome_vfs_job_create_slave (job_to_run);
309
			_gnome_vfs_job_create_slave (op_to_run);
287
		} else {
310
		} else {
288
			g_static_mutex_unlock (&job_queue_lock);
311
			g_static_mutex_unlock (&job_queue_lock);
289
			Q_DEBUG (("waiting job is too low priority (%2d) to start;"
312
			Q_DEBUG (("waiting job is too low priority (%2d) to start;"
Lines 301-323 _gnome_vfs_job_queue_run (void) Link Here
301
gboolean
324
gboolean
302
_gnome_vfs_job_schedule (GnomeVFSJob *job)
325
_gnome_vfs_job_schedule (GnomeVFSJob *job)
303
{
326
{
327
	GnomeVFSOp *op;
328
	int priority;
329
304
	g_static_mutex_lock (&job_queue_lock);
330
	g_static_mutex_lock (&job_queue_lock);
305
      	if (!job_can_start (job->priority)) {
331
306
	  	job_queue_add (job);
332
	g_mutex_lock (job->job_lock);
333
	g_assert (job->op != NULL);
334
	op = job->op;
335
	priority = job->priority;
336
	g_mutex_unlock (job->job_lock);
337
338
      	if (!job_can_start (priority)) {
339
		fmq_log ("_gnome_vfs_job_schedule(): job %p cannot start yet; calling job_queue_add()",
340
			 job);
341
	  	job_queue_add (op, priority);
307
		Q_DEBUG (("adding a %2d priority job to the queue;"
342
		Q_DEBUG (("adding a %2d priority job to the queue;"
308
			 "\t       %d jobs running, %d waiting\n",
343
			 "\t       %d jobs running, %d waiting\n",
309
			 job->priority,
344
			 priority,
310
			 running_job_count,
345
			 running_job_count,
311
			 job_queue_length));
346
			 job_queue_length));
312
		g_static_mutex_unlock (&job_queue_lock);
347
		g_static_mutex_unlock (&job_queue_lock);
313
	} else {
348
	} else {
349
		fmq_log ("_gnome_vfs_job_schedule(): job %p can start right away; spawning a thread",
350
			 job);
314
		running_job_count++;
351
		running_job_count++;
315
		Q_DEBUG (("starting a %2d priority job;\t\t       %d jobs running, %d waiting\n",
352
		Q_DEBUG (("starting a %2d priority job;\t\t       %d jobs running, %d waiting\n",
316
			job->priority,
353
			priority,
317
			running_job_count,
354
			running_job_count,
318
			job_queue_length));
355
			job_queue_length));
319
		g_static_mutex_unlock (&job_queue_lock);
356
		g_static_mutex_unlock (&job_queue_lock);
320
		_gnome_vfs_job_create_slave (job);
357
		_gnome_vfs_job_create_slave (op);
321
	}
358
	}
322
	return TRUE;
359
	return TRUE;
323
}
360
}
(-)libgnomevfs/gnome-vfs-job-slave.c (-39 / +53 lines)
Lines 22-27 Link Here
22
   Author: Ettore Perazzoli <ettore@comm2000.it> */
22
   Author: Ettore Perazzoli <ettore@comm2000.it> */
23
23
24
#include <config.h>
24
#include <config.h>
25
#include <string.h>
26
#include <sys/time.h>
27
#include <glib/gprintf.h>
25
#include "gnome-vfs-job-slave.h"
28
#include "gnome-vfs-job-slave.h"
26
29
27
#include "gnome-vfs-async-job-map.h"
30
#include "gnome-vfs-async-job-map.h"
Lines 34-87 static volatile gboolean gnome_vfs_quitt Link Here
34
static volatile gboolean gnome_vfs_done_quitting = FALSE;
37
static volatile gboolean gnome_vfs_done_quitting = FALSE;
35
38
36
39
40
static void
41
fmq_log (const char *str, ...)
42
{
43
#if 0
44
	va_list args;
45
	GThread *thread;
46
	struct timeval tv;
47
	double sec;
48
49
	va_start (args, str);
50
51
	thread = g_thread_self ();
52
53
	gettimeofday (&tv, NULL);
54
	sec = tv.tv_sec + ((double) tv.tv_usec / 1e6);
55
56
	g_fprintf (stderr, "Thread %p time %.16g: ", thread, sec);
57
	g_vfprintf (stderr, str, args);
58
	g_fprintf (stderr, "\n");
59
60
	va_end (args);
61
#endif
62
}
63
37
static void *
64
static void *
38
thread_routine (void *data)
65
thread_routine (void *data)
39
{
66
{
40
	guint id;
67
	GnomeVFSOp *op;
41
	GnomeVFSJob *job;
68
42
	GnomeVFSAsyncHandle *job_handle;
69
	op = (GnomeVFSOp *) data;
43
	gboolean complete;
70
44
71
	fmq_log ("WORKER: thread_routine() just entered; got op %p, op type %d, job %p, job_handle %p",
45
	job_handle = (GnomeVFSAsyncHandle *) data;
72
		 op,
46
73
		 (int) op->type,
47
	id = GPOINTER_TO_UINT (job_handle);
74
		 op->job,
48
	/* job map must always be locked before the job_lock
75
		 op->job->job_handle);
49
	 * if both locks are needed */
76
50
	_gnome_vfs_async_job_map_lock ();
51
	
52
	job = _gnome_vfs_async_job_map_get_job (job_handle);
53
	
54
	if (job == NULL) {
55
		JOB_DEBUG (("job already dead, bail %u", id));
56
		_gnome_vfs_async_job_map_unlock ();
57
		return NULL;
58
	}
59
	
60
	JOB_DEBUG (("locking job_lock %u", id));
77
	JOB_DEBUG (("locking job_lock %u", id));
61
	g_mutex_lock (job->job_lock);
78
	g_mutex_lock (op->job->job_lock);
62
	_gnome_vfs_async_job_map_unlock ();
63
79
64
	_gnome_vfs_job_execute (job);
80
	fmq_log ("WORKER: thread_routine(): about to call _gnome_vfs_job_execute() for op %p",
65
	complete = _gnome_vfs_job_complete (job);
81
		 op);
66
	
67
	JOB_DEBUG (("Unlocking access lock %u", id));
68
	g_mutex_unlock (job->job_lock);
69
82
70
	if (complete) {
83
	_gnome_vfs_job_execute (op);
71
		_gnome_vfs_async_job_map_lock ();
84
72
		JOB_DEBUG (("job %u done, removing from map and destroying", id));
85
	fmq_log ("WORKER: thread_routine(): finished with op %p, op type %d, job %p, job_handle %p",
73
		_gnome_vfs_async_job_completed (job_handle);
86
		 op,
74
		_gnome_vfs_job_destroy (job);
87
		 (int) op->type,
75
		_gnome_vfs_async_job_map_unlock ();
88
		 op->job,
76
	}
89
		 op->job->job_handle);
90
91
	g_mutex_unlock (op->job->job_lock);
77
92
78
	return NULL;
93
	return NULL;
79
}
94
}
80
95
81
gboolean
96
gboolean
82
_gnome_vfs_job_create_slave (GnomeVFSJob *job)
97
_gnome_vfs_job_create_slave (GnomeVFSOp *op)
83
{
98
{
84
	g_return_val_if_fail (job != NULL, FALSE);
99
	g_assert (op != NULL);
85
100
86
	if (gnome_vfs_quitting) {
101
	if (gnome_vfs_quitting) {
87
		g_warning ("Someone still starting up GnomeVFS async calls after quit.");
102
		g_warning ("Someone still starting up GnomeVFS async calls after quit.");
Lines 96-107 _gnome_vfs_job_create_slave (GnomeVFSJob Link Here
96
		return FALSE;
111
		return FALSE;
97
	}
112
	}
98
	
113
	
99
	if (_gnome_vfs_thread_create (thread_routine, job->job_handle) != 0) {
114
	if (_gnome_vfs_thread_create (thread_routine, op) != 0) {
100
		g_warning ("Impossible to allocate a new GnomeVFSJob thread.");
115
		g_warning ("Impossible to allocate a new GnomeVFSJob thread.");
101
		
116
		
102
		/* thread did not start up, remove the job from the hash table */
117
		/* thread did not start up, remove the job from the hash table */
103
		_gnome_vfs_async_job_completed (job->job_handle);
118
		_gnome_vfs_async_job_completed (op->job->job_handle);
104
		_gnome_vfs_job_destroy (job);
105
		return FALSE;
119
		return FALSE;
106
	}
120
	}
107
121
(-)libgnomevfs/gnome-vfs-job-slave.h (-1 / +1 lines)
Lines 26-32 Link Here
26
26
27
#include "gnome-vfs-job.h"
27
#include "gnome-vfs-job.h"
28
28
29
gboolean _gnome_vfs_job_create_slave        (GnomeVFSJob *job);
29
gboolean _gnome_vfs_job_create_slave        (GnomeVFSOp *op);
30
30
31
/* Call this before taking down the idle task in the master thread to
31
/* Call this before taking down the idle task in the master thread to
32
 * give pending slave threads a chance to finish cleanly.
32
 * give pending slave threads a chance to finish cleanly.
(-)libgnomevfs/gnome-vfs-job.h (-50 / +37 lines)
Lines 82-92 Link Here
82
82
83
#endif
83
#endif
84
84
85
/* GNOME_VFS_OP_MODULE_CALLBACK: is not a real OpType; 
86
 * its intended to mark GnomeVFSAsyncModuleCallback's in the 
87
 * job_callback queue
88
 */
89
90
enum GnomeVFSOpType {
85
enum GnomeVFSOpType {
91
	GNOME_VFS_OP_OPEN,
86
	GNOME_VFS_OP_OPEN,
92
	GNOME_VFS_OP_OPEN_AS_CHANNEL,
87
	GNOME_VFS_OP_OPEN_AS_CHANNEL,
Lines 97-109 Link Here
97
	GNOME_VFS_OP_READ,
92
	GNOME_VFS_OP_READ,
98
	GNOME_VFS_OP_WRITE,
93
	GNOME_VFS_OP_WRITE,
99
	GNOME_VFS_OP_SEEK,
94
	GNOME_VFS_OP_SEEK,
100
	GNOME_VFS_OP_READ_WRITE_DONE,
101
	GNOME_VFS_OP_LOAD_DIRECTORY,
95
	GNOME_VFS_OP_LOAD_DIRECTORY,
102
	GNOME_VFS_OP_FIND_DIRECTORY,
96
	GNOME_VFS_OP_FIND_DIRECTORY,
103
	GNOME_VFS_OP_XFER,
97
	GNOME_VFS_OP_XFER,
104
	GNOME_VFS_OP_GET_FILE_INFO,
98
	GNOME_VFS_OP_GET_FILE_INFO,
105
	GNOME_VFS_OP_SET_FILE_INFO,
99
	GNOME_VFS_OP_SET_FILE_INFO,
106
	GNOME_VFS_OP_MODULE_CALLBACK,
107
	GNOME_VFS_OP_FILE_CONTROL
100
	GNOME_VFS_OP_FILE_CONTROL
108
};
101
};
109
102
Lines 115-122 Link Here
115
} GnomeVFSOpenOp;
108
} GnomeVFSOpenOp;
116
109
117
typedef struct {
110
typedef struct {
118
	GnomeVFSAsyncOpenCallback callback;
119
	void *callback_data;
120
	GnomeVFSResult result;
111
	GnomeVFSResult result;
121
} GnomeVFSOpenOpResult;
112
} GnomeVFSOpenOpResult;
122
113
Lines 127-134 Link Here
127
} GnomeVFSOpenAsChannelOp;
118
} GnomeVFSOpenAsChannelOp;
128
119
129
typedef struct {
120
typedef struct {
130
	GnomeVFSAsyncOpenAsChannelCallback callback;
131
	void *callback_data;
132
	GnomeVFSResult result;
121
	GnomeVFSResult result;
133
	GIOChannel *channel;
122
	GIOChannel *channel;
134
} GnomeVFSOpenAsChannelOpResult;
123
} GnomeVFSOpenAsChannelOpResult;
Lines 141-148 Link Here
141
} GnomeVFSCreateOp;
130
} GnomeVFSCreateOp;
142
131
143
typedef struct {
132
typedef struct {
144
	GnomeVFSAsyncCreateCallback callback;
145
	void *callback_data;
146
	GnomeVFSResult result;
133
	GnomeVFSResult result;
147
} GnomeVFSCreateOpResult;
134
} GnomeVFSCreateOpResult;
148
135
Lines 159-166 Link Here
159
} GnomeVFSCreateAsChannelOp;
146
} GnomeVFSCreateAsChannelOp;
160
147
161
typedef struct {
148
typedef struct {
162
	GnomeVFSAsyncCreateAsChannelCallback callback;
163
	void *callback_data;
164
	GnomeVFSResult result;
149
	GnomeVFSResult result;
165
	GIOChannel *channel;
150
	GIOChannel *channel;
166
} GnomeVFSCreateAsChannelOpResult;
151
} GnomeVFSCreateAsChannelOpResult;
Lines 170-177 Link Here
170
} GnomeVFSCloseOp;
155
} GnomeVFSCloseOp;
171
156
172
typedef struct {
157
typedef struct {
173
	GnomeVFSAsyncCloseCallback callback;
174
	void *callback_data;
175
	GnomeVFSResult result;
158
	GnomeVFSResult result;
176
} GnomeVFSCloseOpResult;
159
} GnomeVFSCloseOpResult;
177
160
Lines 181-188 Link Here
181
} GnomeVFSReadOp;
164
} GnomeVFSReadOp;
182
165
183
typedef struct {
166
typedef struct {
184
	GnomeVFSAsyncReadCallback callback;
185
	void *callback_data;
186
	GnomeVFSFileSize num_bytes;
167
	GnomeVFSFileSize num_bytes;
187
	gpointer buffer;
168
	gpointer buffer;
188
	GnomeVFSResult result;
169
	GnomeVFSResult result;
Lines 195-202 Link Here
195
} GnomeVFSWriteOp;
176
} GnomeVFSWriteOp;
196
177
197
typedef struct {
178
typedef struct {
198
	GnomeVFSAsyncWriteCallback callback;
199
	void *callback_data;
200
	GnomeVFSFileSize num_bytes;
179
	GnomeVFSFileSize num_bytes;
201
	gconstpointer buffer;
180
	gconstpointer buffer;
202
	GnomeVFSResult result;
181
	GnomeVFSResult result;
Lines 209-216 Link Here
209
} GnomeVFSSeekOp;
188
} GnomeVFSSeekOp;
210
189
211
typedef struct {
190
typedef struct {
212
	GnomeVFSAsyncSeekCallback callback;
213
	void *callback_data;
214
	GnomeVFSResult result;
191
	GnomeVFSResult result;
215
} GnomeVFSSeekOpResult;
192
} GnomeVFSSeekOpResult;
216
193
Lines 220-227 Link Here
220
} GnomeVFSGetFileInfoOp;
197
} GnomeVFSGetFileInfoOp;
221
198
222
typedef struct {
199
typedef struct {
223
	GnomeVFSAsyncGetFileInfoCallback callback;
224
	void *callback_data;
225
	GList *result_list; /* GnomeVFSGetFileInfoResult* */
200
	GList *result_list; /* GnomeVFSGetFileInfoResult* */
226
} GnomeVFSGetFileInfoOpResult;
201
} GnomeVFSGetFileInfoOpResult;
227
202
Lines 233-240 Link Here
233
} GnomeVFSSetFileInfoOp;
208
} GnomeVFSSetFileInfoOp;
234
209
235
typedef struct {
210
typedef struct {
236
	GnomeVFSAsyncSetFileInfoCallback callback;
237
	void *callback_data;
238
	GnomeVFSResult set_file_info_result;
211
	GnomeVFSResult set_file_info_result;
239
	GnomeVFSResult get_file_info_result;
212
	GnomeVFSResult get_file_info_result;
240
	GnomeVFSFileInfo *info;
213
	GnomeVFSFileInfo *info;
Lines 249-256 Link Here
249
} GnomeVFSFindDirectoryOp;
222
} GnomeVFSFindDirectoryOp;
250
223
251
typedef struct {
224
typedef struct {
252
	GnomeVFSAsyncFindDirectoryCallback callback;
225
	GnomeVFSResult result;
253
	void *callback_data;
254
	GList *result_list; /* GnomeVFSFindDirectoryResult */
226
	GList *result_list; /* GnomeVFSFindDirectoryResult */
255
} GnomeVFSFindDirectoryOpResult;
227
} GnomeVFSFindDirectoryOpResult;
256
228
Lines 261-268 Link Here
261
} GnomeVFSLoadDirectoryOp;
233
} GnomeVFSLoadDirectoryOp;
262
234
263
typedef struct {
235
typedef struct {
264
	GnomeVFSAsyncDirectoryLoadCallback callback;
265
	void *callback_data;
266
	GnomeVFSResult result;
236
	GnomeVFSResult result;
267
	GList *list;
237
	GList *list;
268
	guint entries_read;
238
	guint entries_read;
Lines 279-286 Link Here
279
} GnomeVFSXferOp;
249
} GnomeVFSXferOp;
280
250
281
typedef struct {
251
typedef struct {
282
	GnomeVFSAsyncXferProgressCallback callback;
283
	void *callback_data;
284
	GnomeVFSXferProgressInfo *progress_info;
252
	GnomeVFSXferProgressInfo *progress_info;
285
	int reply;
253
	int reply;
286
} GnomeVFSXferOpResult;
254
} GnomeVFSXferOpResult;
Lines 303-310 Link Here
303
} GnomeVFSFileControlOp;
271
} GnomeVFSFileControlOp;
304
272
305
typedef struct {
273
typedef struct {
306
	GnomeVFSAsyncFileControlCallback callback;
307
	gpointer callback_data;
308
	GnomeVFSResult result;
274
	GnomeVFSResult result;
309
	gpointer operation_data;
275
	gpointer operation_data;
310
	GDestroyNotify operation_data_destroy_func;
276
	GDestroyNotify operation_data_destroy_func;
Lines 329-337 Link Here
329
} GnomeVFSSpecificOp;
295
} GnomeVFSSpecificOp;
330
296
331
typedef struct {
297
typedef struct {
298
	/* Job corresponding to this operation */
299
	GnomeVFSJob *job;
300
332
	/* ID of the job (e.g. open, create, close...). */
301
	/* ID of the job (e.g. open, create, close...). */
333
	GnomeVFSOpType type;
302
	GnomeVFSOpType type;
334
303
304
	/* Whether this operation was canceled */
305
	gboolean canceled;
306
335
	/* The callback for when the op is completed. */
307
	/* The callback for when the op is completed. */
336
	GFunc callback;
308
	GFunc callback;
337
	gpointer callback_data;
309
	gpointer callback_data;
Lines 363-399 Link Here
363
} GnomeVFSSpecificNotifyResult;
335
} GnomeVFSSpecificNotifyResult;
364
336
365
typedef struct {
337
typedef struct {
366
	GnomeVFSAsyncHandle *job_handle;
338
	/* Operation to which this notification refers */
339
	GnomeVFSOp *op;
367
340
341
#if 0
368
	guint callback_id;
342
	guint callback_id;
369
370
	/* By the time the callback got reached the job might have been cancelled.
343
	/* By the time the callback got reached the job might have been cancelled.
371
	 * We find out by checking this flag.
344
	 * We find out by checking this flag.
372
	 */
345
	 */
373
	gboolean cancelled;
346
	gboolean cancelled; /* FMQ: should this be here?  isn't job_has_cancelled_op () for the corresponding op enough? */
374
	
347
	
375
	/* ID of the job (e.g. open, create, close...). */
348
	/* ID of the job (e.g. open, create, close...). */
376
	GnomeVFSOpType type;
349
	GnomeVFSOpType type; /* FMQ: this is not needed; we can use op->type, right? */
377
350
#endif
378
	GnomeVFSSpecificNotifyResult specifics;
351
	GnomeVFSSpecificNotifyResult specifics;
352
353
	/* Does this result actually correspond to a module callback, rather than an op's notification? */
354
	gboolean is_module_callback;
379
} GnomeVFSNotifyResult;
355
} GnomeVFSNotifyResult;
380
356
381
/* FIXME bugzilla.eazel.com 1135: Move private stuff out of the header.  */
357
/* FIXME bugzilla.eazel.com 1135: Move private stuff out of the header.  */
382
struct GnomeVFSJob {
358
struct GnomeVFSJob {
383
	/* Handle being used for file access.  */
359
	/* Handle being used for file access.  */
384
	GnomeVFSHandle *handle;
360
	GnomeVFSHandle *handle;
385
361
#if 0
386
	/* By the time the entry routine for the job got reached
362
	/* By the time the entry routine for the job got reached
387
	 * the job might have been cancelled. We find out by checking
363
	 * the job might have been cancelled. We find out by checking
388
	 * this flag.
364
	 * this flag.
389
	 */
365
	 */
390
	gboolean cancelled;
366
	gboolean cancelled; /* FMQ: moved to GnomeVFSOp */
391
367
392
	/* Read or create returned with an error - helps
368
	/* Read or create returned with an error - helps
393
	 * flagging that we do not expect a cancel
369
	 * flagging that we do not expect a cancel
394
	 */
370
	 */
395
	gboolean failed;
371
	gboolean failed; /* FMQ: move this to GnomeVFSOp? */
396
372
#endif
397
	/* Global lock for accessing job's 'op' and 'handle' */
373
	/* Global lock for accessing job's 'op' and 'handle' */
398
	GMutex *job_lock;
374
	GMutex *job_lock;
399
375
Lines 401-411 Link Here
401
           notification and wants to acknowledge it.  */
377
           notification and wants to acknowledge it.  */
402
	GCond *notify_ack_condition;
378
	GCond *notify_ack_condition;
403
379
404
	/* Operations that are being done and those that are completed and
380
	/* The current operation, which is in progress.  If this is NULL, it
405
	 * ready for notification to take place.
381
	 * means that the current operation is either done or canceled.  "Done"
382
	 * means that the caller has been notified through its callbacks;
383
	 * canceled means the op is now in the job->canceled_ops list.
406
	 */
384
	 */
407
	GnomeVFSOp *op;
385
	GnomeVFSOp *op;
408
	
386
387
	/* List of canceled operations.  job->op gets moved to here when someone calls
388
	 * gnome_vfs_async_cancel().  The list shrinks when we pick up notification in
389
	 * dispatch_job_callback().
390
	 */
391
	GSList *canceled_ops;
392
393
	/* Whether we must wait for canceled operations to get notification
394
	 * before we can free the job.
395
	 */
396
	gboolean free_when_canceled_ops_complete;
397
409
	/* Unique identifier of this job (a uint, really) */
398
	/* Unique identifier of this job (a uint, really) */
410
	GnomeVFSAsyncHandle *job_handle;
399
	GnomeVFSAsyncHandle *job_handle;
411
400
Lines 423-432 Link Here
423
				      		   GFunc           	 callback,
412
				      		   GFunc           	 callback,
424
				      		   gpointer        	 callback_data);
413
				      		   gpointer        	 callback_data);
425
void         	 _gnome_vfs_job_go       	  (GnomeVFSJob     	*job);
414
void         	 _gnome_vfs_job_go       	  (GnomeVFSJob     	*job);
426
void     	 _gnome_vfs_job_execute  	  (GnomeVFSJob     	*job);
415
void     	 _gnome_vfs_job_execute  	  (GnomeVFSOp     	*op);
427
void         	 _gnome_vfs_job_module_cancel  	  (GnomeVFSJob	 	*job);
416
void         	 _gnome_vfs_job_module_cancel  	  (GnomeVFSJob	 	*job);
428
int          	 gnome_vfs_job_get_count 	  (void);
417
int          	 gnome_vfs_job_get_count 	  (void);
429
430
gboolean	 _gnome_vfs_job_complete	  (GnomeVFSJob 		*job);
431
418
432
#endif /* GNOME_VFS_JOB_H */
419
#endif /* GNOME_VFS_JOB_H */
(-)libgnomevfs/gnome-vfs-job.c (-476 / +626 lines)
Lines 28-33 Link Here
28
   */
28
   */
29
29
30
#include <config.h>
30
#include <config.h>
31
#include <string.h>
32
#include <sys/time.h>
33
#include <glib/gprintf.h>
31
#include "gnome-vfs-job.h"
34
#include "gnome-vfs-job.h"
32
35
33
#include "gnome-vfs-async-job-map.h"
36
#include "gnome-vfs-async-job-map.h"
Lines 44-49 Link Here
44
#include <string.h>
47
#include <string.h>
45
#include <unistd.h>
48
#include <unistd.h>
46
49
50
/* We store a GnomeVFSOp here */
47
static GStaticPrivate job_private = G_STATIC_PRIVATE_INIT;
51
static GStaticPrivate job_private = G_STATIC_PRIVATE_INIT;
48
52
49
#if GNOME_VFS_JOB_DEBUG
53
#if GNOME_VFS_JOB_DEBUG
Lines 71-160 Link Here
71
static int job_count = 0;
75
static int job_count = 0;
72
76
73
static void     gnome_vfs_op_destroy                (GnomeVFSOp           *op);
77
static void     gnome_vfs_op_destroy                (GnomeVFSOp           *op);
74
static void     _gnome_vfs_job_destroy_notify_result (GnomeVFSNotifyResult *notify_result);
78
static void     _gnome_vfs_job_destroy_notify_result (GnomeVFSNotifyResult *notify_result,
79
						      GnomeVFSOpType	    type);
75
static gboolean dispatch_job_callback               (gpointer              data);
80
static gboolean dispatch_job_callback               (gpointer              data);
76
static gboolean dispatch_sync_job_callback          (gpointer              data);
81
static gboolean dispatch_sync_job_callback          (gpointer              data);
77
82
78
static void	clear_current_job 		    (void);
83
static void	clear_current_op 		    (void);
79
static void	set_current_job 		    (GnomeVFSJob *context);
84
static void	set_current_op			    (GnomeVFSOp *op);
80
85
81
/*
86
static void
82
 *   Find out whether or not a given job should be left in
87
fmq_log (const char *str, ...)
83
 * the job map, preserving it's open VFS handle, since we
84
 * can do more operations on it later.
85
 */
86
gboolean
87
_gnome_vfs_job_complete (GnomeVFSJob *job)
88
{
88
{
89
	g_assert (job->op != NULL);
89
#if 0
90
	
90
	va_list args;
91
	switch (job->op->type) {
91
	GThread *thread;
92
	case GNOME_VFS_OP_OPEN:
92
	struct timeval tv;
93
	case GNOME_VFS_OP_OPEN_AS_CHANNEL:
93
	double sec;
94
	case GNOME_VFS_OP_CREATE:
95
	case GNOME_VFS_OP_CREATE_AS_CHANNEL:
96
	case GNOME_VFS_OP_CREATE_SYMBOLIC_LINK:
97
		/* if job got cancelled, no close expected */
98
		return job->cancelled || job->failed;
99
94
100
	case GNOME_VFS_OP_READ:
95
	va_start (args, str);
101
	case GNOME_VFS_OP_WRITE:
96
102
		g_assert_not_reached();
97
	thread = g_thread_self ();
103
		return FALSE;
98
104
	case GNOME_VFS_OP_READ_WRITE_DONE:
99
	gettimeofday (&tv, NULL);
105
	case GNOME_VFS_OP_FILE_CONTROL:
100
	sec = tv.tv_sec + ((double) tv.tv_usec / 1e6);
106
	case GNOME_VFS_OP_SEEK:
101
107
		return FALSE;
102
	g_fprintf (stderr, "Thread %p time %.16g: ", thread, sec);
108
	
103
	g_vfprintf (stderr, str, args);
109
	default:
104
	g_fprintf (stderr, "\n");
110
		return TRUE;
105
111
	}
106
	va_end (args);
107
#endif
112
}
108
}
113
109
114
/* This notifies the master thread asynchronously, without waiting for an
110
/* This notifies the master thread asynchronously, without waiting for an
115
 * acknowledgment.
111
 * acknowledgment.
116
 */
112
 */
117
static void
113
static void
118
job_oneway_notify (GnomeVFSJob *job, GnomeVFSNotifyResult *notify_result)
114
job_oneway_notify (GnomeVFSNotifyResult *notify_result)
119
{
115
{
120
	if (_gnome_vfs_async_job_add_callback (job, notify_result)) {
116
	JOB_DEBUG (("job %u, type '%s'",
121
		JOB_DEBUG (("job %u, callback %u type '%s'",
117
		    GPOINTER_TO_UINT (notify_result->op->job->job_handle),
122
			    GPOINTER_TO_UINT (notify_result->job_handle),
118
		    JOB_DEBUG_TYPE (notify_result->op->type)));
123
			    notify_result->callback_id,
119
124
			    JOB_DEBUG_TYPE (job->op->type)));
120
	g_idle_add (dispatch_job_callback, notify_result);
125
	
126
		g_idle_add (dispatch_job_callback, notify_result);
127
	} else {
128
		JOB_DEBUG (("Barfing on oneway cancel %u (%d) type '%s'",
129
			    GPOINTER_TO_UINT (notify_result->job_handle),
130
			    job->op->type, JOB_DEBUG_TYPE (job->op->type)));
131
		/* TODO: We can leak handle here, if an open succeded.
132
		 * See bug #123472 */
133
		_gnome_vfs_job_destroy_notify_result (notify_result);
134
	}
135
}
121
}
136
122
137
/* This notifies the master threads, waiting until it acknowledges the
123
/* This notifies the master threads, waiting until it acknowledges the
138
   notification.  */
124
   notification.  */
139
static void
125
static void
140
job_notify (GnomeVFSJob *job, GnomeVFSNotifyResult *notify_result)
126
job_notify (GnomeVFSNotifyResult *notify_result)
141
{
127
{
142
	if (!_gnome_vfs_async_job_add_callback (job, notify_result)) {
143
		JOB_DEBUG (("Barfing on sync cancel %u (%d)",
144
			    GPOINTER_TO_UINT (notify_result->job_handle),
145
			    job->op->type));
146
		_gnome_vfs_job_destroy_notify_result (notify_result);
147
		return;
148
	}
149
150
	/* Send the notification.  This will wake up the master thread, which
128
	/* Send the notification.  This will wake up the master thread, which
151
         * will in turn signal the notify condition.
129
         * will in turn signal the notify condition.
152
         */
130
         */
153
	g_idle_add (dispatch_sync_job_callback, notify_result);
131
	g_idle_add (dispatch_sync_job_callback, notify_result);
154
132
155
	JOB_DEBUG (("Wait notify condition %u", GPOINTER_TO_UINT (notify_result->job_handle)));
133
	JOB_DEBUG (("Wait notify condition %u", GPOINTER_TO_UINT (notify_result->op->job->job_handle)));
156
	/* Wait for the notify condition.  */
134
	/* Wait for the notify condition.  */
157
	g_cond_wait (job->notify_ack_condition, job->job_lock);
135
	g_cond_wait (notify_result->op->job->notify_ack_condition, notify_result->op->job->job_lock);
158
136
159
	JOB_DEBUG (("Got notify ack condition %u", GPOINTER_TO_UINT (notify_result->job_handle)));
137
	JOB_DEBUG (("Got notify ack condition %u", GPOINTER_TO_UINT (notify_result->job_handle)));
160
}
138
}
Lines 162-289 Link Here
162
static void
140
static void
163
dispatch_open_callback (GnomeVFSNotifyResult *notify_result)
141
dispatch_open_callback (GnomeVFSNotifyResult *notify_result)
164
{
142
{
165
	(* notify_result->specifics.open.callback) (notify_result->job_handle,
143
	GnomeVFSAsyncOpenCallback callback;
166
						    notify_result->specifics.open.result,
144
167
						    notify_result->specifics.open.callback_data);
145
	callback = (GnomeVFSAsyncOpenCallback) notify_result->op->callback;
146
147
	(* callback) (notify_result->op->job->job_handle,
148
		      notify_result->specifics.open.result,
149
		      notify_result->op->callback_data);
168
}
150
}
169
151
170
static void
152
static void
171
dispatch_create_callback (GnomeVFSNotifyResult *notify_result)
153
dispatch_create_callback (GnomeVFSNotifyResult *notify_result)
172
{
154
{
173
	(* notify_result->specifics.create.callback) (notify_result->job_handle,
155
	GnomeVFSAsyncCreateCallback callback;
174
						      notify_result->specifics.create.result,
156
175
						      notify_result->specifics.create.callback_data);
157
	callback = (GnomeVFSAsyncCreateCallback) notify_result->op->callback;
158
159
	(* callback) (notify_result->op->job->job_handle,
160
		      notify_result->specifics.create.result,
161
		      notify_result->op->callback_data);
176
}
162
}
177
163
178
static void
164
static void
179
dispatch_open_as_channel_callback (GnomeVFSNotifyResult *notify_result)
165
dispatch_open_as_channel_callback (GnomeVFSNotifyResult *notify_result)
180
{
166
{
181
	(* notify_result->specifics.open_as_channel.callback) (notify_result->job_handle,
167
	GnomeVFSAsyncOpenAsChannelCallback callback;
182
							       notify_result->specifics.open_as_channel.channel,
168
183
							       notify_result->specifics.open_as_channel.result,
169
	callback = (GnomeVFSAsyncOpenAsChannelCallback) notify_result->op->callback;
184
							       notify_result->specifics.open_as_channel.callback_data);
170
171
	(* callback) (notify_result->op->job->job_handle,
172
		      notify_result->specifics.open_as_channel.channel,
173
		      notify_result->specifics.open_as_channel.result,
174
		      notify_result->op->callback_data);
185
}
175
}
186
176
187
static void
177
static void
188
dispatch_create_as_channel_callback (GnomeVFSNotifyResult *notify_result)
178
dispatch_create_as_channel_callback (GnomeVFSNotifyResult *notify_result)
189
{
179
{
190
	(* notify_result->specifics.create_as_channel.callback) (notify_result->job_handle,
180
	GnomeVFSAsyncCreateAsChannelCallback callback;
191
								 notify_result->specifics.create_as_channel.channel,
181
192
								 notify_result->specifics.create_as_channel.result,
182
	callback = (GnomeVFSAsyncCreateAsChannelCallback) notify_result->op->callback;
193
								 notify_result->specifics.create_as_channel.callback_data);
183
184
	(* callback) (notify_result->op->job->job_handle,
185
		      notify_result->specifics.create_as_channel.channel,
186
		      notify_result->specifics.create_as_channel.result,
187
		      notify_result->op->callback_data);
194
}
188
}
195
189
196
static void
190
static void
197
dispatch_close_callback (GnomeVFSNotifyResult *notify_result)
191
dispatch_close_callback (GnomeVFSNotifyResult *notify_result)
198
{
192
{
199
	(* notify_result->specifics.close.callback) (notify_result->job_handle,
193
	GnomeVFSAsyncCloseCallback callback;
200
						     notify_result->specifics.close.result,
194
201
						     notify_result->specifics.close.callback_data);
195
	callback = (GnomeVFSAsyncCloseCallback) notify_result->op->callback;
196
197
	(* callback) (notify_result->op->job->job_handle,
198
		      notify_result->specifics.close.result,
199
		      notify_result->op->callback_data);
202
}
200
}
203
201
204
static void
202
static void
205
dispatch_read_callback (GnomeVFSNotifyResult *notify_result)
203
dispatch_read_callback (GnomeVFSNotifyResult *notify_result)
206
{
204
{
207
	(* notify_result->specifics.read.callback) (notify_result->job_handle,
205
	GnomeVFSAsyncReadCallback callback;
208
						    notify_result->specifics.read.result,
206
209
						    notify_result->specifics.read.buffer,
207
	callback = (GnomeVFSAsyncReadCallback) notify_result->op->callback;
210
						    notify_result->specifics.read.num_bytes,
208
211
						    notify_result->specifics.read.bytes_read,
209
	(* callback) (notify_result->op->job->job_handle,
212
						    notify_result->specifics.read.callback_data);
210
		      notify_result->specifics.read.result,
211
		      notify_result->specifics.read.buffer,
212
		      notify_result->specifics.read.num_bytes,
213
		      notify_result->specifics.read.bytes_read,
214
		      notify_result->op->callback_data);
213
}
215
}
214
216
215
static void
217
static void
216
dispatch_write_callback (GnomeVFSNotifyResult *notify_result)
218
dispatch_write_callback (GnomeVFSNotifyResult *notify_result)
217
{
219
{
218
	(* notify_result->specifics.write.callback) (notify_result->job_handle,
220
	GnomeVFSAsyncWriteCallback callback;
219
						     notify_result->specifics.write.result,
221
220
						     notify_result->specifics.write.buffer,
222
	callback = (GnomeVFSAsyncWriteCallback) notify_result->op->callback;
221
						     notify_result->specifics.write.num_bytes,
223
222
						     notify_result->specifics.write.bytes_written,
224
	(* callback) (notify_result->op->job->job_handle,
223
						     notify_result->specifics.write.callback_data);
225
		      notify_result->specifics.write.result,
226
		      notify_result->specifics.write.buffer,
227
		      notify_result->specifics.write.num_bytes,
228
		      notify_result->specifics.write.bytes_written,
229
		      notify_result->op->callback_data);
224
}
230
}
225
231
226
static void
232
static void
227
dispatch_seek_callback (GnomeVFSNotifyResult *notify_result)
233
dispatch_seek_callback (GnomeVFSNotifyResult *notify_result)
228
{
234
{
229
	(* notify_result->specifics.seek.callback) (notify_result->job_handle,
235
	GnomeVFSAsyncSeekCallback callback;
230
						    notify_result->specifics.seek.result,
236
231
						    notify_result->specifics.seek.callback_data);
237
	callback = (GnomeVFSAsyncSeekCallback) notify_result->op->callback;
238
239
	(* callback) (notify_result->op->job->job_handle,
240
		      notify_result->specifics.seek.result,
241
		      notify_result->op->callback_data);
232
}
242
}
233
243
234
static void
244
static void
235
dispatch_load_directory_callback (GnomeVFSNotifyResult *notify_result)
245
dispatch_load_directory_callback (GnomeVFSNotifyResult *notify_result)
236
{
246
{
237
	(* notify_result->specifics.load_directory.callback) (notify_result->job_handle,
247
	GnomeVFSAsyncDirectoryLoadCallback callback;
238
							      notify_result->specifics.load_directory.result,
248
239
							      notify_result->specifics.load_directory.list,
249
	callback = (GnomeVFSAsyncDirectoryLoadCallback) notify_result->op->callback;
240
							      notify_result->specifics.load_directory.entries_read,
250
241
							      notify_result->specifics.load_directory.callback_data);
251
	(* callback) (notify_result->op->job->job_handle,
252
		      notify_result->specifics.load_directory.result,
253
		      notify_result->specifics.load_directory.list,
254
		      notify_result->specifics.load_directory.entries_read,
255
		      notify_result->op->callback_data);
242
}
256
}
243
257
244
static void
258
static void
245
dispatch_get_file_info_callback (GnomeVFSNotifyResult *notify_result)
259
dispatch_get_file_info_callback (GnomeVFSNotifyResult *notify_result)
246
{
260
{
247
	(* notify_result->specifics.get_file_info.callback) (notify_result->job_handle,
261
	GnomeVFSAsyncGetFileInfoCallback callback;
248
							     notify_result->specifics.get_file_info.result_list,
262
249
							     notify_result->specifics.get_file_info.callback_data);
263
	callback = (GnomeVFSAsyncGetFileInfoCallback) notify_result->op->callback;
264
265
	(* callback) (notify_result->op->job->job_handle,
266
		      notify_result->specifics.get_file_info.result_list,
267
		      notify_result->op->callback_data);
250
}
268
}
251
269
252
static void
270
static void
253
dispatch_find_directory_callback (GnomeVFSNotifyResult *notify_result)
271
dispatch_find_directory_callback (GnomeVFSNotifyResult *notify_result)
254
{
272
{
255
	(* notify_result->specifics.find_directory.callback) (notify_result->job_handle,
273
	GnomeVFSAsyncFindDirectoryCallback callback;
256
							      notify_result->specifics.find_directory.result_list,
274
257
							      notify_result->specifics.find_directory.callback_data);
275
	callback = (GnomeVFSAsyncFindDirectoryCallback) notify_result->op->callback;
276
277
	(* callback) (notify_result->op->job->job_handle,
278
		      notify_result->specifics.find_directory.result_list,
279
		      notify_result->op->callback_data);
258
}
280
}
259
281
260
static void
282
static void
261
dispatch_set_file_info_callback (GnomeVFSNotifyResult *notify_result)
283
dispatch_set_file_info_callback (GnomeVFSNotifyResult *notify_result)
262
{
284
{
285
	GnomeVFSAsyncSetFileInfoCallback callback;
263
	gboolean new_info_is_valid;
286
	gboolean new_info_is_valid;
264
287
288
	callback = (GnomeVFSAsyncSetFileInfoCallback) notify_result->op->callback;
289
265
	new_info_is_valid = notify_result->specifics.set_file_info.set_file_info_result == GNOME_VFS_OK
290
	new_info_is_valid = notify_result->specifics.set_file_info.set_file_info_result == GNOME_VFS_OK
266
		&& notify_result->specifics.set_file_info.get_file_info_result == GNOME_VFS_OK;
291
		&& notify_result->specifics.set_file_info.get_file_info_result == GNOME_VFS_OK;
267
		
292
		
268
	(* notify_result->specifics.set_file_info.callback) (notify_result->job_handle,
293
	(* callback) (notify_result->op->job->job_handle,
269
							     notify_result->specifics.set_file_info.set_file_info_result,
294
		      notify_result->specifics.set_file_info.set_file_info_result,
270
							     new_info_is_valid ? notify_result->specifics.set_file_info.info : NULL,
295
		      new_info_is_valid ? notify_result->specifics.set_file_info.info : NULL,
271
							     notify_result->specifics.set_file_info.callback_data);
296
		      notify_result->op->callback_data);
272
}
297
}
273
298
274
static void
299
static void
275
dispatch_xfer_callback (GnomeVFSNotifyResult *notify_result, gboolean cancelled)
300
dispatch_xfer_callback (GnomeVFSNotifyResult *notify_result, gboolean cancelled)
276
{
301
{
302
	GnomeVFSAsyncXferProgressCallback callback;
303
304
	callback = (GnomeVFSAsyncXferProgressCallback) notify_result->op->callback;
305
277
	if (cancelled) {
306
	if (cancelled) {
278
		/* make the xfer operation stop */
307
		/* make the xfer operation stop */
279
		notify_result->specifics.xfer.reply = 0;
308
		notify_result->specifics.xfer.reply = 0;
280
		return;
309
		return;
281
	}
310
	}
282
	
311
	
283
	notify_result->specifics.xfer.reply = (* notify_result->specifics.xfer.callback) (
312
	notify_result->specifics.xfer.reply = (* callback) (notify_result->op->job->job_handle,
284
							    notify_result->job_handle,
285
							    notify_result->specifics.xfer.progress_info,
313
							    notify_result->specifics.xfer.progress_info,
286
						            notify_result->specifics.xfer.callback_data);
314
						            notify_result->op->callback_data);
287
}
315
}
288
316
289
static void
317
static void
Lines 301-310 Link Here
301
static void
329
static void
302
dispatch_file_control_callback (GnomeVFSNotifyResult *notify_result)
330
dispatch_file_control_callback (GnomeVFSNotifyResult *notify_result)
303
{
331
{
304
	notify_result->specifics.file_control.callback (notify_result->job_handle,
332
	GnomeVFSAsyncFileControlCallback callback;
305
							notify_result->specifics.file_control.result,
333
306
							notify_result->specifics.file_control.operation_data,
334
	callback = (GnomeVFSAsyncFileControlCallback) notify_result->op->callback;
307
							notify_result->specifics.file_control.callback_data);
335
336
	(* callback) (notify_result->op->job->job_handle,
337
		      notify_result->specifics.file_control.result,
338
		      notify_result->specifics.file_control.operation_data,
339
		      notify_result->op->callback_data);
308
}
340
}
309
341
310
static void
342
static void
Lines 315-322 Link Here
315
}
347
}
316
348
317
static void
349
static void
350
remove_and_free_job (GnomeVFSJob *job)
351
{
352
	_gnome_vfs_async_job_completed (job);
353
	_gnome_vfs_job_destroy (job);
354
}
355
356
static void
318
handle_cancelled_open (GnomeVFSJob *job)
357
handle_cancelled_open (GnomeVFSJob *job)
319
{
358
{
359
	fmq_log ("MAIN: handle_cancelled_open(): RECYCLING job %p to close a file",
360
		 job);
320
	/* schedule a silent close to make sure the handle does not leak */
361
	/* schedule a silent close to make sure the handle does not leak */
321
	_gnome_vfs_job_set (job, GNOME_VFS_OP_CLOSE, 
362
	_gnome_vfs_job_set (job, GNOME_VFS_OP_CLOSE, 
322
			   (GFunc) empty_close_callback, NULL);
363
			   (GFunc) empty_close_callback, NULL);
Lines 357-367 Link Here
357
}
398
}
358
399
359
static void
400
static void
360
_gnome_vfs_job_destroy_notify_result (GnomeVFSNotifyResult *notify_result)
401
_gnome_vfs_job_destroy_notify_result (GnomeVFSNotifyResult *notify_result, GnomeVFSOpType type)
361
{
402
{
362
	JOB_DEBUG (("%u", notify_result->callback_id));
403
	JOB_DEBUG (("%u", notify_result->callback_id));
363
404
364
	switch (notify_result->type) {
405
	fmq_log ("MAIN: _gnome_vfs_job_destroy_notify_result(): notify_result %p",
406
		 notify_result);
407
408
	switch (type) {
365
	case GNOME_VFS_OP_CLOSE:
409
	case GNOME_VFS_OP_CLOSE:
366
	case GNOME_VFS_OP_CREATE:
410
	case GNOME_VFS_OP_CREATE:
367
	case GNOME_VFS_OP_CREATE_AS_CHANNEL:
411
	case GNOME_VFS_OP_CREATE_AS_CHANNEL:
Lines 406-415 Link Here
406
		/* the XFER result is allocated on the stack */
450
		/* the XFER result is allocated on the stack */
407
		break;
451
		break;
408
		
452
		
409
	case GNOME_VFS_OP_MODULE_CALLBACK:
410
		/* the MODULE_CALLBACK result is allocated on the stack */
411
		break;
412
	
413
	default:
453
	default:
414
		g_assert_not_reached ();
454
		g_assert_not_reached ();
415
		break;
455
		break;
Lines 422-468 Link Here
422
{
462
{
423
	GnomeVFSNotifyResult *notify_result;
463
	GnomeVFSNotifyResult *notify_result;
424
	GnomeVFSJob *job;
464
	GnomeVFSJob *job;
425
	gboolean valid;
426
	gboolean cancelled;
427
465
428
	notify_result = (GnomeVFSNotifyResult *) data;
466
	notify_result = (GnomeVFSNotifyResult *) data;
429
467
430
	_gnome_vfs_async_job_callback_valid (notify_result->callback_id, &valid, &cancelled);
468
	if (notify_result->is_module_callback)
431
432
	/* Even though the notify result is owned by the async thread and persists
433
	 * all through the notification, we still keep it in the job map to
434
	 * make cancellation easier.
435
	 */
436
	_gnome_vfs_async_job_remove_callback (notify_result->callback_id);
437
438
	g_assert (valid);
439
440
	switch (notify_result->type) {
441
	case GNOME_VFS_OP_CREATE_AS_CHANNEL:
442
		dispatch_create_as_channel_callback (notify_result);
443
		break;
444
	case GNOME_VFS_OP_OPEN_AS_CHANNEL:
445
		dispatch_open_as_channel_callback (notify_result);
446
		break;		
447
	case GNOME_VFS_OP_XFER:
448
		dispatch_xfer_callback (notify_result, cancelled);
449
		break;
450
	case GNOME_VFS_OP_MODULE_CALLBACK:
451
		dispatch_module_callback (notify_result);
469
		dispatch_module_callback (notify_result);
452
		break;
470
	else
453
	default:
471
		switch (notify_result->op->type) {
454
		g_assert_not_reached ();
472
		case GNOME_VFS_OP_CREATE_AS_CHANNEL:
455
		break;
473
			dispatch_create_as_channel_callback (notify_result);
456
	}
474
			break;
457
	
475
		case GNOME_VFS_OP_OPEN_AS_CHANNEL:
458
	_gnome_vfs_async_job_map_lock ();
476
			dispatch_open_as_channel_callback (notify_result);
459
	job = _gnome_vfs_async_job_map_get_job (notify_result->job_handle);
477
			break;		
478
		case GNOME_VFS_OP_XFER:
479
			dispatch_xfer_callback (notify_result, notify_result->op->canceled);
480
			break;
481
		default:
482
			g_assert_not_reached ();
483
			break;
484
		}
485
486
	job = notify_result->op->job;
460
	g_mutex_lock (job->job_lock);
487
	g_mutex_lock (job->job_lock);
461
	_gnome_vfs_async_job_map_unlock ();
488
462
	
489
	JOB_DEBUG (("signalling %u", GPOINTER_TO_UINT (job->job_handle)));
463
	g_assert (job != NULL);
464
	
465
	JOB_DEBUG (("signalling %u", GPOINTER_TO_UINT (notify_result->job_handle)));
466
	
490
	
467
	/* Signal the async thread that we are done with the notification. */
491
	/* Signal the async thread that we are done with the notification. */
468
	g_cond_signal (job->notify_ack_condition);
492
	g_cond_signal (job->notify_ack_condition);
Lines 474-577 Link Here
474
/* Entry point for async notification callback */
498
/* Entry point for async notification callback */
475
static gboolean
499
static gboolean
476
dispatch_job_callback (gpointer data)
500
dispatch_job_callback (gpointer data)
477
478
{
501
{
479
	GnomeVFSNotifyResult *notify_result;
502
	GnomeVFSNotifyResult *notify_result;
480
	GnomeVFSJob *job;
503
	GnomeVFSJob *job;
481
	gboolean valid;
504
	gboolean canceled;
482
	gboolean cancelled;
505
	GnomeVFSOpType type;
506
	gboolean free_op;
507
	gboolean maybe_remove_job;
483
	
508
	
484
	notify_result = (GnomeVFSNotifyResult *) data;
509
	notify_result = (GnomeVFSNotifyResult *) data;
485
510
486
	JOB_DEBUG (("%u type '%s'", GPOINTER_TO_UINT (notify_result->job_handle),
511
	fmq_log ("MAIN: dispatch_job_callback(): notify_result %p, op %p, op type %d, job %p, job_handle %p, canceled = %d",
512
		 notify_result,
513
		 notify_result->op,
514
		 (int) notify_result->op->type,
515
		 notify_result->op->job,
516
		 notify_result->op->job->job_handle,
517
		 (int) notify_result->op->canceled);
518
519
	JOB_DEBUG (("%u type '%s'", GPOINTER_TO_UINT (notify_result->op->job->job_handle),
487
		    JOB_DEBUG_TYPE (notify_result->type)));
520
		    JOB_DEBUG_TYPE (notify_result->type)));
488
	
489
	_gnome_vfs_async_job_callback_valid (notify_result->callback_id, &valid, &cancelled);
490
	_gnome_vfs_async_job_remove_callback (notify_result->callback_id);
491
521
492
	if (!valid) {
522
	_gnome_vfs_async_job_map_lock (); /* will unlock after the if() clause below */
493
		/* this can happen when gnome vfs is shutting down */
523
	job = _gnome_vfs_async_job_map_get_job (notify_result->op->job->job_handle);
494
		JOB_DEBUG (("shutting down: callback %u no longer valid",
524
	g_assert (job == notify_result->op->job);
495
			    notify_result->callback_id));
525
	_gnome_vfs_async_job_map_unlock ();
496
		_gnome_vfs_job_destroy_notify_result (notify_result);
526
497
		return FALSE;
527
	g_mutex_lock (job->job_lock);
498
	}
528
	canceled = notify_result->op->canceled;
529
	type = notify_result->op->type;
499
	
530
	
500
	if (cancelled) {
531
	if (canceled) {
501
		/* cancel the job in progress */
532
		GSList *canceled_op_link;
502
		JOB_DEBUG (("cancelling job %u %u",
533
		gboolean job_unlocked;
503
			    GPOINTER_TO_UINT (notify_result->job_handle),
504
			    notify_result->callback_id));
505
534
506
		_gnome_vfs_async_job_map_lock ();
535
		/* cancel the job in progress */
536
		JOB_DEBUG (("cancelling job %u",
537
			    GPOINTER_TO_UINT (job->job_handle)));
507
538
508
		job = _gnome_vfs_async_job_map_get_job (notify_result->job_handle);
539
		fmq_log ("MAIN: dispatch_job_callback(): handling cancelled job for notify_result %p, op %p, job %p, job_handle %p",
509
		
540
			 notify_result,
510
		if (job != NULL) {
541
			 notify_result->op,
511
			g_mutex_lock (job->job_lock);
542
			 job,
543
			 job->job_handle);
544
545
		g_assert (job->op != notify_result->op);
546
		canceled_op_link = g_slist_find (job->canceled_ops, notify_result->op);
547
		g_assert (canceled_op_link != NULL);
548
549
		free_op = TRUE;
550
		maybe_remove_job = FALSE;
551
		job_unlocked = FALSE;
512
552
513
			switch (job->op->type) {
553
		switch (type) {
514
			case GNOME_VFS_OP_OPEN:
554
		case GNOME_VFS_OP_OPEN:
515
			case GNOME_VFS_OP_OPEN_AS_CHANNEL:
555
		case GNOME_VFS_OP_OPEN_AS_CHANNEL:
516
			case GNOME_VFS_OP_CREATE:
556
		case GNOME_VFS_OP_CREATE:
517
			case GNOME_VFS_OP_CREATE_AS_CHANNEL:
557
		case GNOME_VFS_OP_CREATE_AS_CHANNEL:
518
			case GNOME_VFS_OP_CREATE_SYMBOLIC_LINK:
558
		case GNOME_VFS_OP_CREATE_SYMBOLIC_LINK:
519
				if (job->handle) {
559
			/* These operations require special handling, since we
520
					g_mutex_unlock (job->job_lock);
560
			 * may have already succeded in opening a file
521
					handle_cancelled_open (job);
561
			 * descriptor.  We cancel this by closing the file
522
					JOB_DEBUG (("handle cancel open job %u",
562
			 * descriptor.
523
						    GPOINTER_TO_UINT (notify_result->job_handle)));
563
			 */
524
					break;
564
			if (job->handle) {
525
				} /* else drop through */
526
			default:
527
				/* Remove job from the job map. */
528
				_gnome_vfs_async_job_map_remove_job (job);
529
				g_mutex_unlock (job->job_lock);
565
				g_mutex_unlock (job->job_lock);
530
				break;
566
				job_unlocked = TRUE;
567
				fmq_log ("MAIN: dispatch_job_callback(): handling canceled open job %p",
568
					 job);
569
				handle_cancelled_open (job);
570
				JOB_DEBUG (("handle cancel open job %u",
571
					    GPOINTER_TO_UINT (job->job_handle)));
572
			} else
573
				maybe_remove_job = TRUE;
574
575
			break;
576
577
		case GNOME_VFS_OP_CLOSE:
578
		case GNOME_VFS_OP_GET_FILE_INFO:
579
		case GNOME_VFS_OP_SET_FILE_INFO:
580
		case GNOME_VFS_OP_FIND_DIRECTORY:
581
			/* These operations can possibly free the job
582
			 * immediately, since no operations on the handle are
583
			 * possible after it has been cancelled.
584
			 */
585
			fmq_log ("MAIN: Marking job %p for freeing when its canceled ops finish",
586
				 job);
587
			job->free_when_canceled_ops_complete = TRUE;
588
			maybe_remove_job = TRUE;
589
			break;
590
591
		case GNOME_VFS_OP_LOAD_DIRECTORY:
592
			/* Since this operation invokes multiple callbacks, we
593
			 * can only free it when it returns anything other than
594
			 * GNOME_VFS_OK; that's when it is done emitting all the
595
			 * callbacks and thus terminated.
596
			 */
597
			fmq_log ("dispatch_job_callback(): canceled load_directory, result %d",
598
				 (int) notify_result->specifics.load_directory.result);
599
600
			if (notify_result->specifics.load_directory.result == GNOME_VFS_OK)
601
				free_op = FALSE;
602
			else
603
				maybe_remove_job = TRUE;
604
605
			break;
606
607
		default:
608
			/* All other operations require the job to remain alive
609
			 * unless it has to wait for its pending cancellations
610
			 * to finish.
611
			 */
612
			break;
613
		}
614
615
		if (free_op) {
616
			if (job_unlocked) {
617
				g_mutex_lock (job->job_lock);
618
				job_unlocked = FALSE;
531
			}
619
			}
620
621
			job->canceled_ops = g_slist_remove_link (job->canceled_ops, canceled_op_link);
622
			gnome_vfs_op_destroy (notify_result->op);
532
		}
623
		}
533
	
624
534
		_gnome_vfs_async_job_map_unlock ();
625
		_gnome_vfs_job_destroy_notify_result (notify_result, type);
535
		_gnome_vfs_job_destroy_notify_result (notify_result);
626
627
		if (maybe_remove_job) {
628
			if (job_unlocked) {
629
				g_mutex_lock (job->job_lock);
630
				job_unlocked = FALSE;
631
			}
632
633
			if (g_slist_length (job->canceled_ops) != 0) {
634
				maybe_remove_job = FALSE;
635
				fmq_log ("MAIN: Wanted to remove job %p, but it still has pending cancellations",
636
					 job);
637
			} else
638
				fmq_log ("MAIN: Will remove job %p",
639
					 job);
640
		} else {
641
			if (job_unlocked) {
642
				g_mutex_lock (job->job_lock);
643
				job_unlocked = FALSE;
644
			}
645
646
			if (job->free_when_canceled_ops_complete && g_slist_length (job->canceled_ops) == 0) {
647
				maybe_remove_job = TRUE;
648
				fmq_log ("MAIN: will remove job %p; it has no pending cancellations and is marked for destruction",
649
					 job);
650
			}
651
		}
652
653
		if (!job_unlocked)
654
			g_mutex_unlock (job->job_lock);
655
656
		if (maybe_remove_job)
657
			remove_and_free_job (job);
658
536
		return FALSE;
659
		return FALSE;
537
	}
660
	}
538
	
539
		
540
	JOB_DEBUG (("executing callback %u", GPOINTER_TO_UINT (notify_result->job_handle)));	
541
661
542
	switch (notify_result->type) {
662
	JOB_DEBUG (("executing callback %u", GPOINTER_TO_UINT (notify_result->job_handle)));
663
664
	g_assert (job->op == notify_result->op);
665
666
	/* set the job to "no current operation" here so the user callbacks can
667
	 * queue another operation.  Do this for all except
668
	 * GNOME_VFS_OP_LOAD_DIRECTORY, because that one can emit further
669
	 * notifications after the current one.
670
	 */
671
	if (notify_result->op->type != GNOME_VFS_OP_LOAD_DIRECTORY)
672
		job->op = NULL;
673
674
	g_mutex_unlock (job->job_lock);
675
676
	free_op = TRUE;
677
	maybe_remove_job = FALSE;
678
679
	switch (type) {
543
	case GNOME_VFS_OP_CLOSE:
680
	case GNOME_VFS_OP_CLOSE:
544
		dispatch_close_callback (notify_result);
681
		dispatch_close_callback (notify_result);
682
683
		g_mutex_lock (job->job_lock);
684
		fmq_log ("MAIN: Marking job %p for freeing when its canceled ops finish",
685
			 job);
686
		job->free_when_canceled_ops_complete = TRUE;
687
		g_mutex_unlock (job->job_lock);
688
689
		maybe_remove_job = TRUE;
545
		break;
690
		break;
546
	case GNOME_VFS_OP_CREATE:
691
	case GNOME_VFS_OP_CREATE:
547
		dispatch_create_callback (notify_result);
692
		dispatch_create_callback (notify_result);
693
		if (notify_result->specifics.create.result != GNOME_VFS_OK)
694
			maybe_remove_job = TRUE;
548
		break;
695
		break;
549
	case GNOME_VFS_OP_CREATE_AS_CHANNEL:
696
	case GNOME_VFS_OP_CREATE_AS_CHANNEL:
550
		dispatch_create_as_channel_callback (notify_result);
697
		dispatch_create_as_channel_callback (notify_result);
698
		if (notify_result->specifics.create_as_channel.result != GNOME_VFS_OK)
699
			maybe_remove_job = TRUE;
551
		break;
700
		break;
552
	case GNOME_VFS_OP_CREATE_SYMBOLIC_LINK:
701
	case GNOME_VFS_OP_CREATE_SYMBOLIC_LINK:
553
		dispatch_create_callback (notify_result);
702
		dispatch_create_callback (notify_result);
703
		maybe_remove_job = TRUE;
554
		break;
704
		break;
555
	case GNOME_VFS_OP_FIND_DIRECTORY:
705
	case GNOME_VFS_OP_FIND_DIRECTORY:
556
		dispatch_find_directory_callback (notify_result);
706
		dispatch_find_directory_callback (notify_result);
707
		maybe_remove_job = TRUE;
557
		break;
708
		break;
558
	case GNOME_VFS_OP_GET_FILE_INFO:
709
	case GNOME_VFS_OP_GET_FILE_INFO:
559
		dispatch_get_file_info_callback (notify_result);
710
		dispatch_get_file_info_callback (notify_result);
711
		maybe_remove_job = TRUE;
560
		break;
712
		break;
561
	case GNOME_VFS_OP_LOAD_DIRECTORY:
713
	case GNOME_VFS_OP_LOAD_DIRECTORY:
562
		dispatch_load_directory_callback (notify_result);
714
		dispatch_load_directory_callback (notify_result);
715
		/* Since this operation invokes multiple callbacks, we
716
		 * can only free it when it returns anything other than
717
		 * GNOME_VFS_OK; that's when it is done emitting all the
718
		 * callbacks and thus terminated.
719
		 */
720
		if (notify_result->specifics.load_directory.result == GNOME_VFS_OK)
721
			free_op = FALSE;
722
		else {
723
			g_mutex_lock (job->job_lock);
724
			job->op = NULL;
725
			g_mutex_unlock (job->job_lock);
726
727
			maybe_remove_job = TRUE;
728
		}
729
563
		break;
730
		break;
564
	case GNOME_VFS_OP_OPEN:
731
	case GNOME_VFS_OP_OPEN:
565
		dispatch_open_callback (notify_result);
732
		dispatch_open_callback (notify_result);
733
		if (notify_result->specifics.open.result != GNOME_VFS_OK)
734
			maybe_remove_job = TRUE;
566
		break;
735
		break;
567
	case GNOME_VFS_OP_OPEN_AS_CHANNEL:
736
	case GNOME_VFS_OP_OPEN_AS_CHANNEL:
568
		dispatch_open_as_channel_callback (notify_result);
737
		dispatch_open_as_channel_callback (notify_result);
738
		if (notify_result->specifics.open_as_channel.result != GNOME_VFS_OK)
739
			maybe_remove_job = TRUE;
569
		break;
740
		break;
570
	case GNOME_VFS_OP_READ:
741
	case GNOME_VFS_OP_READ:
571
		dispatch_read_callback (notify_result);
742
		dispatch_read_callback (notify_result);
572
		break;
743
		break;
573
	case GNOME_VFS_OP_SET_FILE_INFO:
744
	case GNOME_VFS_OP_SET_FILE_INFO:
574
		dispatch_set_file_info_callback (notify_result);
745
		dispatch_set_file_info_callback (notify_result);
746
		maybe_remove_job = TRUE;
575
		break;
747
		break;
576
	case GNOME_VFS_OP_WRITE:
748
	case GNOME_VFS_OP_WRITE:
577
		dispatch_write_callback (notify_result);
749
		dispatch_write_callback (notify_result);
Lines 588-594 Link Here
588
	}
760
	}
589
761
590
	JOB_DEBUG (("dispatch callback - done %u", GPOINTER_TO_UINT (notify_result->job_handle)));
762
	JOB_DEBUG (("dispatch callback - done %u", GPOINTER_TO_UINT (notify_result->job_handle)));
591
	_gnome_vfs_job_destroy_notify_result (notify_result);
763
764
	if (free_op)
765
		gnome_vfs_op_destroy (notify_result->op);
766
767
	_gnome_vfs_job_destroy_notify_result (notify_result, type);
768
769
	if (maybe_remove_job) {
770
		g_mutex_lock (job->job_lock);
771
772
		if (g_slist_length (job->canceled_ops) != 0) {
773
			maybe_remove_job = FALSE;
774
			fmq_log ("MAIN: Wanted to remove job %p, but it still has pending cancellations",
775
				 job);
776
		} else
777
			fmq_log ("MAIN: Will remove job %p",
778
				 job);
779
780
		g_mutex_unlock (job->job_lock);
781
	} else {
782
		g_mutex_lock (job->job_lock);
783
784
		if (job->free_when_canceled_ops_complete && g_slist_length (job->canceled_ops) == 0) {
785
			maybe_remove_job = TRUE;
786
			fmq_log ("MAIN: will remove job %p; it has no pending cancellations and is marked for destruction",
787
				 job);
788
		}
789
790
		g_mutex_unlock (job->job_lock);
791
	}
792
793
	if (maybe_remove_job)
794
		remove_and_free_job (job);
592
795
593
	return FALSE;
796
	return FALSE;
594
}
797
}
Lines 601-622 Link Here
601
{
804
{
602
	GnomeVFSOp *op;
805
	GnomeVFSOp *op;
603
806
807
	g_mutex_lock (job->job_lock);
808
809
	if (job->op != NULL)
810
		g_error ("Cannot change the current operation of a running job; please cancel it first");
811
604
	op = g_new (GnomeVFSOp, 1);
812
	op = g_new (GnomeVFSOp, 1);
813
	op->job = job;
605
	op->type = type;
814
	op->type = type;
815
	op->canceled = FALSE;
606
	op->callback = callback;
816
	op->callback = callback;
607
	op->callback_data = callback_data;
817
	op->callback_data = callback_data;
608
	op->context = gnome_vfs_context_new ();
818
	op->context = gnome_vfs_context_new ();
609
	op->stack_info = _gnome_vfs_module_callback_get_stack_info ();
819
	op->stack_info = _gnome_vfs_module_callback_get_stack_info ();
610
820
821
	fmq_log ("MAIN: _gnome_vfs_job_set(): job %p, job_handle %p, op %p, op type %d, user_callback %p, user_callback_data %p",
822
		 job,
823
		 job->job_handle,
824
		 op,
825
		 (int) type,
826
		 callback,
827
		 callback_data);
828
611
	g_assert (gnome_vfs_context_get_cancellation (op->context) != NULL);
829
	g_assert (gnome_vfs_context_get_cancellation (op->context) != NULL);
612
830
613
	JOB_DEBUG (("locking access lock %u, op %d", GPOINTER_TO_UINT (job->job_handle), type));
831
	JOB_DEBUG (("locking access lock %u, op %d", GPOINTER_TO_UINT (job->job_handle), type));
614
832
615
	g_mutex_lock (job->job_lock);
616
617
	gnome_vfs_op_destroy (job->op);
618
	job->op = op;
833
	job->op = op;
619
	job->cancelled = FALSE;
620
834
621
	g_mutex_unlock (job->job_lock);
835
	g_mutex_unlock (job->job_lock);
622
836
Lines 643-648 Link Here
643
857
644
	job_count++;
858
	job_count++;
645
859
860
	fmq_log ("_gnome_vfs_job_new(): returning new job %p with op_type %d",
861
		 new_job,
862
		 type);
863
646
	return new_job;
864
	return new_job;
647
}
865
}
648
866
Lines 651-656 Link Here
651
{
869
{
652
	JOB_DEBUG (("destroying job %u", GPOINTER_TO_UINT (job->job_handle)));
870
	JOB_DEBUG (("destroying job %u", GPOINTER_TO_UINT (job->job_handle)));
653
871
872
	fmq_log ("_gnome_vfs_job_destroy(): job %p",
873
		 job);
874
654
	gnome_vfs_op_destroy (job->op);
875
	gnome_vfs_op_destroy (job->op);
655
876
656
	g_mutex_free (job->job_lock);
877
	g_mutex_free (job->job_lock);
Lines 725-731 Link Here
725
	case GNOME_VFS_OP_WRITE:
946
	case GNOME_VFS_OP_WRITE:
726
	case GNOME_VFS_OP_SEEK:
947
	case GNOME_VFS_OP_SEEK:
727
	case GNOME_VFS_OP_CLOSE:
948
	case GNOME_VFS_OP_CLOSE:
728
	case GNOME_VFS_OP_READ_WRITE_DONE:
729
		break;
949
		break;
730
	case GNOME_VFS_OP_FILE_CONTROL:
950
	case GNOME_VFS_OP_FILE_CONTROL:
731
		g_free (op->specifics.file_control.operation);
951
		g_free (op->specifics.file_control.operation);
Lines 738-743 Link Here
738
	
958
	
739
	gnome_vfs_context_free (op->context);
959
	gnome_vfs_context_free (op->context);
740
	_gnome_vfs_module_callback_free_stack_info (op->stack_info);
960
	_gnome_vfs_module_callback_free_stack_info (op->stack_info);
961
962
	memset (op, 0xaa, sizeof (GnomeVFSOp));
741
	
963
	
742
	g_free (op);
964
	g_free (op);
743
}
965
}
Lines 949-989 Link Here
949
/* Job execution.  This is performed by the slave thread.  */
1171
/* Job execution.  This is performed by the slave thread.  */
950
1172
951
static void
1173
static void
952
execute_open (GnomeVFSJob *job)
1174
execute_open (GnomeVFSOp *op)
953
{
1175
{
954
	GnomeVFSResult result;
1176
	GnomeVFSResult result;
955
	GnomeVFSHandle *handle;
1177
	GnomeVFSHandle *handle;
956
	GnomeVFSOpenOp *open_op;
1178
	GnomeVFSOpenOp *open_op;
957
	GnomeVFSNotifyResult *notify_result;
1179
	GnomeVFSNotifyResult *notify_result;
958
1180
959
	open_op = &job->op->specifics.open;
1181
	open_op = &op->specifics.open;
960
1182
961
	if (open_op->uri == NULL) {
1183
	if (open_op->uri == NULL) {
962
		result = GNOME_VFS_ERROR_INVALID_URI;
1184
		result = GNOME_VFS_ERROR_INVALID_URI;
963
	} else {
1185
	} else {
964
		result = gnome_vfs_open_uri_cancellable (&handle, open_op->uri,
1186
		result = gnome_vfs_open_uri_cancellable (&handle, open_op->uri,
965
							  open_op->open_mode,
1187
							  open_op->open_mode,
966
							  job->op->context);
1188
							  op->context);
967
		job->handle = handle;
1189
		op->job->handle = handle;
968
	}
1190
	}
969
	
1191
	
970
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1192
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
971
	notify_result->job_handle = job->job_handle;
1193
	notify_result->op = op;
972
	notify_result->type = job->op->type;
973
	notify_result->specifics.open.result = result;
1194
	notify_result->specifics.open.result = result;
974
	notify_result->specifics.open.callback = (GnomeVFSAsyncOpenCallback) job->op->callback;
975
	notify_result->specifics.open.callback_data = job->op->callback_data;
976
1195
977
	if (result != GNOME_VFS_OK) {
1196
	fmq_log ("WORKER: execute_open(): creating notify_result %p, job_handle %p, job %p, vfs_result %d",
978
		/* if the open failed, just drop the job */
1197
		 notify_result,
979
		job->failed = TRUE;
1198
		 notify_result->op->job->job_handle,
980
	}
1199
		 notify_result->op->job,
981
	
1200
		 (int) result);
982
	job_oneway_notify (job, notify_result);
1201
1202
	job_oneway_notify (notify_result);
983
}
1203
}
984
1204
985
static void
1205
static void
986
execute_open_as_channel (GnomeVFSJob *job)
1206
execute_open_as_channel (GnomeVFSOp *op)
987
{
1207
{
988
	GnomeVFSResult result;
1208
	GnomeVFSResult result;
989
	GnomeVFSHandle *handle;
1209
	GnomeVFSHandle *handle;
Lines 993-999 Link Here
993
	gint pipefd[2];
1213
	gint pipefd[2];
994
	GnomeVFSNotifyResult *notify_result;
1214
	GnomeVFSNotifyResult *notify_result;
995
1215
996
	open_as_channel_op = &job->op->specifics.open_as_channel;
1216
	open_as_channel_op = &op->specifics.open_as_channel;
997
1217
998
	if (open_as_channel_op->uri == NULL) {
1218
	if (open_as_channel_op->uri == NULL) {
999
		result = GNOME_VFS_ERROR_INVALID_URI;
1219
		result = GNOME_VFS_ERROR_INVALID_URI;
Lines 1002-1022 Link Here
1002
			(&handle,
1222
			(&handle,
1003
			 open_as_channel_op->uri,
1223
			 open_as_channel_op->uri,
1004
			 open_as_channel_op->open_mode,
1224
			 open_as_channel_op->open_mode,
1005
			 job->op->context);
1225
			 op->context);
1006
	}
1226
	}
1007
1227
1008
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1228
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1009
	notify_result->job_handle = job->job_handle;
1229
	notify_result->op = op;
1010
	notify_result->type = job->op->type;
1011
	notify_result->specifics.open_as_channel.result = result;
1230
	notify_result->specifics.open_as_channel.result = result;
1012
	notify_result->specifics.open_as_channel.callback =
1013
		(GnomeVFSAsyncOpenAsChannelCallback) job->op->callback;
1014
	notify_result->specifics.open_as_channel.callback_data = job->op->callback_data;
1015
1231
1016
	if (result != GNOME_VFS_OK) {
1232
	if (result != GNOME_VFS_OK) {
1017
		/* if the open failed, just drop the job */
1233
		job_oneway_notify (notify_result);
1018
		job->failed = TRUE;
1019
		job_oneway_notify (job, notify_result);
1020
		return;
1234
		return;
1021
	}
1235
	}
1022
	
1236
	
Lines 1025-1033 Link Here
1025
		g_warning (_("Cannot create pipe for open GIOChannel: %s"),
1239
		g_warning (_("Cannot create pipe for open GIOChannel: %s"),
1026
			   g_strerror (errno));
1240
			   g_strerror (errno));
1027
		notify_result->specifics.open_as_channel.result = GNOME_VFS_ERROR_INTERNAL;
1241
		notify_result->specifics.open_as_channel.result = GNOME_VFS_ERROR_INTERNAL;
1028
		/* if the open failed, just drop the job */
1242
		job_oneway_notify (notify_result);
1029
		job->failed = TRUE;
1030
		job_oneway_notify (job, notify_result);
1031
		return;
1243
		return;
1032
	}
1244
	}
1033
1245
Lines 1054-1080 Link Here
1054
1266
1055
	notify_result->specifics.open_as_channel.result = GNOME_VFS_OK;
1267
	notify_result->specifics.open_as_channel.result = GNOME_VFS_OK;
1056
1268
1057
	job_notify (job, notify_result);
1269
	job_notify (notify_result);
1270
	/* FMQ: who frees notify_result? */
1058
1271
1059
	if (open_mode & GNOME_VFS_OPEN_READ) {
1272
	if (open_mode & GNOME_VFS_OPEN_READ) {
1060
		serve_channel_read (handle, channel_in, channel_out,
1273
		serve_channel_read (handle, channel_in, channel_out,
1061
				    open_as_channel_op->advised_block_size,
1274
				    open_as_channel_op->advised_block_size,
1062
				    job->op->context);
1275
				    op->context);
1063
	} else {
1276
	} else {
1064
		serve_channel_write (handle, channel_in, channel_out,
1277
		serve_channel_write (handle, channel_in, channel_out,
1065
				     job->op->context);
1278
				     op->context);
1066
	}
1279
	}
1067
}
1280
}
1068
1281
1069
static void
1282
static void
1070
execute_create (GnomeVFSJob *job)
1283
execute_create (GnomeVFSOp *op)
1071
{
1284
{
1072
	GnomeVFSResult result;
1285
	GnomeVFSResult result;
1073
	GnomeVFSHandle *handle;
1286
	GnomeVFSHandle *handle;
1074
	GnomeVFSCreateOp *create_op;
1287
	GnomeVFSCreateOp *create_op;
1075
	GnomeVFSNotifyResult *notify_result;
1288
	GnomeVFSNotifyResult *notify_result;
1076
1289
1077
	create_op = &job->op->specifics.create;
1290
	create_op = &op->specifics.create;
1078
1291
1079
	if (create_op->uri == NULL) {
1292
	if (create_op->uri == NULL) {
1080
		result = GNOME_VFS_ERROR_INVALID_URI;
1293
		result = GNOME_VFS_ERROR_INVALID_URI;
Lines 1085-1141 Link Here
1085
			 create_op->open_mode,
1298
			 create_op->open_mode,
1086
			 create_op->exclusive,
1299
			 create_op->exclusive,
1087
			 create_op->perm,
1300
			 create_op->perm,
1088
			 job->op->context);
1301
			 op->context);
1089
		
1302
		
1090
		job->handle = handle;
1303
		op->job->handle = handle;
1091
	}
1304
	}
1092
1305
1093
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1306
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1094
	notify_result->job_handle = job->job_handle;
1307
	notify_result->op = op;
1095
	notify_result->type = job->op->type;
1096
	notify_result->specifics.create.result = result;
1308
	notify_result->specifics.create.result = result;
1097
	notify_result->specifics.create.callback = (GnomeVFSAsyncCreateCallback) job->op->callback;
1098
	notify_result->specifics.create.callback_data = job->op->callback_data;
1099
1309
1100
	if (result != GNOME_VFS_OK) {
1310
	job_oneway_notify (notify_result);
1101
		/* if the open failed, just drop the job */
1102
		job->failed = TRUE;
1103
	}
1104
1105
	job_oneway_notify (job, notify_result);
1106
}
1311
}
1107
1312
1108
static void
1313
static void
1109
execute_create_symbolic_link (GnomeVFSJob *job)
1314
execute_create_symbolic_link (GnomeVFSOp *op)
1110
{
1315
{
1111
	GnomeVFSResult result;
1316
	GnomeVFSResult result;
1112
	GnomeVFSCreateLinkOp *create_op;
1317
	GnomeVFSCreateLinkOp *create_op;
1113
	GnomeVFSNotifyResult *notify_result;
1318
	GnomeVFSNotifyResult *notify_result;
1114
1319
1115
	create_op = &job->op->specifics.create_symbolic_link;
1320
	create_op = &op->specifics.create_symbolic_link;
1116
1321
1117
	result = gnome_vfs_create_symbolic_link_cancellable
1322
	result = gnome_vfs_create_symbolic_link_cancellable
1118
		(create_op->uri,
1323
		(create_op->uri,
1119
		 create_op->uri_reference,
1324
		 create_op->uri_reference,
1120
		 job->op->context);
1325
		 op->context);
1121
1326
1122
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1327
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1123
	notify_result->job_handle = job->job_handle;
1328
	notify_result->op = op;
1124
	notify_result->type = job->op->type;
1125
	notify_result->specifics.create.result = result;
1329
	notify_result->specifics.create.result = result;
1126
	notify_result->specifics.create.callback = (GnomeVFSAsyncCreateCallback) job->op->callback;
1127
	notify_result->specifics.create.callback_data = job->op->callback_data;
1128
1330
1129
	if (result != GNOME_VFS_OK) {
1331
	job_oneway_notify (notify_result);
1130
		/* if the open failed, just drop the job */
1131
		job->failed = TRUE;
1132
	}
1133
1134
	job_oneway_notify (job, notify_result);
1135
}
1332
}
1136
	
1333
	
1137
static void
1334
static void
1138
execute_create_as_channel (GnomeVFSJob *job)
1335
execute_create_as_channel (GnomeVFSOp *op)
1139
{
1336
{
1140
	GnomeVFSResult result;
1337
	GnomeVFSResult result;
1141
	GnomeVFSHandle *handle;
1338
	GnomeVFSHandle *handle;
Lines 1144-1150 Link Here
1144
	gint pipefd[2];
1341
	gint pipefd[2];
1145
	GnomeVFSNotifyResult *notify_result;
1342
	GnomeVFSNotifyResult *notify_result;
1146
1343
1147
	create_as_channel_op = &job->op->specifics.create_as_channel;
1344
	create_as_channel_op = &op->specifics.create_as_channel;
1148
1345
1149
	if (create_as_channel_op->uri == NULL) {
1346
	if (create_as_channel_op->uri == NULL) {
1150
		result = GNOME_VFS_ERROR_INVALID_URI;
1347
		result = GNOME_VFS_ERROR_INVALID_URI;
Lines 1155-1174 Link Here
1155
			 create_as_channel_op->open_mode,
1352
			 create_as_channel_op->open_mode,
1156
                         create_as_channel_op->exclusive,
1353
                         create_as_channel_op->exclusive,
1157
                         create_as_channel_op->perm,
1354
                         create_as_channel_op->perm,
1158
			 job->op->context);
1355
			 op->context);
1159
	}
1356
	}
1160
	
1357
	
1161
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1358
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1162
	notify_result->job_handle = job->job_handle;
1359
	notify_result->op = op;
1163
	notify_result->type = job->op->type;
1164
	notify_result->specifics.create_as_channel.result = result;
1360
	notify_result->specifics.create_as_channel.result = result;
1165
	notify_result->specifics.create_as_channel.callback = (GnomeVFSAsyncCreateAsChannelCallback) job->op->callback;
1166
	notify_result->specifics.create_as_channel.callback_data = job->op->callback_data;
1167
1361
1168
	if (result != GNOME_VFS_OK) {
1362
	if (result != GNOME_VFS_OK) {
1169
		/* if the open failed, just drop the job */
1363
		job_oneway_notify (notify_result);
1170
		job->failed = TRUE;
1171
		job_oneway_notify (job, notify_result);
1172
		return;
1364
		return;
1173
	}
1365
	}
1174
1366
Lines 1176-1184 Link Here
1176
		g_warning (_("Cannot create pipe for open GIOChannel: %s"),
1368
		g_warning (_("Cannot create pipe for open GIOChannel: %s"),
1177
			   g_strerror (errno));
1369
			   g_strerror (errno));
1178
		notify_result->specifics.create_as_channel.result = GNOME_VFS_ERROR_INTERNAL;
1370
		notify_result->specifics.create_as_channel.result = GNOME_VFS_ERROR_INTERNAL;
1179
		/* if the open failed, just drop the job */
1371
		job_oneway_notify (notify_result);
1180
		job->failed = TRUE;
1181
		job_oneway_notify (job, notify_result);
1182
		return;
1372
		return;
1183
	}
1373
	}
1184
	
1374
	
Lines 1192-1315 Link Here
1192
1382
1193
	notify_result->specifics.create_as_channel.channel = channel_out;
1383
	notify_result->specifics.create_as_channel.channel = channel_out;
1194
1384
1195
	job_notify (job, notify_result);
1385
	job_notify (notify_result);
1386
	_gnome_vfs_job_destroy_notify_result (notify_result, notify_result->op->type);
1196
1387
1197
	serve_channel_write (handle, channel_in, channel_out, job->op->context);
1388
	serve_channel_write (handle, channel_in, channel_out, op->context);
1198
}
1389
}
1199
1390
1200
static void
1391
static void
1201
execute_close (GnomeVFSJob *job)
1392
execute_close (GnomeVFSOp *op)
1202
{
1393
{
1203
	GnomeVFSCloseOp *close_op;
1394
	GnomeVFSCloseOp *close_op;
1204
	GnomeVFSNotifyResult *notify_result;
1395
	GnomeVFSNotifyResult *notify_result;
1205
1396
1206
	close_op = &job->op->specifics.close;
1397
	close_op = &op->specifics.close;
1207
1398
1208
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1399
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1209
	notify_result->job_handle = job->job_handle;
1400
	notify_result->op = op;
1210
	notify_result->type = job->op->type;
1401
	notify_result->specifics.close.result = gnome_vfs_close_cancellable (op->job->handle, op->context);
1211
	notify_result->specifics.close.callback = (GnomeVFSAsyncCloseCallback) job->op->callback;
1212
	notify_result->specifics.close.callback_data = job->op->callback_data;
1213
	notify_result->specifics.close.result
1214
		= gnome_vfs_close_cancellable (job->handle, job->op->context);
1215
1402
1216
	job_oneway_notify (job, notify_result);
1403
	job_oneway_notify (notify_result);
1217
}
1404
}
1218
1405
1219
static void
1406
static void
1220
execute_read (GnomeVFSJob *job)
1407
execute_read (GnomeVFSOp *op)
1221
{
1408
{
1222
	GnomeVFSReadOp *read_op;
1409
	GnomeVFSReadOp *read_op;
1223
	GnomeVFSNotifyResult *notify_result;
1410
	GnomeVFSNotifyResult *notify_result;
1224
	
1411
	
1225
	read_op = &job->op->specifics.read;
1412
	read_op = &op->specifics.read;
1226
1413
1227
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1414
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1228
	notify_result->job_handle = job->job_handle;
1415
	notify_result->op = op;
1229
	notify_result->type = job->op->type;
1230
	notify_result->specifics.read.callback = (GnomeVFSAsyncReadCallback) job->op->callback;
1231
	notify_result->specifics.read.callback_data = job->op->callback_data;
1232
	notify_result->specifics.read.buffer = read_op->buffer;
1416
	notify_result->specifics.read.buffer = read_op->buffer;
1233
	notify_result->specifics.read.num_bytes = read_op->num_bytes;
1417
	notify_result->specifics.read.num_bytes = read_op->num_bytes;
1234
	
1418
	
1235
	notify_result->specifics.read.result = gnome_vfs_read_cancellable (job->handle,
1419
	notify_result->specifics.read.result = gnome_vfs_read_cancellable (op->job->handle,
1236
									   read_op->buffer,
1420
									   read_op->buffer,
1237
									   read_op->num_bytes,
1421
									   read_op->num_bytes,
1238
									   &notify_result->specifics.read.bytes_read,
1422
									   &notify_result->specifics.read.bytes_read,
1239
									   job->op->context);
1423
									   op->context);
1240
1424
1241
	job->op->type = GNOME_VFS_OP_READ_WRITE_DONE;
1425
	job_oneway_notify (notify_result);
1242
1243
	job_oneway_notify (job, notify_result);
1244
}
1426
}
1245
1427
1246
static void
1428
static void
1247
execute_write (GnomeVFSJob *job)
1429
execute_write (GnomeVFSOp *op)
1248
{
1430
{
1249
	GnomeVFSWriteOp *write_op;
1431
	GnomeVFSWriteOp *write_op;
1250
	GnomeVFSNotifyResult *notify_result;
1432
	GnomeVFSNotifyResult *notify_result;
1251
	
1433
	
1252
	write_op = &job->op->specifics.write;
1434
	write_op = &op->specifics.write;
1253
1435
1254
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1436
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1255
	notify_result->job_handle = job->job_handle;
1437
	notify_result->op = op;
1256
	notify_result->type = job->op->type;
1257
	notify_result->specifics.write.callback = (GnomeVFSAsyncWriteCallback) job->op->callback;
1258
	notify_result->specifics.write.callback_data = job->op->callback_data;
1259
	notify_result->specifics.write.buffer = write_op->buffer;
1438
	notify_result->specifics.write.buffer = write_op->buffer;
1260
	notify_result->specifics.write.num_bytes = write_op->num_bytes;
1439
	notify_result->specifics.write.num_bytes = write_op->num_bytes;
1261
1440
1262
	notify_result->specifics.write.result = gnome_vfs_write_cancellable (job->handle,
1441
	notify_result->specifics.write.result = gnome_vfs_write_cancellable (op->job->handle,
1263
									     write_op->buffer,
1442
									     write_op->buffer,
1264
									     write_op->num_bytes,
1443
									     write_op->num_bytes,
1265
									     &notify_result->specifics.write.bytes_written,
1444
									     &notify_result->specifics.write.bytes_written,
1266
									     job->op->context);
1445
									     op->context);
1267
1268
	job->op->type = GNOME_VFS_OP_READ_WRITE_DONE;
1269
1446
1270
	job_oneway_notify (job, notify_result);
1447
	job_oneway_notify (notify_result);
1271
}
1448
}
1272
1449
1273
static void
1450
static void
1274
execute_seek (GnomeVFSJob *job)
1451
execute_seek (GnomeVFSOp *op)
1275
{
1452
{
1276
	GnomeVFSResult result;
1453
	GnomeVFSResult result;
1277
	GnomeVFSSeekOp *seek_op;
1454
	GnomeVFSSeekOp *seek_op;
1278
	GnomeVFSNotifyResult *notify_result;
1455
	GnomeVFSNotifyResult *notify_result;
1279
1456
1280
	seek_op = &job->op->specifics.seek;
1457
	seek_op = &op->specifics.seek;
1281
1458
1282
	result = gnome_vfs_seek_cancellable (job->handle,
1459
	result = gnome_vfs_seek_cancellable (op->job->handle,
1283
					     seek_op->whence,
1460
					     seek_op->whence,
1284
					     seek_op->offset,
1461
					     seek_op->offset,
1285
					     job->op->context);
1462
					     op->context);
1286
1463
1287
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1464
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1288
	notify_result->job_handle = job->job_handle;
1465
	notify_result->op = op;
1289
	notify_result->type = job->op->type;
1290
	notify_result->specifics.seek.result = result;
1466
	notify_result->specifics.seek.result = result;
1291
	notify_result->specifics.seek.callback = (GnomeVFSAsyncSeekCallback) job->op->callback;
1292
	notify_result->specifics.seek.callback_data = job->op->callback_data;
1293
1467
1294
	job_oneway_notify (job, notify_result);
1468
	job_oneway_notify (notify_result);
1295
}
1469
}
1296
1470
1297
static void
1471
static void
1298
execute_get_file_info (GnomeVFSJob *job)
1472
execute_get_file_info (GnomeVFSOp *op)
1299
{
1473
{
1300
	GnomeVFSGetFileInfoOp *get_file_info_op;
1474
	GnomeVFSGetFileInfoOp *get_file_info_op;
1301
	GList *p;
1475
	GList *p;
1302
	GnomeVFSGetFileInfoResult *result_item;
1476
	GnomeVFSGetFileInfoResult *result_item;
1303
	GnomeVFSNotifyResult *notify_result;
1477
	GnomeVFSNotifyResult *notify_result;
1304
1478
1305
	get_file_info_op = &job->op->specifics.get_file_info;
1479
	get_file_info_op = &op->specifics.get_file_info;
1306
1480
1307
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1481
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1308
	notify_result->job_handle = job->job_handle;
1482
	notify_result->op = op;
1309
	notify_result->type = job->op->type;
1310
	notify_result->specifics.get_file_info.callback =
1311
		(GnomeVFSAsyncGetFileInfoCallback) job->op->callback;
1312
	notify_result->specifics.get_file_info.callback_data = job->op->callback_data;
1313
1483
1314
	for (p = get_file_info_op->uris; p != NULL; p = p->next) {
1484
	for (p = get_file_info_op->uris; p != NULL; p = p->next) {
1315
		result_item = g_new (GnomeVFSGetFileInfoResult, 1);
1485
		result_item = g_new (GnomeVFSGetFileInfoResult, 1);
Lines 1321-1327 Link Here
1321
			(result_item->uri,
1491
			(result_item->uri,
1322
			 result_item->file_info,
1492
			 result_item->file_info,
1323
			 get_file_info_op->options,
1493
			 get_file_info_op->options,
1324
			 job->op->context);
1494
			 op->context);
1325
1495
1326
		notify_result->specifics.get_file_info.result_list =
1496
		notify_result->specifics.get_file_info.result_list =
1327
			g_list_prepend (notify_result->specifics.get_file_info.result_list, result_item);
1497
			g_list_prepend (notify_result->specifics.get_file_info.result_list, result_item);
Lines 1329-1358 Link Here
1329
	notify_result->specifics.get_file_info.result_list =
1499
	notify_result->specifics.get_file_info.result_list =
1330
		g_list_reverse (notify_result->specifics.get_file_info.result_list);
1500
		g_list_reverse (notify_result->specifics.get_file_info.result_list);
1331
1501
1332
	job_oneway_notify (job, notify_result);
1502
	job_oneway_notify (notify_result);
1333
}
1503
}
1334
1504
1335
static void
1505
static void
1336
execute_set_file_info (GnomeVFSJob *job)
1506
execute_set_file_info (GnomeVFSOp *op)
1337
{
1507
{
1338
	GnomeVFSSetFileInfoOp *set_file_info_op;
1508
	GnomeVFSSetFileInfoOp *set_file_info_op;
1339
	GnomeVFSURI *parent_uri, *uri_after;
1509
	GnomeVFSURI *parent_uri, *uri_after;
1340
	GnomeVFSNotifyResult *notify_result;
1510
	GnomeVFSNotifyResult *notify_result;
1341
1511
1342
	set_file_info_op = &job->op->specifics.set_file_info;
1512
	set_file_info_op = &op->specifics.set_file_info;
1343
1513
1344
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1514
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1345
	notify_result->job_handle = job->job_handle;
1515
	notify_result->op = op;
1346
	notify_result->type = job->op->type;
1347
	notify_result->specifics.set_file_info.callback =
1348
		(GnomeVFSAsyncSetFileInfoCallback) job->op->callback;
1349
	notify_result->specifics.set_file_info.callback_data =
1350
		job->op->callback_data;
1351
1352
	notify_result->specifics.set_file_info.set_file_info_result =
1516
	notify_result->specifics.set_file_info.set_file_info_result =
1353
		gnome_vfs_set_file_info_cancellable (set_file_info_op->uri,
1517
		gnome_vfs_set_file_info_cancellable (set_file_info_op->uri,
1354
			set_file_info_op->info, set_file_info_op->mask,
1518
			set_file_info_op->info, set_file_info_op->mask,
1355
		 	job->op->context);
1519
		 	op->context);
1356
1520
1357
	/* Get the new URI after the set_file_info. The name may have
1521
	/* Get the new URI after the set_file_info. The name may have
1358
	 * changed.
1522
	 * changed.
Lines 1382-1410 Link Here
1382
			(uri_after,
1546
			(uri_after,
1383
			 notify_result->specifics.set_file_info.info,
1547
			 notify_result->specifics.set_file_info.info,
1384
			 set_file_info_op->options,
1548
			 set_file_info_op->options,
1385
			 job->op->context);
1549
			 op->context);
1386
		gnome_vfs_uri_unref (uri_after);
1550
		gnome_vfs_uri_unref (uri_after);
1387
	}
1551
	}
1388
1552
1389
	job_oneway_notify (job, notify_result);
1553
	job_oneway_notify (notify_result);
1390
}
1554
}
1391
1555
1392
static void
1556
static void
1393
execute_find_directory (GnomeVFSJob *job)
1557
execute_find_directory (GnomeVFSOp *op)
1394
{
1558
{
1395
	GnomeVFSFindDirectoryOp *find_directory_op;
1559
	GnomeVFSFindDirectoryOp *find_directory_op;
1396
	GList *p;
1560
	GList *p;
1397
	GnomeVFSFindDirectoryResult *result_item;
1561
	GnomeVFSFindDirectoryResult *result_item;
1398
	GnomeVFSNotifyResult *notify_result;
1562
	GnomeVFSNotifyResult *notify_result;
1563
	gboolean cancelled;
1399
1564
1400
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1565
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1401
	notify_result->job_handle = job->job_handle;
1566
	notify_result->op = op;
1402
	notify_result->type = job->op->type;
1567
1403
	notify_result->specifics.find_directory.callback
1568
	find_directory_op = &op->specifics.find_directory;
1404
		= (GnomeVFSAsyncFindDirectoryCallback) job->op->callback;
1569
1405
	notify_result->specifics.find_directory.callback_data = job->op->callback_data;
1570
	cancelled = FALSE;
1406
1571
1407
	find_directory_op = &job->op->specifics.find_directory;
1408
	for (p = find_directory_op->uris; p != NULL; p = p->next) {
1572
	for (p = find_directory_op->uris; p != NULL; p = p->next) {
1409
		result_item = g_new0 (GnomeVFSFindDirectoryResult, 1);
1573
		result_item = g_new0 (GnomeVFSFindDirectoryResult, 1);
1410
1574
Lines 1415-1433 Link Here
1415
			 find_directory_op->create_if_needed,
1579
			 find_directory_op->create_if_needed,
1416
			 find_directory_op->find_if_needed,
1580
			 find_directory_op->find_if_needed,
1417
			 find_directory_op->permissions,
1581
			 find_directory_op->permissions,
1418
			 job->op->context);
1582
			 op->context);
1583
1584
		if (result_item->result == GNOME_VFS_ERROR_CANCELLED)
1585
			cancelled = TRUE;
1586
1419
		notify_result->specifics.find_directory.result_list =
1587
		notify_result->specifics.find_directory.result_list =
1420
			g_list_prepend (notify_result->specifics.find_directory.result_list, result_item);
1588
			g_list_prepend (notify_result->specifics.find_directory.result_list, result_item);
1421
	}
1589
	}
1422
1590
1423
	notify_result->specifics.find_directory.result_list =
1591
	notify_result->specifics.find_directory.result_list =
1424
		g_list_reverse (notify_result->specifics.find_directory.result_list);
1592
		g_list_reverse (notify_result->specifics.find_directory.result_list);
1593
1594
	if (cancelled)
1595
		notify_result->specifics.find_directory.result = GNOME_VFS_ERROR_CANCELLED;
1596
	else
1597
		notify_result->specifics.find_directory.result = GNOME_VFS_OK;
1425
	
1598
	
1426
	job_oneway_notify (job, notify_result);
1599
	job_oneway_notify (notify_result);
1427
}
1600
}
1428
1601
1429
static void
1602
static void
1430
load_directory_details (GnomeVFSJob *job)
1603
execute_load_directory (GnomeVFSOp *op)
1431
{
1604
{
1432
	GnomeVFSLoadDirectoryOp *load_directory_op;
1605
	GnomeVFSLoadDirectoryOp *load_directory_op;
1433
	GnomeVFSDirectoryHandle *handle;
1606
	GnomeVFSDirectoryHandle *handle;
Lines 1437-1444 Link Here
1437
	guint count;
1610
	guint count;
1438
	GnomeVFSNotifyResult *notify_result;
1611
	GnomeVFSNotifyResult *notify_result;
1439
1612
1440
	JOB_DEBUG (("%u", GPOINTER_TO_UINT (job->job_handle)));
1613
	JOB_DEBUG (("%u", GPOINTER_TO_UINT (op->job->job_handle)));
1441
	load_directory_op = &job->op->specifics.load_directory;
1614
	load_directory_op = &op->specifics.load_directory;
1442
	
1615
	
1443
	if (load_directory_op->uri == NULL) {
1616
	if (load_directory_op->uri == NULL) {
1444
		result = GNOME_VFS_ERROR_INVALID_URI;
1617
		result = GNOME_VFS_ERROR_INVALID_URI;
Lines 1447-1464 Link Here
1447
			(&handle,
1620
			(&handle,
1448
			 load_directory_op->uri,
1621
			 load_directory_op->uri,
1449
			 load_directory_op->options,
1622
			 load_directory_op->options,
1450
			 job->op->context);
1623
			 op->context);
1451
	}
1624
	}
1452
1625
1453
	if (result != GNOME_VFS_OK) {
1626
	if (result != GNOME_VFS_OK) {
1454
		notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1627
		notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1455
		notify_result->job_handle = job->job_handle;
1628
		notify_result->op = op;
1456
		notify_result->type = job->op->type;
1457
		notify_result->specifics.load_directory.result = result;
1629
		notify_result->specifics.load_directory.result = result;
1458
		notify_result->specifics.load_directory.callback =
1630
		job_oneway_notify (notify_result);
1459
			(GnomeVFSAsyncDirectoryLoadCallback) job->op->callback;
1460
		notify_result->specifics.load_directory.callback_data = job->op->callback_data;
1461
		job_oneway_notify (job, notify_result);
1462
		return;
1631
		return;
1463
	}
1632
	}
1464
1633
Lines 1466-1484 Link Here
1466
1635
1467
	count = 0;
1636
	count = 0;
1468
	while (1) {
1637
	while (1) {
1469
		if (gnome_vfs_context_check_cancellation (job->op->context)) {
1638
		if (gnome_vfs_context_check_cancellation (op->context)) {
1470
			JOB_DEBUG (("cancelled, bailing %u",
1639
			JOB_DEBUG (("cancelled, bailing %u",
1471
				    GPOINTER_TO_UINT (job->job_handle)));
1640
				    GPOINTER_TO_UINT (op->job->job_handle)));
1472
			gnome_vfs_file_info_list_free (directory_list);
1641
			gnome_vfs_file_info_list_free (directory_list);
1473
			directory_list = NULL;
1642
			directory_list = NULL;
1474
			result = GNOME_VFS_ERROR_CANCELLED;
1643
			result = GNOME_VFS_ERROR_CANCELLED;
1644
1645
			notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1646
			notify_result->op = op;
1647
			notify_result->specifics.load_directory.result = result;
1648
			job_oneway_notify (notify_result);
1649
1475
			break;
1650
			break;
1476
		}
1651
		}
1477
1652
1478
		info = gnome_vfs_file_info_new ();
1653
		info = gnome_vfs_file_info_new ();
1479
1654
1480
		result = gnome_vfs_directory_read_next_cancellable
1655
		result = gnome_vfs_directory_read_next_cancellable (handle, info, op->context);
1481
			(handle, info, job->op->context);
1482
1656
1483
		if (result == GNOME_VFS_OK) {
1657
		if (result == GNOME_VFS_OK) {
1484
			directory_list = g_list_prepend (directory_list, info);
1658
			directory_list = g_list_prepend (directory_list, info);
Lines 1491-1508 Link Here
1491
			|| result != GNOME_VFS_OK) {
1665
			|| result != GNOME_VFS_OK) {
1492
1666
1493
			notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1667
			notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1494
			notify_result->job_handle = job->job_handle;
1668
			notify_result->op = op;
1495
			notify_result->type = job->op->type;
1496
			notify_result->specifics.load_directory.result = result;
1669
			notify_result->specifics.load_directory.result = result;
1497
			notify_result->specifics.load_directory.entries_read = count;
1670
			notify_result->specifics.load_directory.entries_read = count;
1498
			notify_result->specifics.load_directory.list = 
1671
			notify_result->specifics.load_directory.list = 
1499
				g_list_reverse (directory_list);
1672
				g_list_reverse (directory_list);
1500
			notify_result->specifics.load_directory.callback =
1501
				(GnomeVFSAsyncDirectoryLoadCallback) job->op->callback;
1502
			notify_result->specifics.load_directory.callback_data =
1503
				job->op->callback_data;
1504
1673
1505
			job_oneway_notify (job, notify_result);
1674
			job_oneway_notify (notify_result);
1675
			fmq_log ("load_directory_details(): called job_oneway_notify() result %d",
1676
				 (int) notify_result->specifics.load_directory.result);
1506
1677
1507
			count = 0;
1678
			count = 0;
1508
			directory_list = NULL;
1679
			directory_list = NULL;
Lines 1517-1565 Link Here
1517
	gnome_vfs_directory_close (handle);
1688
	gnome_vfs_directory_close (handle);
1518
}
1689
}
1519
1690
1520
static void
1521
execute_load_directory (GnomeVFSJob *job)
1522
{
1523
	GnomeVFSLoadDirectoryOp *load_directory_op;
1524
1525
	load_directory_op = &job->op->specifics.load_directory;
1526
1527
	load_directory_details (job);
1528
}
1529
1530
static gint
1691
static gint
1531
xfer_callback (GnomeVFSXferProgressInfo *info,
1692
xfer_callback (GnomeVFSXferProgressInfo *info,
1532
	       gpointer data)
1693
	       gpointer data)
1533
{
1694
{
1534
	GnomeVFSJob *job;
1695
	GnomeVFSOp *op;
1535
	GnomeVFSNotifyResult notify_result;
1696
	GnomeVFSNotifyResult notify_result;
1536
1697
1537
	job = (GnomeVFSJob *) data;
1698
	op = (GnomeVFSOp *) data;
1538
1699
1539
	/* xfer is fully synchronous, just allocate the notify result struct on the stack */
1700
	/* xfer is fully synchronous, just allocate the notify result struct on the stack */
1540
	notify_result.job_handle = job->job_handle;
1701
	memset (&notify_result, 0, sizeof (notify_result));
1541
	notify_result.callback_id = 0;
1702
	notify_result.op = op;
1542
	notify_result.cancelled = FALSE;
1543
	notify_result.type = job->op->type;
1544
	notify_result.specifics.xfer.progress_info = info;
1703
	notify_result.specifics.xfer.progress_info = info;
1545
	notify_result.specifics.xfer.callback = (GnomeVFSAsyncXferProgressCallback) job->op->callback;
1546
	notify_result.specifics.xfer.callback_data = job->op->callback_data;
1547
1704
1548
	job_notify (job, &notify_result);
1705
	job_notify (&notify_result);
1549
1706
1550
	/* Pass the value returned from the callback in the master thread.  */
1707
	/* Pass the value returned from the callback in the master thread.  */
1551
	return notify_result.specifics.xfer.reply;
1708
	return notify_result.specifics.xfer.reply;
1552
}
1709
}
1553
1710
1554
static void
1711
static void
1555
execute_xfer (GnomeVFSJob *job)
1712
execute_xfer (GnomeVFSOp *op)
1556
{
1713
{
1557
	GnomeVFSXferOp *xfer_op;
1714
	GnomeVFSXferOp *xfer_op;
1558
	GnomeVFSResult result;
1715
	GnomeVFSResult result;
1559
	GnomeVFSXferProgressInfo info;
1716
	GnomeVFSXferProgressInfo info;
1560
	GnomeVFSNotifyResult notify_result;
1717
	GnomeVFSNotifyResult notify_result;
1561
1718
1562
	xfer_op = &job->op->specifics.xfer;
1719
	xfer_op = &op->specifics.xfer;
1563
1720
1564
	result = _gnome_vfs_xfer_private (xfer_op->source_uri_list,
1721
	result = _gnome_vfs_xfer_private (xfer_op->source_uri_list,
1565
					 xfer_op->target_uri_list,
1722
					 xfer_op->target_uri_list,
Lines 1567-1573 Link Here
1567
					 xfer_op->error_mode,
1724
					 xfer_op->error_mode,
1568
					 xfer_op->overwrite_mode,
1725
					 xfer_op->overwrite_mode,
1569
					 xfer_callback,
1726
					 xfer_callback,
1570
					 job,
1727
					 op,
1571
					 xfer_op->progress_sync_callback,
1728
					 xfer_op->progress_sync_callback,
1572
					 xfer_op->sync_callback_data);
1729
					 xfer_op->sync_callback_data);
1573
1730
Lines 1588-1718 Link Here
1588
		info.bytes_copied = 0;
1745
		info.bytes_copied = 0;
1589
		info.total_bytes_copied = 0;
1746
		info.total_bytes_copied = 0;
1590
1747
1591
		notify_result.job_handle = job->job_handle;
1748
		memset (&notify_result, 0, sizeof (notify_result));
1592
		notify_result.callback_id = 0;
1749
		notify_result.op = op;
1593
		notify_result.cancelled = FALSE;
1594
		notify_result.type = job->op->type;
1595
		notify_result.specifics.xfer.progress_info = &info;
1750
		notify_result.specifics.xfer.progress_info = &info;
1596
		notify_result.specifics.xfer.callback = (GnomeVFSAsyncXferProgressCallback) job->op->callback;
1597
		notify_result.specifics.xfer.callback_data = job->op->callback_data;
1598
1751
1599
		job_notify (job, &notify_result);
1752
		job_notify (&notify_result);
1600
	}
1753
	}
1601
}
1754
}
1602
1755
1603
static void
1756
static void
1604
execute_file_control (GnomeVFSJob *job)
1757
execute_file_control (GnomeVFSOp *op)
1605
{
1758
{
1606
	GnomeVFSFileControlOp *file_control_op;
1759
	GnomeVFSFileControlOp *file_control_op;
1607
	GnomeVFSNotifyResult *notify_result;
1760
	GnomeVFSNotifyResult *notify_result;
1608
	
1761
	
1609
	file_control_op = &job->op->specifics.file_control;
1762
	file_control_op = &op->specifics.file_control;
1610
1763
1611
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1764
	notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1612
	notify_result->job_handle = job->job_handle;
1765
	notify_result->op = op;
1613
	notify_result->type = job->op->type;
1614
	notify_result->specifics.file_control.callback = (GnomeVFSAsyncFileControlCallback) job->op->callback;
1615
	notify_result->specifics.file_control.callback_data = job->op->callback_data;
1616
	notify_result->specifics.file_control.operation_data = file_control_op->operation_data;
1766
	notify_result->specifics.file_control.operation_data = file_control_op->operation_data;
1617
	notify_result->specifics.file_control.operation_data_destroy_func = file_control_op->operation_data_destroy_func;
1767
	notify_result->specifics.file_control.operation_data_destroy_func = file_control_op->operation_data_destroy_func;
1618
	
1768
	
1619
	notify_result->specifics.file_control.result = gnome_vfs_file_control_cancellable (job->handle,
1769
	notify_result->specifics.file_control.result = gnome_vfs_file_control_cancellable (op->job->handle,
1620
											   file_control_op->operation,
1770
											   file_control_op->operation,
1621
											   file_control_op->operation_data,
1771
											   file_control_op->operation_data,
1622
											   job->op->context);
1772
											   op->context);
1623
1773
1624
	job->op->type = GNOME_VFS_OP_FILE_CONTROL;
1774
	job_oneway_notify (notify_result);
1625
1626
	job_oneway_notify (job, notify_result);
1627
}
1775
}
1628
1776
1629
1630
/*
1777
/*
1631
 * _gnome_vfs_job_execute:
1778
 * _gnome_vfs_job_execute:
1632
 * @job: the job to execute
1779
 * @op: the operation to execute
1633
 * 
1780
 * 
1634
 *   This function is called by the slave thread to execute
1781
 *   This function is called by the slave thread to execute
1635
 * the job - all work performed by a thread starts here.
1782
 * the job - all work performed by a thread starts here.
1636
 */
1783
 */
1637
void
1784
void
1638
_gnome_vfs_job_execute (GnomeVFSJob *job)
1785
_gnome_vfs_job_execute (GnomeVFSOp *op)
1639
{
1786
{
1640
	guint id;
1787
	JOB_DEBUG (("exec job %u", GPOINTER_TO_UINT (op->job->job_handle)));
1641
1788
1642
	id = GPOINTER_TO_UINT (job->job_handle);
1789
	fmq_log ("WORKER: _gnome_vfs_job_execute(): job %p, job->cancelled = %d",
1790
		 op->job,
1791
		 (int) op->canceled);
1643
1792
1644
	JOB_DEBUG (("exec job %u", id));
1793
	if (!op->canceled) {
1794
		set_current_op (op);
1645
1795
1646
	if (!job->cancelled) {
1796
		JOB_DEBUG (("executing %u %d type %s", GPOINTER_TO_UINT (op->job->job_handle), op->type,
1647
		set_current_job (job);
1797
			    JOB_DEBUG_TYPE (op->type)));
1648
1798
1649
		JOB_DEBUG (("executing %u %d type %s", id, job->op->type,
1799
		switch (op->type) {
1650
			    JOB_DEBUG_TYPE (job->op->type)));
1651
1652
		switch (job->op->type) {
1653
		case GNOME_VFS_OP_OPEN:
1800
		case GNOME_VFS_OP_OPEN:
1654
			execute_open (job);
1801
			execute_open (op);
1655
			break;
1802
			break;
1656
		case GNOME_VFS_OP_OPEN_AS_CHANNEL:
1803
		case GNOME_VFS_OP_OPEN_AS_CHANNEL:
1657
			execute_open_as_channel (job);
1804
			execute_open_as_channel (op);
1658
			break;
1805
			break;
1659
		case GNOME_VFS_OP_CREATE:
1806
		case GNOME_VFS_OP_CREATE:
1660
			execute_create (job);
1807
			execute_create (op);
1661
			break;
1808
			break;
1662
		case GNOME_VFS_OP_CREATE_AS_CHANNEL:
1809
		case GNOME_VFS_OP_CREATE_AS_CHANNEL:
1663
			execute_create_as_channel (job);
1810
			execute_create_as_channel (op);
1664
			break;
1811
			break;
1665
		case GNOME_VFS_OP_CREATE_SYMBOLIC_LINK:
1812
		case GNOME_VFS_OP_CREATE_SYMBOLIC_LINK:
1666
			execute_create_symbolic_link (job);
1813
			execute_create_symbolic_link (op);
1667
			break;
1814
			break;
1668
		case GNOME_VFS_OP_CLOSE:
1815
		case GNOME_VFS_OP_CLOSE:
1669
			execute_close (job);
1816
			execute_close (op);
1670
			break;
1817
			break;
1671
		case GNOME_VFS_OP_READ:
1818
		case GNOME_VFS_OP_READ:
1672
			execute_read (job);
1819
			execute_read (op);
1673
			break;
1820
			break;
1674
		case GNOME_VFS_OP_WRITE:
1821
		case GNOME_VFS_OP_WRITE:
1675
			execute_write (job);
1822
			execute_write (op);
1676
			break;
1823
			break;
1677
		case GNOME_VFS_OP_SEEK:
1824
		case GNOME_VFS_OP_SEEK:
1678
			execute_seek (job);
1825
			execute_seek (op);
1679
			break;
1826
			break;
1680
		case GNOME_VFS_OP_LOAD_DIRECTORY:
1827
		case GNOME_VFS_OP_LOAD_DIRECTORY:
1681
			execute_load_directory (job);
1828
			execute_load_directory (op);
1682
			break;
1829
			break;
1683
		case GNOME_VFS_OP_FIND_DIRECTORY:
1830
		case GNOME_VFS_OP_FIND_DIRECTORY:
1684
			execute_find_directory (job);
1831
			execute_find_directory (op);
1685
			break;
1832
			break;
1686
		case GNOME_VFS_OP_XFER:
1833
		case GNOME_VFS_OP_XFER:
1687
			execute_xfer (job);
1834
			execute_xfer (op);
1688
			break;
1835
			break;
1689
		case GNOME_VFS_OP_GET_FILE_INFO:
1836
		case GNOME_VFS_OP_GET_FILE_INFO:
1690
			execute_get_file_info (job);
1837
			execute_get_file_info (op);
1691
			break;
1838
			break;
1692
		case GNOME_VFS_OP_SET_FILE_INFO:
1839
		case GNOME_VFS_OP_SET_FILE_INFO:
1693
			execute_set_file_info (job);
1840
			execute_set_file_info (op);
1694
			break;
1841
			break;
1695
		case GNOME_VFS_OP_FILE_CONTROL:
1842
		case GNOME_VFS_OP_FILE_CONTROL:
1696
			execute_file_control (job);
1843
			execute_file_control (op);
1697
			break;
1844
			break;
1698
		default:
1845
		default:
1699
			g_warning (_("Unknown job kind %u"), job->op->type);
1846
			g_warning (_("Unknown job kind %u"), op->type);
1700
			break;
1847
			break;
1701
		}
1848
		}
1702
		/* NB. 'job' is quite probably invalid now */
1849
1703
		clear_current_job ();
1850
		clear_current_op ();
1704
	} else {
1851
	} else {
1705
		switch (job->op->type) {
1852
		GnomeVFSNotifyResult *notify_result;
1706
		case GNOME_VFS_OP_READ:
1853
1707
		case GNOME_VFS_OP_WRITE:
1854
		notify_result = g_new0 (GnomeVFSNotifyResult, 1);
1708
			job->op->type = GNOME_VFS_OP_READ_WRITE_DONE;
1855
		notify_result->op = op;
1709
			break;
1856
1710
		default:
1857
		/* Since LOAD_DIRECTORY can emit multiple notifications, we
1711
			break;
1858
		 * really need to know about its result, as the last
1712
		}
1859
		 * notification for it is identified by !GNOME_VFS_OK.  It's not
1860
		 * enough to test op->canceled.
1861
		 */
1862
		if (op->type == GNOME_VFS_OP_LOAD_DIRECTORY)
1863
			notify_result->specifics.load_directory.result = GNOME_VFS_ERROR_CANCELLED;
1864
1865
		job_oneway_notify (notify_result);
1713
	}
1866
	}
1714
	
1867
	
1715
	JOB_DEBUG (("done job %u", id));
1868
	JOB_DEBUG (("done job %u", GPOINTER_TO_UINT (op->job->job_handle)));
1716
}
1869
}
1717
1870
1718
void
1871
void
Lines 1721-1757 Link Here
1721
	GnomeVFSCancellation *cancellation;
1874
	GnomeVFSCancellation *cancellation;
1722
1875
1723
	JOB_DEBUG (("%u", GPOINTER_TO_UINT (job->job_handle)));
1876
	JOB_DEBUG (("%u", GPOINTER_TO_UINT (job->job_handle)));
1724
	
1877
1878
	g_mutex_lock (job->job_lock);
1725
	cancellation = gnome_vfs_context_get_cancellation (job->op->context);
1879
	cancellation = gnome_vfs_context_get_cancellation (job->op->context);
1880
	g_mutex_unlock (job->job_lock);
1881
1882
	fmq_log ("MAIN: _gnome_vfs_job_module_cancel(): canceling cancellation %p of job %p",
1883
		 cancellation,
1884
		 job);
1726
	if (cancellation != NULL) {
1885
	if (cancellation != NULL) {
1727
		JOB_DEBUG (("cancelling %u", GPOINTER_TO_UINT (job->job_handle)));
1886
		JOB_DEBUG (("cancelling %u", GPOINTER_TO_UINT (job->job_handle)));
1728
		gnome_vfs_cancellation_cancel (cancellation);
1887
		gnome_vfs_cancellation_cancel (cancellation);
1729
	}
1888
	}
1730
1731
#ifdef OLD_CONTEXT_DEPRECATED	
1732
	gnome_vfs_context_emit_message (job->op->context, _("Operation stopped"));
1733
#endif /* OLD_CONTEXT_DEPRECATED */
1734
1735
	/* Since we are cancelling, we won't have anyone respond to notifications;
1736
	 * set the expectations right.
1737
	 */
1738
	JOB_DEBUG (("done %u", GPOINTER_TO_UINT (job->job_handle)));
1739
}
1889
}
1740
1890
1741
static void
1891
static void
1742
set_current_job (GnomeVFSJob *job)
1892
set_current_op (GnomeVFSOp *op)
1743
{
1893
{
1744
	/* There shouldn't have been anything here. */
1894
	/* There shouldn't have been anything here. */
1745
	g_assert (g_static_private_get (&job_private) == NULL);
1895
	g_assert (g_static_private_get (&job_private) == NULL);
1746
1896
1747
	g_static_private_set (&job_private, job, NULL);
1897
	g_static_private_set (&job_private, op, NULL);
1748
1898
1749
	_gnome_vfs_module_callback_use_stack_info (job->op->stack_info);
1899
	_gnome_vfs_module_callback_use_stack_info (op->stack_info);
1750
	_gnome_vfs_module_callback_set_in_async_thread (TRUE);
1900
	_gnome_vfs_module_callback_set_in_async_thread (TRUE);
1751
}
1901
}
1752
1902
1753
static void
1903
static void
1754
clear_current_job (void)
1904
clear_current_op (void)
1755
{
1905
{
1756
	g_static_private_set (&job_private, NULL, NULL);
1906
	g_static_private_set (&job_private, NULL, NULL);
1757
1907
Lines 1761-1774 Link Here
1761
void
1911
void
1762
_gnome_vfs_get_current_context (GnomeVFSContext **context)
1912
_gnome_vfs_get_current_context (GnomeVFSContext **context)
1763
{
1913
{
1764
	GnomeVFSJob *job;
1914
	GnomeVFSOp *op;
1765
	
1915
	
1766
	g_return_if_fail (context != NULL);
1916
	g_return_if_fail (context != NULL);
1767
1917
1768
	job = g_static_private_get (&job_private);
1918
	op = g_static_private_get (&job_private);
1769
1919
1770
	if (job != NULL) {
1920
	if (op != NULL) {
1771
		*context = job->op->context;
1921
		*context = op->context;
1772
	} else {
1922
	} else {
1773
		*context = NULL;
1923
		*context = NULL;
1774
	}
1924
	}
Lines 1782-1799 Link Here
1782
				    GnomeVFSModuleCallbackResponse response,
1932
				    GnomeVFSModuleCallbackResponse response,
1783
				    gpointer response_data)
1933
				    gpointer response_data)
1784
{
1934
{
1785
	GnomeVFSJob *job;
1935
	GnomeVFSOp *op;
1786
	GnomeVFSNotifyResult notify_result;
1936
	GnomeVFSNotifyResult notify_result;
1787
1937
1788
	job = g_static_private_get (&job_private);
1938
	op = g_static_private_get (&job_private);
1789
1939
1790
	g_return_if_fail (job != NULL);
1940
	g_return_if_fail (op != NULL);
1791
1941
1792
	memset (&notify_result, 0, sizeof (notify_result));
1942
	memset (&notify_result, 0, sizeof (notify_result));
1793
1943
1794
	notify_result.job_handle = job->job_handle;
1944
	notify_result.op = op;
1795
1945
1796
	notify_result.type = GNOME_VFS_OP_MODULE_CALLBACK;
1946
	notify_result.is_module_callback = TRUE;
1797
1947
1798
	notify_result.specifics.callback.callback 	= callback;
1948
	notify_result.specifics.callback.callback 	= callback;
1799
	notify_result.specifics.callback.user_data 	= user_data;
1949
	notify_result.specifics.callback.user_data 	= user_data;
Lines 1806-1810 Link Here
1806
	notify_result.specifics.callback.response	= response;
1956
	notify_result.specifics.callback.response	= response;
1807
	notify_result.specifics.callback.response_data 	= response_data;
1957
	notify_result.specifics.callback.response_data 	= response_data;
1808
1958
1809
	job_notify (job, &notify_result);
1959
	job_notify (&notify_result);
1810
}
1960
}

Return to bug 114710