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"
33 * SECTION:gfileenumerator
34 * @short_description: Enumerated Files Routines
39 G_DEFINE_TYPE (GFileEnumerator, g_file_enumerator, G_TYPE_OBJECT);
41 struct _GFileEnumeratorPrivate {
42 /* TODO: Should be public for subclasses? */
45 GAsyncReadyCallback outstanding_callback;
46 GError *outstanding_error;
49 static void g_file_enumerator_real_next_files_async (GFileEnumerator *enumerator,
52 GCancellable *cancellable,
53 GAsyncReadyCallback callback,
55 static GList * g_file_enumerator_real_next_files_finish (GFileEnumerator *enumerator,
58 static void g_file_enumerator_real_close_async (GFileEnumerator *enumerator,
60 GCancellable *cancellable,
61 GAsyncReadyCallback callback,
63 static gboolean g_file_enumerator_real_close_finish (GFileEnumerator *enumerator,
68 g_file_enumerator_finalize (GObject *object)
70 GFileEnumerator *enumerator;
72 enumerator = G_FILE_ENUMERATOR (object);
74 if (!enumerator->priv->closed)
75 g_file_enumerator_close (enumerator, NULL, NULL);
77 if (G_OBJECT_CLASS (g_file_enumerator_parent_class)->finalize)
78 (*G_OBJECT_CLASS (g_file_enumerator_parent_class)->finalize) (object);
82 g_file_enumerator_class_init (GFileEnumeratorClass *klass)
84 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
86 g_type_class_add_private (klass, sizeof (GFileEnumeratorPrivate));
88 gobject_class->finalize = g_file_enumerator_finalize;
90 klass->next_files_async = g_file_enumerator_real_next_files_async;
91 klass->next_files_finish = g_file_enumerator_real_next_files_finish;
92 klass->close_async = g_file_enumerator_real_close_async;
93 klass->close_finish = g_file_enumerator_real_close_finish;
97 g_file_enumerator_init (GFileEnumerator *enumerator)
99 enumerator->priv = G_TYPE_INSTANCE_GET_PRIVATE (enumerator,
100 G_TYPE_FILE_ENUMERATOR,
101 GFileEnumeratorPrivate);
105 * g_file_enumerator_next_file:
106 * @enumerator: a #GFileEnumerator.
107 * @cancellable: optional #GCancellable object, %NULL to ignore.
108 * @error: location to store the error occuring, or %NULL to ignore
110 * Returns information for the next file in the enumerated object.
111 * Will block until the information is available.
113 * On error, returns %NULL and sets @error to the error. If the
114 * enumerator is at the end, %NULL will be returned and @error will
117 * Return value: A #GFileInfo or %NULL on error or end of enumerator
120 g_file_enumerator_next_file (GFileEnumerator *enumerator,
121 GCancellable *cancellable,
124 GFileEnumeratorClass *class;
127 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
128 g_return_val_if_fail (enumerator != NULL, NULL);
130 if (enumerator->priv->closed)
132 g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
133 _("Enumerator is closed"));
137 if (enumerator->priv->pending)
139 g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
140 _("File enumerator has outstanding operation"));
144 if (enumerator->priv->outstanding_error)
146 g_propagate_error (error, enumerator->priv->outstanding_error);
147 enumerator->priv->outstanding_error = NULL;
151 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
154 g_push_current_cancellable (cancellable);
156 enumerator->priv->pending = TRUE;
157 info = (* class->next_file) (enumerator, cancellable, error);
158 enumerator->priv->pending = FALSE;
161 g_pop_current_cancellable (cancellable);
167 * g_file_enumerator_close:
168 * @enumerator: a #GFileEnumerator.
169 * @cancellable: optional #GCancellable object, %NULL to ignore.
170 * @error: location to store the error occuring, or %NULL to ignore
172 * Releases all resources used by this enumerator, making the
173 * enumerator return %G_IO_ERROR_CLOSED on all calls.
175 * This will be automatically called when the last reference
176 * is dropped, but you might want to call make sure resources
177 * are released as early as possible.
179 * Return value: #TRUE on success or #FALSE on error.
182 g_file_enumerator_close (GFileEnumerator *enumerator,
183 GCancellable *cancellable,
186 GFileEnumeratorClass *class;
188 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
189 g_return_val_if_fail (enumerator != NULL, FALSE);
191 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
193 if (enumerator->priv->closed)
196 if (enumerator->priv->pending)
198 g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
199 _("File enumerator has outstanding operation"));
204 g_push_current_cancellable (cancellable);
206 enumerator->priv->pending = TRUE;
207 (* class->close) (enumerator, cancellable, error);
208 enumerator->priv->pending = FALSE;
209 enumerator->priv->closed = TRUE;
212 g_pop_current_cancellable (cancellable);
218 next_async_callback_wrapper (GObject *source_object,
222 GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
224 enumerator->priv->pending = FALSE;
225 if (enumerator->priv->outstanding_callback)
226 (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
227 g_object_unref (enumerator);
231 * g_file_enumerator_next_files_async:
232 * @enumerator: a #GFileEnumerator.
233 * @num_files: the number of file info objects to request
234 * @io_priority: the <link linkend="gioscheduler">io priority</link>
236 * @cancellable: optional #GCancellable object, %NULL to ignore.
237 * @callback: callback to call when the request is satisfied
238 * @user_data: the user_data to pass to callback function
240 * Request information for a number of files from the enumerator asynchronously.
241 * When all i/o for the operation is finished the @callback will be called with
242 * the requested information.
244 * The callback can be called with less than @num_files files in case of error
245 * or at the end of the enumerator. In case of a partial error the callback will
246 * be called with any succeeding items and no error, and on the next request the
247 * error will be reported. If a request is cancelled the callback will be called
248 * with %G_IO_ERROR_CANCELLED.
250 * During an async request no other sync and async calls are allowed, and will
251 * result in %G_IO_ERROR_PENDING errors.
253 * Any outstanding i/o request with higher priority (lower numerical value) will
254 * be executed before an outstanding request with lower priority. Default
255 * priority is %G_PRIORITY_DEFAULT.
258 g_file_enumerator_next_files_async (GFileEnumerator *enumerator,
261 GCancellable *cancellable,
262 GAsyncReadyCallback callback,
265 GFileEnumeratorClass *class;
266 GSimpleAsyncResult *simple;
268 g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
269 g_return_if_fail (enumerator != NULL);
270 g_return_if_fail (num_files >= 0);
274 simple = g_simple_async_result_new (G_OBJECT (enumerator),
277 g_file_enumerator_next_files_async);
278 g_simple_async_result_complete_in_idle (simple);
279 g_object_unref (simple);
283 if (enumerator->priv->closed)
285 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
288 G_IO_ERROR, G_IO_ERROR_CLOSED,
289 _("File enumerator is already closed"));
293 if (enumerator->priv->pending)
295 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
298 G_IO_ERROR, G_IO_ERROR_PENDING,
299 _("File enumerator has outstanding operation"));
303 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
305 enumerator->priv->pending = TRUE;
306 enumerator->priv->outstanding_callback = callback;
307 g_object_ref (enumerator);
308 (* class->next_files_async) (enumerator, num_files, io_priority, cancellable,
309 next_async_callback_wrapper, user_data);
313 * g_file_enumerator_next_files_finish:
314 * @enumerator: a #GFileEnumerator.
315 * @result: a #GAsyncResult.
316 * @error: a #GError location to store the error occuring, or %NULL to
324 g_file_enumerator_next_files_finish (GFileEnumerator *enumerator,
325 GAsyncResult *result,
328 GFileEnumeratorClass *class;
329 GSimpleAsyncResult *simple;
331 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
332 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
334 if (G_IS_SIMPLE_ASYNC_RESULT (result))
336 simple = G_SIMPLE_ASYNC_RESULT (result);
337 if (g_simple_async_result_propagate_error (simple, error))
340 /* Special case read of 0 files */
341 if (g_simple_async_result_get_source_tag (simple) == g_file_enumerator_next_files_async)
345 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
346 return class->next_files_finish (enumerator, result, error);
350 close_async_callback_wrapper (GObject *source_object,
354 GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
356 enumerator->priv->pending = FALSE;
357 enumerator->priv->closed = TRUE;
358 if (enumerator->priv->outstanding_callback)
359 (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
360 g_object_unref (enumerator);
364 * g_file_enumerator_close_async:
365 * @enumerator: a #GFileEnumerator.
366 * @io_priority: the <link linkend="io-priority">I/O priority</link>
368 * @cancellable: optional #GCancellable object, %NULL to ignore.
369 * @callback: callback to call when the request is satisfied
370 * @user_data: the user_data to pass to callback function
374 g_file_enumerator_close_async (GFileEnumerator *enumerator,
376 GCancellable *cancellable,
377 GAsyncReadyCallback callback,
380 GFileEnumeratorClass *class;
382 g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
384 if (enumerator->priv->closed)
386 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
389 G_IO_ERROR, G_IO_ERROR_CLOSED,
390 _("File enumerator is already closed"));
394 if (enumerator->priv->pending)
396 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
399 G_IO_ERROR, G_IO_ERROR_PENDING,
400 _("File enumerator has outstanding operation"));
404 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
406 enumerator->priv->pending = TRUE;
407 enumerator->priv->outstanding_callback = callback;
408 g_object_ref (enumerator);
409 (* class->close_async) (enumerator, io_priority, cancellable,
410 close_async_callback_wrapper, user_data);
414 * g_file_enumerator_close_finish:
415 * @enumerator: a #GFileEnumerator.
416 * @result: a #GAsyncResult.
417 * @error: a #GError location to store the error occuring, or %NULL to
422 * Returns: %TRUE if the close operation has finished successfully.
425 g_file_enumerator_close_finish (GFileEnumerator *enumerator,
426 GAsyncResult *result,
429 GSimpleAsyncResult *simple;
430 GFileEnumeratorClass *class;
432 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
433 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
435 if (G_IS_SIMPLE_ASYNC_RESULT (result))
437 simple = G_SIMPLE_ASYNC_RESULT (result);
438 if (g_simple_async_result_propagate_error (simple, error))
442 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
443 return class->close_finish (enumerator, result, error);
447 * g_file_enumerator_is_closed:
448 * @enumerator: a #GFileEnumerator.
450 * Returns: %TRUE if the @enumerator is closed.
453 g_file_enumerator_is_closed (GFileEnumerator *enumerator)
455 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
457 return enumerator->priv->closed;
461 * g_file_enumerator_has_pending:
462 * @enumerator: a #GFileEnumerator.
464 * Returns: %TRUE if the @enumerator has pending operations.
467 g_file_enumerator_has_pending (GFileEnumerator *enumerator)
469 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
471 return enumerator->priv->pending;
475 * g_file_enumerator_set_pending:
476 * @enumerator: a #GFileEnumerator.
477 * @pending: a boolean value.
481 g_file_enumerator_set_pending (GFileEnumerator *enumerator,
484 g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
486 enumerator->priv->pending = pending;
495 next_files_thread (GSimpleAsyncResult *res,
497 GCancellable *cancellable)
500 GFileEnumeratorClass *class;
501 GError *error = NULL;
503 GFileEnumerator *enumerator;
506 enumerator = G_FILE_ENUMERATOR (object);
507 op = g_simple_async_result_get_op_res_gpointer (res);
509 class = G_FILE_ENUMERATOR_GET_CLASS (object);
511 for (i = 0; i < op->num_files; i++)
513 if (g_cancellable_set_error_if_cancelled (cancellable, &error))
516 info = class->next_file (enumerator, cancellable, &error);
520 /* If we get an error after first file, return that on next operation */
521 if (error != NULL && i > 0)
523 if (error->domain == G_IO_ERROR &&
524 error->code == G_IO_ERROR_CANCELLED)
525 g_error_free (error); /* Never propagate cancel errors to other call */
527 enumerator->priv->outstanding_error = error;
534 op->files = g_list_prepend (op->files, info);
540 g_file_enumerator_real_next_files_async (GFileEnumerator *enumerator,
543 GCancellable *cancellable,
544 GAsyncReadyCallback callback,
547 GSimpleAsyncResult *res;
550 op = g_new0 (NextAsyncOp, 1);
552 op->num_files = num_files;
555 res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, g_file_enumerator_real_next_files_async);
556 g_simple_async_result_set_op_res_gpointer (res, op, g_free);
558 g_simple_async_result_run_in_thread (res, next_files_thread, io_priority, cancellable);
559 g_object_unref (res);
563 g_file_enumerator_real_next_files_finish (GFileEnumerator *enumerator,
564 GAsyncResult *result,
567 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
570 g_assert (g_simple_async_result_get_source_tag (simple) ==
571 g_file_enumerator_real_next_files_async);
573 op = g_simple_async_result_get_op_res_gpointer (simple);
579 close_async_thread (GSimpleAsyncResult *res,
581 GCancellable *cancellable)
583 GFileEnumeratorClass *class;
584 GError *error = NULL;
587 /* Auto handling of cancelation disabled, and ignore
588 cancellation, since we want to close things anyway, although
589 possibly in a quick-n-dirty way. At least we never want to leak
592 class = G_FILE_ENUMERATOR_GET_CLASS (object);
593 result = class->close (G_FILE_ENUMERATOR (object), cancellable, &error);
596 g_simple_async_result_set_from_error (res, error);
597 g_error_free (error);
603 g_file_enumerator_real_close_async (GFileEnumerator *enumerator,
605 GCancellable *cancellable,
606 GAsyncReadyCallback callback,
609 GSimpleAsyncResult *res;
611 res = g_simple_async_result_new (G_OBJECT (enumerator),
614 g_file_enumerator_real_close_async);
616 g_simple_async_result_set_handle_cancellation (res, FALSE);
618 g_simple_async_result_run_in_thread (res,
622 g_object_unref (res);
626 g_file_enumerator_real_close_finish (GFileEnumerator *enumerator,
627 GAsyncResult *result,
630 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
631 g_assert (g_simple_async_result_get_source_tag (simple) ==
632 g_file_enumerator_real_close_async);
636 #define __G_FILE_ENUMERATOR_C__
637 #include "gioaliasdef.c"