1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Alexander Larsson <alexl@redhat.com>
24 #include "gfileenumerator.h"
25 #include "gioscheduler.h"
26 #include "gasynchelper.h"
27 #include "gsimpleasyncresult.h"
31 * SECTION:gfileenumerator
32 * @short_description: Enumerated Files Routines
37 G_DEFINE_TYPE (GFileEnumerator, g_file_enumerator, G_TYPE_OBJECT);
39 struct _GFileEnumeratorPrivate {
40 /* TODO: Should be public for subclasses? */
43 GAsyncReadyCallback outstanding_callback;
44 GError *outstanding_error;
47 static void g_file_enumerator_real_next_files_async (GFileEnumerator *enumerator,
50 GCancellable *cancellable,
51 GAsyncReadyCallback callback,
53 static GList * g_file_enumerator_real_next_files_finish (GFileEnumerator *enumerator,
56 static void g_file_enumerator_real_close_async (GFileEnumerator *enumerator,
58 GCancellable *cancellable,
59 GAsyncReadyCallback callback,
61 static gboolean g_file_enumerator_real_close_finish (GFileEnumerator *enumerator,
66 g_file_enumerator_finalize (GObject *object)
68 GFileEnumerator *enumerator;
70 enumerator = G_FILE_ENUMERATOR (object);
72 if (!enumerator->priv->closed)
73 g_file_enumerator_close (enumerator, NULL, NULL);
75 if (G_OBJECT_CLASS (g_file_enumerator_parent_class)->finalize)
76 (*G_OBJECT_CLASS (g_file_enumerator_parent_class)->finalize) (object);
80 g_file_enumerator_class_init (GFileEnumeratorClass *klass)
82 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
84 g_type_class_add_private (klass, sizeof (GFileEnumeratorPrivate));
86 gobject_class->finalize = g_file_enumerator_finalize;
88 klass->next_files_async = g_file_enumerator_real_next_files_async;
89 klass->next_files_finish = g_file_enumerator_real_next_files_finish;
90 klass->close_async = g_file_enumerator_real_close_async;
91 klass->close_finish = g_file_enumerator_real_close_finish;
95 g_file_enumerator_init (GFileEnumerator *enumerator)
97 enumerator->priv = G_TYPE_INSTANCE_GET_PRIVATE (enumerator,
98 G_TYPE_FILE_ENUMERATOR,
99 GFileEnumeratorPrivate);
103 * g_file_enumerator_next_file:
104 * @enumerator: a #GFileEnumerator.
105 * @cancellable: optional #GCancellable object, %NULL to ignore.
106 * @error: location to store the error occuring, or %NULL to ignore
108 * Returns information for the next file in the enumerated object.
109 * Will block until the information is available.
111 * On error, returns %NULL and sets @error to the error. If the
112 * enumerator is at the end, %NULL will be returned and @error will
115 * Return value: A #GFileInfo or %NULL on error or end of enumerator
118 g_file_enumerator_next_file (GFileEnumerator *enumerator,
119 GCancellable *cancellable,
122 GFileEnumeratorClass *class;
125 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
126 g_return_val_if_fail (enumerator != NULL, NULL);
128 if (enumerator->priv->closed)
130 g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
131 _("Enumerator is closed"));
135 if (enumerator->priv->pending)
137 g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
138 _("File enumerator has outstanding operation"));
142 if (enumerator->priv->outstanding_error)
144 g_propagate_error (error, enumerator->priv->outstanding_error);
145 enumerator->priv->outstanding_error = NULL;
149 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
152 g_push_current_cancellable (cancellable);
154 enumerator->priv->pending = TRUE;
155 info = (* class->next_file) (enumerator, cancellable, error);
156 enumerator->priv->pending = FALSE;
159 g_pop_current_cancellable (cancellable);
165 * g_file_enumerator_close:
166 * @enumerator: a #GFileEnumerator.
167 * @cancellable: optional #GCancellable object, %NULL to ignore.
168 * @error: location to store the error occuring, or %NULL to ignore
170 * Releases all resources used by this enumerator, making the
171 * enumerator return %G_IO_ERROR_CLOSED on all calls.
173 * This will be automatically called when the last reference
174 * is dropped, but you might want to call make sure resources
175 * are released as early as possible.
177 * Return value: #TRUE on success or #FALSE on error.
180 g_file_enumerator_close (GFileEnumerator *enumerator,
181 GCancellable *cancellable,
184 GFileEnumeratorClass *class;
186 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
187 g_return_val_if_fail (enumerator != NULL, FALSE);
189 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
191 if (enumerator->priv->closed)
194 if (enumerator->priv->pending)
196 g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
197 _("File enumerator has outstanding operation"));
202 g_push_current_cancellable (cancellable);
204 enumerator->priv->pending = TRUE;
205 (* class->close) (enumerator, cancellable, error);
206 enumerator->priv->pending = FALSE;
207 enumerator->priv->closed = TRUE;
210 g_pop_current_cancellable (cancellable);
216 next_async_callback_wrapper (GObject *source_object,
220 GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
222 enumerator->priv->pending = FALSE;
223 if (enumerator->priv->outstanding_callback)
224 (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
225 g_object_unref (enumerator);
229 * g_file_enumerator_next_files_async:
230 * @enumerator: a #GFileEnumerator.
231 * @num_files: the number of file info objects to request
232 * @io_priority: the io priority of the request. the io priority of the request
233 * @cancellable: optional #GCancellable object, %NULL to ignore.
234 * @callback: callback to call when the request is satisfied
235 * @user_data: the user_data to pass to callback function
237 * Request information for a number of files from the enumerator asynchronously.
238 * When all i/o for the operation is finished the @callback will be called with
239 * the requested information.
241 * The callback can be called with less than @num_files files in case of error
242 * or at the end of the enumerator. In case of a partial error the callback will
243 * be called with any succeeding items and no error, and on the next request the
244 * error will be reported. If a request is cancelled the callback will be called
245 * with %G_IO_ERROR_CANCELLED.
247 * During an async request no other sync and async calls are allowed, and will
248 * result in %G_IO_ERROR_PENDING errors.
250 * Any outstanding i/o request with higher priority (lower numerical value) will
251 * be executed before an outstanding request with lower priority. Default
252 * priority is %G_PRIORITY_DEFAULT.
255 g_file_enumerator_next_files_async (GFileEnumerator *enumerator,
258 GCancellable *cancellable,
259 GAsyncReadyCallback callback,
262 GFileEnumeratorClass *class;
263 GSimpleAsyncResult *simple;
265 g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
266 g_return_if_fail (enumerator != NULL);
267 g_return_if_fail (num_files >= 0);
271 simple = g_simple_async_result_new (G_OBJECT (enumerator),
274 g_file_enumerator_next_files_async);
275 g_simple_async_result_complete_in_idle (simple);
276 g_object_unref (simple);
280 if (enumerator->priv->closed)
282 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
285 G_IO_ERROR, G_IO_ERROR_CLOSED,
286 _("File enumerator is already closed"));
290 if (enumerator->priv->pending)
292 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
295 G_IO_ERROR, G_IO_ERROR_PENDING,
296 _("File enumerator has outstanding operation"));
300 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
302 enumerator->priv->pending = TRUE;
303 enumerator->priv->outstanding_callback = callback;
304 g_object_ref (enumerator);
305 (* class->next_files_async) (enumerator, num_files, io_priority, cancellable,
306 next_async_callback_wrapper, user_data);
310 * g_file_enumerator_next_files_finish:
311 * @enumerator: a #GFileEnumerator.
312 * @result: a #GAsyncResult.
313 * @error: a #GError location to store the error occuring, or %NULL to
321 g_file_enumerator_next_files_finish (GFileEnumerator *enumerator,
322 GAsyncResult *result,
325 GFileEnumeratorClass *class;
326 GSimpleAsyncResult *simple;
328 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
329 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
331 if (G_IS_SIMPLE_ASYNC_RESULT (result))
333 simple = G_SIMPLE_ASYNC_RESULT (result);
334 if (g_simple_async_result_propagate_error (simple, error))
337 /* Special case read of 0 files */
338 if (g_simple_async_result_get_source_tag (simple) == g_file_enumerator_next_files_async)
342 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
343 return class->next_files_finish (enumerator, result, error);
347 close_async_callback_wrapper (GObject *source_object,
351 GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
353 enumerator->priv->pending = FALSE;
354 enumerator->priv->closed = TRUE;
355 if (enumerator->priv->outstanding_callback)
356 (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
357 g_object_unref (enumerator);
361 * g_file_enumerator_close_async:
362 * @enumerator: a #GFileEnumerator.
363 * @io_priority: the io priority of the request. the io priority of the request
364 * @cancellable: optional #GCancellable object, %NULL to ignore.
365 * @callback: callback to call when the request is satisfied
366 * @user_data: the user_data to pass to callback function
370 g_file_enumerator_close_async (GFileEnumerator *enumerator,
372 GCancellable *cancellable,
373 GAsyncReadyCallback callback,
376 GFileEnumeratorClass *class;
378 g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
380 if (enumerator->priv->closed)
382 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
385 G_IO_ERROR, G_IO_ERROR_CLOSED,
386 _("File enumerator is already closed"));
390 if (enumerator->priv->pending)
392 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
395 G_IO_ERROR, G_IO_ERROR_PENDING,
396 _("File enumerator has outstanding operation"));
400 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
402 enumerator->priv->pending = TRUE;
403 enumerator->priv->outstanding_callback = callback;
404 g_object_ref (enumerator);
405 (* class->close_async) (enumerator, io_priority, cancellable,
406 close_async_callback_wrapper, user_data);
410 * g_file_enumerator_close_finish:
411 * @enumerator: a #GFileEnumerator.
412 * @result: a #GAsyncResult.
413 * @error: a #GError location to store the error occuring, or %NULL to
418 * Returns: %TRUE if the close operation has finished successfully.
421 g_file_enumerator_close_finish (GFileEnumerator *enumerator,
422 GAsyncResult *result,
425 GSimpleAsyncResult *simple;
426 GFileEnumeratorClass *class;
428 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
429 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
431 if (G_IS_SIMPLE_ASYNC_RESULT (result))
433 simple = G_SIMPLE_ASYNC_RESULT (result);
434 if (g_simple_async_result_propagate_error (simple, error))
438 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
439 return class->close_finish (enumerator, result, error);
443 * g_file_enumerator_is_closed:
444 * @enumerator: a #GFileEnumerator.
446 * Returns: %TRUE if the @enumerator is closed.
449 g_file_enumerator_is_closed (GFileEnumerator *enumerator)
451 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
453 return enumerator->priv->closed;
457 * g_file_enumerator_has_pending:
458 * @enumerator: a #GFileEnumerator.
460 * Returns: %TRUE if the @enumerator has pending operations.
463 g_file_enumerator_has_pending (GFileEnumerator *enumerator)
465 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
467 return enumerator->priv->pending;
471 * g_file_enumerator_set_pending:
472 * @enumerator: a #GFileEnumerator.
473 * @pending: a boolean value.
477 g_file_enumerator_set_pending (GFileEnumerator *enumerator,
480 g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
482 enumerator->priv->pending = pending;
491 next_files_thread (GSimpleAsyncResult *res,
493 GCancellable *cancellable)
496 GFileEnumeratorClass *class;
497 GError *error = NULL;
499 GFileEnumerator *enumerator;
502 enumerator = G_FILE_ENUMERATOR (object);
503 op = g_simple_async_result_get_op_res_gpointer (res);
505 class = G_FILE_ENUMERATOR_GET_CLASS (object);
507 for (i = 0; i < op->num_files; i++)
509 if (g_cancellable_set_error_if_cancelled (cancellable, &error))
512 info = class->next_file (enumerator, cancellable, &error);
516 /* If we get an error after first file, return that on next operation */
517 if (error != NULL && i > 0)
519 if (error->domain == G_IO_ERROR &&
520 error->code == G_IO_ERROR_CANCELLED)
521 g_error_free (error); /* Never propagate cancel errors to other call */
523 enumerator->priv->outstanding_error = error;
530 op->files = g_list_prepend (op->files, info);
536 g_file_enumerator_real_next_files_async (GFileEnumerator *enumerator,
539 GCancellable *cancellable,
540 GAsyncReadyCallback callback,
543 GSimpleAsyncResult *res;
546 op = g_new0 (NextAsyncOp, 1);
548 op->num_files = num_files;
551 res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, g_file_enumerator_real_next_files_async);
552 g_simple_async_result_set_op_res_gpointer (res, op, g_free);
554 g_simple_async_result_run_in_thread (res, next_files_thread, io_priority, cancellable);
555 g_object_unref (res);
559 g_file_enumerator_real_next_files_finish (GFileEnumerator *enumerator,
560 GAsyncResult *result,
563 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
566 g_assert (g_simple_async_result_get_source_tag (simple) ==
567 g_file_enumerator_real_next_files_async);
569 op = g_simple_async_result_get_op_res_gpointer (simple);
575 close_async_thread (GSimpleAsyncResult *res,
577 GCancellable *cancellable)
579 GFileEnumeratorClass *class;
580 GError *error = NULL;
583 /* Auto handling of cancelation disabled, and ignore
584 cancellation, since we want to close things anyway, although
585 possibly in a quick-n-dirty way. At least we never want to leak
588 class = G_FILE_ENUMERATOR_GET_CLASS (object);
589 result = class->close (G_FILE_ENUMERATOR (object), cancellable, &error);
592 g_simple_async_result_set_from_error (res, error);
593 g_error_free (error);
599 g_file_enumerator_real_close_async (GFileEnumerator *enumerator,
601 GCancellable *cancellable,
602 GAsyncReadyCallback callback,
605 GSimpleAsyncResult *res;
607 res = g_simple_async_result_new (G_OBJECT (enumerator),
610 g_file_enumerator_real_close_async);
612 g_simple_async_result_set_handle_cancellation (res, FALSE);
614 g_simple_async_result_run_in_thread (res,
618 g_object_unref (res);
622 g_file_enumerator_real_close_finish (GFileEnumerator *enumerator,
623 GAsyncResult *result,
626 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
627 g_assert (g_simple_async_result_get_source_tag (simple) ==
628 g_file_enumerator_real_close_async);