[rygel] media-export: Refactor filessystem walking
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rygel] media-export: Refactor filessystem walking
- Date: Thu, 12 Aug 2010 15:19:19 +0000 (UTC)
commit b2090101ee66c891c558e0ba068f3776a827438b
Author: Jens Georg <mail jensge org>
Date: Wed Jul 28 12:29:17 2010 +0200
media-export: Refactor filessystem walking
Handling harvester events and book-keeping is done by a new Harvester
class, the old harvester class has been renamed to HarvestingTask
src/plugins/media-export/Makefile.am | 1 +
.../media-export/rygel-media-export-harvester.vala | 370 +++-----------------
.../rygel-media-export-harvesting-task.vala | 355 +++++++++++++++++++
.../rygel-media-export-root-container.vala | 63 +---
4 files changed, 404 insertions(+), 385 deletions(-)
---
diff --git a/src/plugins/media-export/Makefile.am b/src/plugins/media-export/Makefile.am
index 5340b61..772aa3a 100644
--- a/src/plugins/media-export/Makefile.am
+++ b/src/plugins/media-export/Makefile.am
@@ -34,6 +34,7 @@ librygel_media_export_la_SOURCES = rygel-media-export-plugin.vala \
rygel-media-export-dbus-service.vala \
rygel-media-export-recursive-file-monitor.vala \
rygel-media-export-harvester.vala \
+ rygel-media-export-harvesting-task.vala \
rygel-media-export-item.vala \
rygel-media-export-jpeg-writer.vala \
rygel-media-export-object-factory.vala
diff --git a/src/plugins/media-export/rygel-media-export-harvester.vala b/src/plugins/media-export/rygel-media-export-harvester.vala
index ca93aab..8da1940 100644
--- a/src/plugins/media-export/rygel-media-export-harvester.vala
+++ b/src/plugins/media-export/rygel-media-export-harvester.vala
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Jens Georg <mail jensge org>.
+ * Copyright (C) 2010 Jens Georg <mail jensge org>.
*
* This file is part of Rygel.
*
@@ -17,354 +17,64 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-
-using GLib;
using Gee;
-public class Rygel.MediaExport.Harvester : GLib.Object {
+internal class Rygel.MediaExport.Harvester : GLib.Object {
+ private HashMap<File, HarvestingTask> tasks;
+ private ArrayList<HarvestingTask> trash;
private MetadataExtractor extractor;
- private MediaCache media_db;
- private GLib.Queue<MediaContainer> containers;
- private Gee.Queue<File> files;
- private File origin;
- private MediaContainer parent;
private RecursiveFileMonitor monitor;
- private Regex file_filter;
- public Cancellable cancellable;
- private string flag;
- private const string HARVESTER_ATTRIBUTES =
- FILE_ATTRIBUTE_STANDARD_NAME + "," +
- FILE_ATTRIBUTE_STANDARD_TYPE + "," +
- FILE_ATTRIBUTE_TIME_MODIFIED + "," +
- FILE_ATTRIBUTE_STANDARD_SIZE;
-
- public Harvester (MediaContainer parent,
- MediaCache media_db,
- MetadataExtractor extractor,
- RecursiveFileMonitor monitor,
- string? flag = null) {
- this.parent = parent;
+ public Harvester (MetadataExtractor extractor,
+ RecursiveFileMonitor monitor) {
this.extractor = extractor;
- this.media_db = media_db;
- this.extractor.extraction_done.connect (on_extracted_cb);
- this.extractor.error.connect (on_extractor_error_cb);
- this.files = new LinkedList<File> ();
- this.containers = new GLib.Queue<MediaContainer> ();
- this.origin = null;
this.monitor = monitor;
- this.cancellable = new Cancellable ();
- this.flag = flag;
- var config = MetaConfig.get_default ();
-
- try {
- var extensions = config.get_string_list ("MediaExport",
- "include-filter");
-
- // never trust user input
- string[] escaped_extensions = new string[0];
- foreach (var extension in extensions) {
- escaped_extensions += Regex.escape_string (extension);
- }
-
- var list = string.joinv ("|", escaped_extensions);
- file_filter = new Regex ("(%s)$".printf (list),
- RegexCompileFlags.CASELESS |
- RegexCompileFlags.OPTIMIZE);
- } catch (Error error) {
- file_filter = null;
- }
- }
-
- private bool push_if_changed_or_unknown (File file,
- FileInfo info,
- out string id) {
- id = Checksum.compute_for_string (ChecksumType.MD5, file.get_uri ());
- int64 timestamp;
- try {
- if (this.media_db.exists (id, out timestamp)) {
- int64 mtime = (int64) info.get_attribute_uint64 (
- FILE_ATTRIBUTE_TIME_MODIFIED);
-
- if (mtime > timestamp) {
- this.files.offer (file);
-
- return true;
- } else {
- // check size
- var size = info.get_size ();
- var item = media_db.get_item (id);
- if (item.size != size) {
- this.files.offer (file);
-
- return true;
- }
- }
- } else {
- this.files.offer (file);
-
- return true;
- }
- } catch (Error error) {
- warning (_("Failed to query database: %s"), error.message);
- }
-
- return false;
+ this.tasks = new HashMap<File, HarvestingTask> (file_hash, file_equal);
+ this.trash = new ArrayList<HarvestingTask> ();
}
- private bool process_children (GLib.List<FileInfo>? list) {
- if (list == null || this.cancellable.is_cancelled ()) {
- return false;
- }
-
- foreach (var info in list) {
- if (info.get_name ()[0] == '.') {
- continue;
- }
- var parent_container =
- (DummyContainer) this.containers.peek_head ();
-
- var dir = parent_container.file;
- var file = dir.get_child (info.get_name ());
- if (info.get_file_type () == FileType.DIRECTORY) {
- monitor.monitor (file);
- var container = new DummyContainer (file,
- parent_container);
- this.containers.push_tail (container);
- parent_container.seen (container.id);
- try {
- int64 timestamp;
- if (!this.media_db.exists (container.id,
- out timestamp)) {
- this.media_db.save_container (container);
- }
- } catch (Error err) {
- warning (_("Failed to update database: %s"), err.message);
- }
- } else {
- string id;
-
- // Let's see if the file is wanted
- if (file_filter != null &&
- !file_filter.match (file.get_uri ())) {
- continue;
- }
-
- push_if_changed_or_unknown (file, info, out id);
- parent_container.seen (id);
- }
- }
-
- return true;
- }
-
- private async void enumerate_directory (File directory) {
- try {
- var enumerator = yield directory.enumerate_children_async (
- HARVESTER_ATTRIBUTES,
- FileQueryInfoFlags.NONE,
- Priority.DEFAULT,
- this.cancellable);
-
- GLib.List<FileInfo> list = null;
- do {
- list = yield enumerator.next_files_async (256,
- Priority.DEFAULT,
- this.cancellable);
- } while (process_children (list));
-
- yield enumerator.close_async (Priority.DEFAULT, this.cancellable);
- } catch (Error err) {
- warning (_("failed to enumerate folder: %s"), err.message);
- }
-
- cleanup_database (this.containers.peek_head () as DummyContainer);
- this.do_update ();
- }
+ public void schedule (File file,
+ MediaContainer parent,
+ string? flag = null) {
+ if (this.extractor == null) {
+ warning (_("No Metadata extractor available. Will not crawl"));
- void cleanup_database (DummyContainer container) {
- // delete all children which are not in filesystem anymore
- container = (DummyContainer) this.containers.peek_head ();
- try {
- var children = this.media_db.get_child_ids (container.id);
-
- foreach (var seen_id in container.seen_children) {
- children.remove (seen_id);
- }
-
- foreach (var child in children) {
- this.media_db.remove_by_id (child);
- }
- } catch (DatabaseError err) {
- warning (_("Failed to get children of container %s: %s"),
- container.id,
- err.message);
+ return;
}
+ // Cancel currently running harvester
+ this.cancel (file);
+
+ var task = new HarvestingTask (this.extractor,
+ this.monitor,
+ file,
+ parent,
+ flag);
+ task.completed.connect (this.on_file_harvested);
+ this.tasks[file] = task;
+ task.run ();
}
- private bool on_idle () {
- if (this.cancellable.is_cancelled ()) {
- return false;
+ public void cancel (File file) {
+ if (this.tasks.contains (file)) {
+ var task = this.tasks[file];
+ task.completed.disconnect (this.on_file_harvested);
+ this.tasks.remove (file);
+ task.cancellable.cancel ();
+ task.completed.connect (this.on_remove_cancelled_harvester);
+ this.trash.add (task);
}
-
- if (this.files.size > 0) {
- var candidate = this.files.peek ();
- this.extractor.extract (candidate);
- } else if (this.containers.get_length () > 0) {
- var container = this.containers.peek_head () as DummyContainer;
- var directory = container.file;
- enumerate_directory (directory);
- } else {
- // nothing to do
- if (this.flag != null) {
- try {
- this.media_db.flag_object (Item.get_id (this.origin),
- this.flag);
- } catch (Error error) {};
- }
- harvested (this.origin);
- }
-
- return false;
}
- /**
- * Fired for every file passed to harvest.
- */
- public signal void harvested (File file);
-
- /**
- * Extract all metainformation from a given file.
- *
- * What action will be taken depends on the arguments
- * * file is a simple file. Then only information of this
- * file will be extracted
- * * file is a directory and recursive is false. The children
- * of the directory (if not directories themselves) will be
- * enqueued for extraction
- * * file is a directory and recursive is true. ++ All ++ children
- * of the directory will be enqueued for extraction, even directories
- *
- * No matter how many children are contained within file's hierarchy,
- * only one event is sent when all the children are done.
- */
- public async void harvest (File file) {
- try {
- this.cancellable.reset ();
- var info = yield file.query_info_async (
- HARVESTER_ATTRIBUTES,
- FileQueryInfoFlags.NONE,
- Priority.DEFAULT,
- this.cancellable);
+ private void on_file_harvested (StateMachine state_machine) {
+ var task = state_machine as HarvestingTask;
+ var file = task.origin;
+ message (_("'%s' harvested"), file.get_uri ());
- if (info.get_file_type () == FileType.DIRECTORY) {
- this.origin = file;
- monitor.monitor (file);
- var container = new DummyContainer (file, this.parent);
- this.containers.push_tail (container);
-
- int64 timestamp;
- if (!this.media_db.exists (container.id, out timestamp)) {
- this.media_db.save_container (container);
- }
-
- Idle.add (this.on_idle);
- } else {
- string id;
- if (push_if_changed_or_unknown (file, info, out id)) {
- Idle.add (this.on_idle);
- this.origin = file;
- this.containers.push_tail (this.parent);
- } else {
- // 'Harvesting' here means extraction of metadata (title,
- // codec, bitrate etc) from media files.
- debug (_("File %s does not need harvesting"),
- file.get_uri ());
- harvested (file);
- }
- }
-
- } catch (Error err) {
- warning (_("Failed to harvest file %s: %s"),
- file.get_uri (),
- err.message);
- harvested (file);
- }
+ this.tasks.remove (file);
}
- private void on_extracted_cb (File file,
- GUPnP.DLNAInformation? dlna,
- string mime,
- uint64 size,
- uint64 mtime) {
- if (this.cancellable.is_cancelled ()) {
- harvested (this.origin);
- }
-
- var entry = this.files.peek ();
- if (entry == null) {
- // this event may be triggered by another instance
- // just ignore it
- return;
- }
- if (file == entry) {
- MediaItem item;
- if (dlna == null) {
- item = new Item.simple (this.containers.peek_head (),
- file,
- mime,
- size,
- mtime);
- } else {
- item = Item.create_from_info (this.containers.peek_head (),
- file,
- dlna,
- mime,
- size,
- mtime);
- }
-
- if (item != null) {
- item.parent_ref = this.containers.peek_head ();
- try {
- this.media_db.save_item (item);
- } catch (Error error) {
- // Ignore it for now
- }
- }
-
- this.files.poll ();
- this.do_update ();
- }
- }
-
- private void on_extractor_error_cb (File file, Error error) {
- var entry = this.files.peek ();
- if (entry == null) {
- // this event may be triggered by another instance
- // just ignore it
- return;
- }
-
- if (file == entry) {
- this.files.poll ();
- this.do_update ();
- }
- }
-
- /**
- * If all files of a container were processed, notify the container
- * about this and set the updating signal.
- * Reschedule the iteration and extraction
- */
- private void do_update () {
- if (this.files.size == 0 &&
- this.containers.get_length () != 0) {
- this.containers.peek_head ().updated ();
- this.containers.pop_head ();
- }
-
- Idle.add (this.on_idle);
+ private void on_remove_cancelled_harvester (StateMachine state_machine) {
+ this.trash.remove (state_machine as HarvestingTask);
}
}
diff --git a/src/plugins/media-export/rygel-media-export-harvesting-task.vala b/src/plugins/media-export/rygel-media-export-harvesting-task.vala
new file mode 100644
index 0000000..8240da5
--- /dev/null
+++ b/src/plugins/media-export/rygel-media-export-harvesting-task.vala
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2009 Jens Georg <mail jensge org>.
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using GLib;
+using Gee;
+
+public class Rygel.MediaExport.HarvestingTask : Rygel.StateMachine, GLib.Object {
+ public File origin;
+ private MetadataExtractor extractor;
+ private MediaCache cache;
+ private GLib.Queue<MediaContainer> containers;
+ private Gee.Queue<File> files;
+ private RecursiveFileMonitor monitor;
+ private Regex file_filter;
+ private string flag;
+ private MediaContainer parent;
+
+ public Cancellable cancellable { get; set; }
+
+ private const string HARVESTER_ATTRIBUTES =
+ FILE_ATTRIBUTE_STANDARD_NAME + "," +
+ FILE_ATTRIBUTE_STANDARD_TYPE + "," +
+ FILE_ATTRIBUTE_TIME_MODIFIED + "," +
+ FILE_ATTRIBUTE_STANDARD_SIZE;
+
+
+ public HarvestingTask (MetadataExtractor extractor,
+ RecursiveFileMonitor monitor,
+ File file,
+ MediaContainer parent,
+ string? flag = null) {
+ this.extractor = extractor;
+ this.origin = file;
+ this.parent = parent;
+
+ try {
+ this.cache = MediaCache.get_default ();
+ } catch (Error error) {
+ assert_not_reached ();
+ }
+
+ this.extractor.extraction_done.connect (on_extracted_cb);
+ this.extractor.error.connect (on_extractor_error_cb);
+
+ this.files = new LinkedList<File> ();
+ this.containers = new GLib.Queue<MediaContainer> ();
+ this.monitor = monitor;
+ this.cancellable = new Cancellable ();
+ this.flag = flag;
+ var config = MetaConfig.get_default ();
+
+ try {
+ var extensions = config.get_string_list ("MediaExport",
+ "include-filter");
+
+ // never trust user input
+ string[] escaped_extensions = new string[0];
+ foreach (var extension in extensions) {
+ escaped_extensions += Regex.escape_string (extension);
+ }
+
+ var list = string.joinv ("|", escaped_extensions);
+ file_filter = new Regex ("(%s)$".printf (list),
+ RegexCompileFlags.CASELESS |
+ RegexCompileFlags.OPTIMIZE);
+ } catch (Error error) {
+ file_filter = null;
+ }
+ }
+
+ /**
+ * Extract all metainformation from a given file.
+ *
+ * What action will be taken depends on the arguments
+ * * file is a simple file. Then only information of this
+ * file will be extracted
+ * * file is a directory and recursive is false. The children
+ * of the directory (if not directories themselves) will be
+ * enqueued for extraction
+ * * file is a directory and recursive is true. ++ All ++ children
+ * of the directory will be enqueued for extraction, even directories
+ *
+ * No matter how many children are contained within file's hierarchy,
+ * only one event is sent when all the children are done.
+ */
+ public async void run () {
+ try {
+ var info = yield this.origin.query_info_async (
+ HARVESTER_ATTRIBUTES,
+ FileQueryInfoFlags.NONE,
+ Priority.DEFAULT,
+ this.cancellable);
+
+ if (process_file (this.origin, info, this.parent)) {
+ if (info.get_file_type () != FileType.DIRECTORY) {
+ this.containers.push_tail (this.parent);
+ }
+ Idle.add (this.on_idle);
+ } else {
+ this.completed ();
+ }
+ } catch (Error err) {
+ warning (_("Failed to harvest file %s: %s"),
+ this.origin.get_uri (),
+ err.message);
+ this.completed ();
+ }
+ }
+
+ private bool push_if_changed_or_unknown (File file,
+ FileInfo info,
+ out string id) {
+ id = Checksum.compute_for_string (ChecksumType.MD5, file.get_uri ());
+ int64 timestamp;
+ try {
+ if (this.cache.exists (id, out timestamp)) {
+ int64 mtime = (int64) info.get_attribute_uint64 (
+ FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ if (mtime > timestamp) {
+ this.files.offer (file);
+
+ return true;
+ } else {
+ // check size
+ var size = info.get_size ();
+ var item = cache.get_item (id);
+ if (item.size != size) {
+ this.files.offer (file);
+
+ return true;
+ }
+ }
+ } else {
+ this.files.offer (file);
+
+ return true;
+ }
+ } catch (Error error) {
+ warning (_("Failed to query database: %s"), error.message);
+ }
+
+ return false;
+ }
+
+ private bool process_file (File file,
+ FileInfo info,
+ MediaContainer parent) {
+ if (info.get_name ()[0] == '.') {
+ return false;
+ }
+
+ if (info.get_file_type () == FileType.DIRECTORY) {
+ monitor.monitor (file);
+ var container = new DummyContainer (file, parent);
+ this.containers.push_tail (container);
+ try {
+ int64 timestamp;
+ if (!this.cache.exists (container.id, out timestamp)) {
+ this.cache.save_container (container);
+ }
+ } catch (Error err) {
+ warning (_("Failed to update database: %s"), err.message);
+
+ return false;
+ }
+
+ return true;
+ } else {
+ string id;
+
+ // Let's see if the file is wanted
+ if (file_filter != null &&
+ !file_filter.match (file.get_uri ())) {
+ return false;
+ }
+
+ return push_if_changed_or_unknown (file, info, out id);
+ }
+ }
+
+ private bool process_children (GLib.List<FileInfo>? list) {
+ if (list == null || this.cancellable.is_cancelled ()) {
+ return false;
+ }
+
+ var parent_container = (DummyContainer) this.containers.peek_head ();
+
+ foreach (var info in list) {
+ var dir = parent_container.file;
+ var file = dir.get_child (info.get_name ());
+ parent_container.seen (Item.get_id (file));
+ process_file (file, info, parent_container);
+ }
+
+ return true;
+ }
+
+ private async void enumerate_directory (File directory) {
+ try {
+ var enumerator = yield directory.enumerate_children_async (
+ HARVESTER_ATTRIBUTES,
+ FileQueryInfoFlags.NONE,
+ Priority.DEFAULT,
+ this.cancellable);
+
+ GLib.List<FileInfo> list = null;
+ do {
+ list = yield enumerator.next_files_async (256,
+ Priority.DEFAULT,
+ this.cancellable);
+ } while (process_children (list));
+
+ yield enumerator.close_async (Priority.DEFAULT, this.cancellable);
+ } catch (Error err) {
+ warning (_("failed to enumerate folder: %s"), err.message);
+ }
+
+ cleanup_database (this.containers.peek_head () as DummyContainer);
+ this.do_update ();
+ }
+
+ private void cleanup_database (DummyContainer container) {
+ // delete all children which are not in filesystem anymore
+ container = (DummyContainer) this.containers.peek_head ();
+ try {
+ foreach (var child in container.children) {
+ this.cache.remove_by_id (child);
+ }
+ } catch (DatabaseError err) {
+ warning (_("Failed to get children of container %s: %s"),
+ container.id,
+ err.message);
+ }
+
+ }
+
+ private bool on_idle () {
+ if (this.cancellable.is_cancelled ()) {
+ return false;
+ }
+
+ if (this.files.size > 0) {
+ var candidate = this.files.peek ();
+ this.extractor.extract (candidate);
+ } else if (this.containers.get_length () > 0) {
+ var container = this.containers.peek_head () as DummyContainer;
+ var directory = container.file;
+ enumerate_directory (directory);
+ } else {
+ // nothing to do
+ if (this.flag != null) {
+ try {
+ this.cache.flag_object (Item.get_id (this.origin),
+ this.flag);
+ } catch (Error error) {};
+ }
+ this.completed ();
+ }
+
+ return false;
+ }
+
+ private void on_extracted_cb (File file,
+ GUPnP.DLNAInformation? dlna,
+ string mime,
+ uint64 size,
+ uint64 mtime) {
+ if (this.cancellable.is_cancelled ()) {
+ this.completed ();
+ }
+
+ var entry = this.files.peek ();
+ if (entry == null) {
+ // this event may be triggered by another instance
+ // just ignore it
+ return;
+ }
+ if (file == entry) {
+ MediaItem item;
+ if (dlna == null) {
+ item = new Item.simple (this.containers.peek_head (),
+ file,
+ mime,
+ size,
+ mtime);
+ } else {
+ item = Item.create_from_info (this.containers.peek_head (),
+ file,
+ dlna,
+ mime,
+ size,
+ mtime);
+ }
+
+ if (item != null) {
+ item.parent_ref = this.containers.peek_head ();
+ try {
+ this.cache.save_item (item);
+ } catch (Error error) {
+ // Ignore it for now
+ }
+ }
+
+ this.files.poll ();
+ this.do_update ();
+ }
+ }
+
+ private void on_extractor_error_cb (File file, Error error) {
+ var entry = this.files.peek ();
+ if (entry == null) {
+ // this event may be triggered by another instance
+ // just ignore it
+ return;
+ }
+
+ if (file == entry) {
+ this.files.poll ();
+ this.do_update ();
+ }
+ }
+
+ /**
+ * If all files of a container were processed, notify the container
+ * about this and set the updating signal.
+ * Reschedule the iteration and extraction
+ */
+ private void do_update () {
+ if (this.files.size == 0 &&
+ this.containers.get_length () != 0) {
+ this.containers.peek_head ().updated ();
+ this.containers.pop_head ();
+ }
+
+ Idle.add (this.on_idle);
+ }
+}
diff --git a/src/plugins/media-export/rygel-media-export-root-container.vala b/src/plugins/media-export/rygel-media-export-root-container.vala
index 0dca896..af40bd6 100644
--- a/src/plugins/media-export/rygel-media-export-root-container.vala
+++ b/src/plugins/media-export/rygel-media-export-root-container.vala
@@ -26,10 +26,9 @@ using GUPnP;
*/
public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
private MetadataExtractor extractor;
- private HashMap<File, Harvester> harvester;
private RecursiveFileMonitor monitor;
private DBusService service;
- private Gee.List<Harvester> harvester_trash;
+ private Harvester harvester;
private static MediaContainer instance = null;
@@ -66,7 +65,7 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
public void add_uri (string uri) {
var file = File.new_for_commandline_arg (uri);
- this.harvest (file, this, "DBUS");
+ this.harvester.schedule (file, this, "DBUS");
}
public void remove_uri (string uri) {
@@ -74,7 +73,7 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
var id = Checksum.compute_for_string (ChecksumType.MD5,
file.get_uri ());
- cancel_harvester (file);
+ this.harvester.cancel (file);
try {
this.media_db.remove_by_id (id);
} catch (Error error) {
@@ -262,13 +261,11 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
base (db, "0", "MediaExportRoot");
this.extractor = new MetadataExtractor ();
-
- this.harvester = new HashMap<File, Harvester> (file_hash, file_equal);
- this.harvester_trash = new ArrayList<Harvester> ();
-
this.monitor = new RecursiveFileMonitor (null);
this.monitor.changed.connect (this.on_file_changed);
+ this.harvester = new Harvester (this.extractor, this.monitor);
+
try {
this.service = new DBusService (this);
} catch (Error err) {
@@ -297,7 +294,7 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
var id = Checksum.compute_for_string (ChecksumType.MD5,
file.get_uri ());
ids.remove (id);
- this.harvest (file);
+ this.harvester.schedule (file, this);
}
}
@@ -344,50 +341,6 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
this.updated ();
}
- private void on_file_harvested (Harvester harvester,
- File file) {
- message (_("'%s' harvested"), file.get_uri ());
-
- this.harvester.remove (file);
- }
-
- private void on_remove_cancelled_harvester (Harvester harvester,
- File file) {
- this.harvester_trash.remove (harvester);
- }
-
- private void cancel_harvester (File file) {
- if (this.harvester.contains (file)) {
- var harvester = this.harvester[file];
- harvester.harvested.disconnect (this.on_file_harvested);
- harvester.cancellable.cancel ();
- harvester.harvested.connect (this.on_remove_cancelled_harvester);
- this.harvester_trash.add (harvester);
- }
- }
-
- private void harvest (File file,
- MediaContainer parent = this,
- string? flag = null) {
- if (this.extractor == null) {
- warning (_("No Metadata extractor available. Will not crawl"));
-
- return;
- }
-
- // Cancel currently running harvester
- cancel_harvester (file);
-
- var harvester = new Harvester (parent,
- this.media_db,
- this.extractor,
- this.monitor,
- flag);
- harvester.harvested.connect (this.on_file_harvested);
- this.harvester[file] = harvester;
- harvester.harvest (file);
- }
-
private void on_file_changed (File file,
File? other,
FileMonitorEvent event) {
@@ -405,7 +358,7 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
as MediaContainer;
assert (parent_container != null);
- this.harvest (file, parent_container);
+ this.harvester.schedule (file, parent_container);
} catch (DatabaseError error) {
warning (_("Error fetching object '%s' from database: %s"),
id,
@@ -416,7 +369,7 @@ public class Rygel.MediaExport.RootContainer : Rygel.MediaExport.DBContainer {
var id = Checksum.compute_for_string (ChecksumType.MD5,
file.get_uri ());
- cancel_harvester (file);
+ this.harvester.cancel (file);
try {
// the full object is fetched instead of simply calling
// exists because we need the parent to signalize the
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]