tracker-file-enumerator.c 5.75 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*
 * Copyright (C) 2014, Softathome <contact@softathome.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 * Author: Martyn Russell <martyn@lanedo.com>
 */

#include "config.h"

#include "tracker-file-enumerator.h"

static void tracker_file_enumerator_file_iface_init (TrackerEnumeratorIface *iface);

struct _TrackerFileEnumerator {
	GObject parent_instance;
30
	GFileEnumerator *file_enumerator;
31 32
};

33 34 35 36 37 38 39 40 41 42 43 44 45 46
/**
 * SECTION:tracker-file-enumerator
 * @short_description: File based enumerator for file:// descendant URIs
 * @include: libtracker-miner/miner.h
 *
 * #TrackerFileEnumerator is a local file implementation of the
 * #TrackerEnumerator interface, charged with handling all file:// type URIs.
 *
 * Underneath it all, this implementation makes use of the
 * #GFileEnumerator APIs.
 *
 * Since: 1.2
 **/

47 48 49 50 51 52 53
G_DEFINE_TYPE_WITH_CODE (TrackerFileEnumerator, tracker_file_enumerator, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (TRACKER_TYPE_ENUMERATOR,
                                                tracker_file_enumerator_file_iface_init))

static void
tracker_file_enumerator_finalize (GObject *object)
{
54 55 56 57 58 59
	TrackerFileEnumerator *tfe = TRACKER_FILE_ENUMERATOR (object);

	if (tfe->file_enumerator) {
		g_object_unref (tfe->file_enumerator);
	}

60 61 62 63 64 65 66 67 68 69 70 71 72 73
	G_OBJECT_CLASS (tracker_file_enumerator_parent_class)->finalize (object);
}

static void
tracker_file_enumerator_class_init (TrackerFileEnumeratorClass *klass)
{
	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

	gobject_class->finalize = tracker_file_enumerator_finalize;
}

static void
tracker_file_enumerator_init (TrackerFileEnumerator *fe)
{
74 75
}

76 77 78 79
static gpointer
file_enumerator_next (TrackerEnumerator  *enumerator,
                      GCancellable       *cancellable,
                      GError            **error)
80
{
81 82
	TrackerFileEnumerator *tfe;
	GFileInfo *info = NULL;
83 84
	GError *local_error = NULL;

85
	if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
86 87 88
		return NULL;
	}

89 90
	tfe = TRACKER_FILE_ENUMERATOR (enumerator);
	info = g_file_enumerator_next_file (tfe->file_enumerator, cancellable, &local_error);
91

92 93 94 95 96
	/* FIXME: Do we need a ->is_running check here like before? */
	if (local_error || !info) {
		if (local_error) {
			g_critical ("Could not crawl through directory: %s", local_error->message);
			g_propagate_error (error, local_error);
97 98
		}

99 100 101 102 103 104
		/* No more files or we are stopping anyway, so clean
		 * up and close all file enumerators.
		 */
		if (info) {
			g_object_unref (info);
		}
105

106
		return NULL;
107 108
	}

109 110 111 112 113 114 115
	/* FIXME: We need some check here to call
	 * enumerator_data_process which signals
	 * CHECK_DIRECTORY_CONTENTS
	 */
	g_debug ("--> Found:'%s' (%s)",
	         g_file_info_get_name (info),
	         g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY ? "Dir" : "File");
116

117
	return info;
118 119 120
}

static void
121 122 123 124
file_enumerator_next_thread (GTask        *task,
                             gpointer      source_object,
                             gpointer      task_data,
                             GCancellable *cancellable)
125 126
{
	TrackerEnumerator *enumerator = source_object;
127
	GFileInfo *info;
128 129
	GError *error = NULL;

130
	info = file_enumerator_next (enumerator, cancellable, &error);
131 132 133 134

	if (error) {
		g_task_return_error (task, error);
	} else {
135
		g_task_return_pointer (task, info, (GDestroyNotify) g_object_unref);
136 137 138 139
	}
}

static void
140 141 142 143 144
file_enumerator_next_async (TrackerEnumerator    *enumerator,
                            gint                  io_priority,
                            GCancellable         *cancellable,
                            GAsyncReadyCallback   callback,
                            gpointer              user_data)
145 146 147 148 149
{
	GTask *task;

	task = g_task_new (enumerator, cancellable, callback, user_data);
	g_task_set_priority (task, io_priority);
150
	g_task_run_in_thread (task, file_enumerator_next_thread);
151 152 153
	g_object_unref (task);
}

154 155 156 157
static gpointer
file_enumerator_next_finish (TrackerEnumerator  *enumerator,
                             GAsyncResult       *result,
                             GError            **error)
158 159 160 161 162 163 164 165 166
{
	g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);

	return g_task_propagate_pointer (G_TASK (result), error);
}

static void
tracker_file_enumerator_file_iface_init (TrackerEnumeratorIface *iface)
{
167 168 169
	iface->next = file_enumerator_next;
	iface->next_async = file_enumerator_next_async;
	iface->next_finish = file_enumerator_next_finish;
170 171
}

172 173
/**
 * tracker_file_enumerator_new:
174
 * @file_enumerator: the #GFileEnumerator used to enumerate with
175 176 177 178 179 180 181 182
 *
 * Creates a new TrackerEnumerator which can be used to create new
 * #TrackerMinerFS classes. See #TrackerMinerFS for an example of how
 * to use your #TrackerEnumerator.
 *
 * Returns: (transfer full): a #TrackerEnumerator which must be
 * unreferenced with g_object_unref().
 *
183
 * Since: 1.2
184
 **/
185
TrackerEnumerator *
186
tracker_file_enumerator_new (GFileEnumerator *file_enumerator)
187 188 189
{
	TrackerFileEnumerator *tfe;

190 191
	g_return_val_if_fail (G_IS_FILE_ENUMERATOR (file_enumerator), NULL);

192
	tfe = g_object_new (TRACKER_TYPE_FILE_ENUMERATOR, NULL);
193 194 195 196 197
	if (!tfe) {
		return NULL;
	}

	tfe->file_enumerator = g_object_ref (file_enumerator);
198 199 200

	return TRACKER_ENUMERATOR (tfe);
}