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 io priority of the request. the io priority of the request
235 * @cancellable: optional #GCancellable object, %NULL to ignore.
236 * @callback: callback to call when the request is satisfied
237 * @user_data: the user_data to pass to callback function
239 * Request information for a number of files from the enumerator asynchronously.
240 * When all i/o for the operation is finished the @callback will be called with
241 * the requested information.
243 * The callback can be called with less than @num_files files in case of error
244 * or at the end of the enumerator. In case of a partial error the callback will
245 * be called with any succeeding items and no error, and on the next request the
246 * error will be reported. If a request is cancelled the callback will be called
247 * with %G_IO_ERROR_CANCELLED.
249 * During an async request no other sync and async calls are allowed, and will
250 * result in %G_IO_ERROR_PENDING errors.
252 * Any outstanding i/o request with higher priority (lower numerical value) will
253 * be executed before an outstanding request with lower priority. Default
254 * priority is %G_PRIORITY_DEFAULT.
257 g_file_enumerator_next_files_async (GFileEnumerator *enumerator,
260 GCancellable *cancellable,
261 GAsyncReadyCallback callback,
264 GFileEnumeratorClass *class;
265 GSimpleAsyncResult *simple;
267 g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
268 g_return_if_fail (enumerator != NULL);
269 g_return_if_fail (num_files >= 0);
273 simple = g_simple_async_result_new (G_OBJECT (enumerator),
276 g_file_enumerator_next_files_async);
277 g_simple_async_result_complete_in_idle (simple);
278 g_object_unref (simple);
282 if (enumerator->priv->closed)
284 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
287 G_IO_ERROR, G_IO_ERROR_CLOSED,
288 _("File enumerator is already closed"));
292 if (enumerator->priv->pending)
294 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
297 G_IO_ERROR, G_IO_ERROR_PENDING,
298 _("File enumerator has outstanding operation"));
302 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
304 enumerator->priv->pending = TRUE;
305 enumerator->priv->outstanding_callback = callback;
306 g_object_ref (enumerator);
307 (* class->next_files_async) (enumerator, num_files, io_priority, cancellable,
308 next_async_callback_wrapper, user_data);
312 * g_file_enumerator_next_files_finish:
313 * @enumerator: a #GFileEnumerator.
314 * @result: a #GAsyncResult.
315 * @error: a #GError location to store the error occuring, or %NULL to
323 g_file_enumerator_next_files_finish (GFileEnumerator *enumerator,
324 GAsyncResult *result,
327 GFileEnumeratorClass *class;
328 GSimpleAsyncResult *simple;
330 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
331 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
333 if (G_IS_SIMPLE_ASYNC_RESULT (result))
335 simple = G_SIMPLE_ASYNC_RESULT (result);
336 if (g_simple_async_result_propagate_error (simple, error))
339 /* Special case read of 0 files */
340 if (g_simple_async_result_get_source_tag (simple) == g_file_enumerator_next_files_async)
344 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
345 return class->next_files_finish (enumerator, result, error);
349 close_async_callback_wrapper (GObject *source_object,
353 GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source_object);
355 enumerator->priv->pending = FALSE;
356 enumerator->priv->closed = TRUE;
357 if (enumerator->priv->outstanding_callback)
358 (*enumerator->priv->outstanding_callback) (source_object, res, user_data);
359 g_object_unref (enumerator);
363 * g_file_enumerator_close_async:
364 * @enumerator: a #GFileEnumerator.
365 * @io_priority: the io priority of the request. the io priority of the request
366 * @cancellable: optional #GCancellable object, %NULL to ignore.
367 * @callback: callback to call when the request is satisfied
368 * @user_data: the user_data to pass to callback function
372 g_file_enumerator_close_async (GFileEnumerator *enumerator,
374 GCancellable *cancellable,
375 GAsyncReadyCallback callback,
378 GFileEnumeratorClass *class;
380 g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
382 if (enumerator->priv->closed)
384 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
387 G_IO_ERROR, G_IO_ERROR_CLOSED,
388 _("File enumerator is already closed"));
392 if (enumerator->priv->pending)
394 g_simple_async_report_error_in_idle (G_OBJECT (enumerator),
397 G_IO_ERROR, G_IO_ERROR_PENDING,
398 _("File enumerator has outstanding operation"));
402 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
404 enumerator->priv->pending = TRUE;
405 enumerator->priv->outstanding_callback = callback;
406 g_object_ref (enumerator);
407 (* class->close_async) (enumerator, io_priority, cancellable,
408 close_async_callback_wrapper, user_data);
412 * g_file_enumerator_close_finish:
413 * @enumerator: a #GFileEnumerator.
414 * @result: a #GAsyncResult.
415 * @error: a #GError location to store the error occuring, or %NULL to
420 * Returns: %TRUE if the close operation has finished successfully.
423 g_file_enumerator_close_finish (GFileEnumerator *enumerator,
424 GAsyncResult *result,
427 GSimpleAsyncResult *simple;
428 GFileEnumeratorClass *class;
430 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE);
431 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
433 if (G_IS_SIMPLE_ASYNC_RESULT (result))
435 simple = G_SIMPLE_ASYNC_RESULT (result);
436 if (g_simple_async_result_propagate_error (simple, error))
440 class = G_FILE_ENUMERATOR_GET_CLASS (enumerator);
441 return class->close_finish (enumerator, result, error);
445 * g_file_enumerator_is_closed:
446 * @enumerator: a #GFileEnumerator.
448 * Returns: %TRUE if the @enumerator is closed.
451 g_file_enumerator_is_closed (GFileEnumerator *enumerator)
453 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
455 return enumerator->priv->closed;
459 * g_file_enumerator_has_pending:
460 * @enumerator: a #GFileEnumerator.
462 * Returns: %TRUE if the @enumerator has pending operations.
465 g_file_enumerator_has_pending (GFileEnumerator *enumerator)
467 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), TRUE);
469 return enumerator->priv->pending;
473 * g_file_enumerator_set_pending:
474 * @enumerator: a #GFileEnumerator.
475 * @pending: a boolean value.
479 g_file_enumerator_set_pending (GFileEnumerator *enumerator,
482 g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
484 enumerator->priv->pending = pending;
493 next_files_thread (GSimpleAsyncResult *res,
495 GCancellable *cancellable)
498 GFileEnumeratorClass *class;
499 GError *error = NULL;
501 GFileEnumerator *enumerator;
504 enumerator = G_FILE_ENUMERATOR (object);
505 op = g_simple_async_result_get_op_res_gpointer (res);
507 class = G_FILE_ENUMERATOR_GET_CLASS (object);
509 for (i = 0; i < op->num_files; i++)
511 if (g_cancellable_set_error_if_cancelled (cancellable, &error))
514 info = class->next_file (enumerator, cancellable, &error);
518 /* If we get an error after first file, return that on next operation */
519 if (error != NULL && i > 0)
521 if (error->domain == G_IO_ERROR &&
522 error->code == G_IO_ERROR_CANCELLED)
523 g_error_free (error); /* Never propagate cancel errors to other call */
525 enumerator->priv->outstanding_error = error;
532 op->files = g_list_prepend (op->files, info);
538 g_file_enumerator_real_next_files_async (GFileEnumerator *enumerator,
541 GCancellable *cancellable,
542 GAsyncReadyCallback callback,
545 GSimpleAsyncResult *res;
548 op = g_new0 (NextAsyncOp, 1);
550 op->num_files = num_files;
553 res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, g_file_enumerator_real_next_files_async);
554 g_simple_async_result_set_op_res_gpointer (res, op, g_free);
556 g_simple_async_result_run_in_thread (res, next_files_thread, io_priority, cancellable);
557 g_object_unref (res);
561 g_file_enumerator_real_next_files_finish (GFileEnumerator *enumerator,
562 GAsyncResult *result,
565 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
568 g_assert (g_simple_async_result_get_source_tag (simple) ==
569 g_file_enumerator_real_next_files_async);
571 op = g_simple_async_result_get_op_res_gpointer (simple);
577 close_async_thread (GSimpleAsyncResult *res,
579 GCancellable *cancellable)
581 GFileEnumeratorClass *class;
582 GError *error = NULL;
585 /* Auto handling of cancelation disabled, and ignore
586 cancellation, since we want to close things anyway, although
587 possibly in a quick-n-dirty way. At least we never want to leak
590 class = G_FILE_ENUMERATOR_GET_CLASS (object);
591 result = class->close (G_FILE_ENUMERATOR (object), cancellable, &error);
594 g_simple_async_result_set_from_error (res, error);
595 g_error_free (error);
601 g_file_enumerator_real_close_async (GFileEnumerator *enumerator,
603 GCancellable *cancellable,
604 GAsyncReadyCallback callback,
607 GSimpleAsyncResult *res;
609 res = g_simple_async_result_new (G_OBJECT (enumerator),
612 g_file_enumerator_real_close_async);
614 g_simple_async_result_set_handle_cancellation (res, FALSE);
616 g_simple_async_result_run_in_thread (res,
620 g_object_unref (res);
624 g_file_enumerator_real_close_finish (GFileEnumerator *enumerator,
625 GAsyncResult *result,
628 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
629 g_assert (g_simple_async_result_get_source_tag (simple) ==
630 g_file_enumerator_real_close_async);
634 #define __G_FILE_ENUMERATOR_C__
635 #include "gioaliasdef.c"