Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2254)

Unified Diff: ui/file_manager/file_manager/background/js/media_scanner.js

Issue 1038433002: Update scanning to scan files in small batches (well batches of 1)...this fixes an issue where scan… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Respond to review comments. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | ui/file_manager/file_manager/background/js/media_scanner_unittest.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/file_manager/file_manager/background/js/media_scanner.js
diff --git a/ui/file_manager/file_manager/background/js/media_scanner.js b/ui/file_manager/file_manager/background/js/media_scanner.js
index 4a6227dedbf9d362cb12be7406ea666c3ce2ad25..02e411e5ceb444eb9b5636f9bcd9724e668f429e 100644
--- a/ui/file_manager/file_manager/background/js/media_scanner.js
+++ b/ui/file_manager/file_manager/background/js/media_scanner.js
@@ -12,11 +12,22 @@ importer.MediaScanner = function() {};
/**
* Initiates scanning.
*
- * @param {!Array.<!Entry>} entries Must be non-empty.
+ * @param {!DirectoryEntry} directory
* @return {!importer.ScanResult} ScanResult object representing the scan
* job both while in-progress and when completed.
*/
-importer.MediaScanner.prototype.scan;
+importer.MediaScanner.prototype.scanDirectory;
+
+/**
+ * Initiates scanning.
+ *
+ * @param {!Array<!FileEntry>} entries Must be non-empty, and all entires
+ * must be of a supported media type. Individually supplied files
+ * are not subject to deduplication.
+ * @return {!importer.ScanResult} ScanResult object representing the scan
+ * job for the explicitly supplied entries.
+ */
+importer.MediaScanner.prototype.scanFiles;
/**
* Adds an observer, which will be notified on scan events.
@@ -57,7 +68,7 @@ importer.DefaultMediaScanner =
return new importer.DefaultScanResult(hashGenerator);
};
- /** @private {!Array.<!importer.ScanObserver>} */
+ /** @private {!Array<!importer.ScanObserver>} */
this.observers_ = [];
/**
@@ -90,11 +101,35 @@ importer.DefaultMediaScanner.prototype.removeObserver = function(observer) {
};
/** @override */
-importer.DefaultMediaScanner.prototype.scan = function(entries) {
- if (entries.length == 0) {
- throw new Error('Cannot scan empty list of entries.');
- }
+importer.DefaultMediaScanner.prototype.scanDirectory = function(directory) {
+ var scan = this.createScanResult_();
+ var watcher = this.watcherFactory_(
+ /** @this {importer.DefaultMediaScanner} */
+ function() {
+ scan.invalidateScan();
+ this.notify_(importer.ScanEvent.INVALIDATED, scan);
+ }.bind(this));
+
+ this.crawlDirectory_(directory, watcher)
+ .then(this.scanMediaFiles_.bind(this, scan))
+ .then(scan.resolve)
+ .catch(scan.reject);
+
+ scan.whenFinal()
+ .then(
+ /** @this {importer.DefaultMediaScanner} */
+ function() {
+ this.notify_(importer.ScanEvent.FINALIZED, scan);
+ }.bind(this));
+ return scan;
+};
+
+/** @override */
+importer.DefaultMediaScanner.prototype.scanFiles = function(entries) {
+ if (entries.length === 0) {
+ throw new Error('Cannot scan empty list.');
+ }
var scan = this.createScanResult_();
var watcher = this.watcherFactory_(
/** @this {importer.DefaultMediaScanner} */
@@ -103,8 +138,7 @@ importer.DefaultMediaScanner.prototype.scan = function(entries) {
this.notify_(importer.ScanEvent.INVALIDATED, scan);
}.bind(this));
- var scanPromises = entries.map(
- this.scanEntry_.bind(this, scan, watcher));
+ var scanPromises = entries.map(this.onUniqueFileFound_.bind(this, scan));
Promise.all(scanPromises)
.then(scan.resolve)
@@ -120,6 +154,40 @@ importer.DefaultMediaScanner.prototype.scan = function(entries) {
return scan;
};
+/** @const {number} */
+importer.DefaultMediaScanner.SCAN_BATCH_SIZE = 1;
+
+/**
+ * @param {!importer.DefaultScanResult} scan
+ * @param {!Array<!FileEntry>} entries
+ * @return {!Promise} Resolves when scanning is finished.
+ * @private
+ */
+importer.DefaultMediaScanner.prototype.scanMediaFiles_ =
+ function(scan, entries) {
+ var handleFileEntry = this.onFileEntryFound_.bind(this, scan);
+
+ /**
+ * @param {number} begin The beginning offset in the list of entries
+ * to process.
+ * @return {!Promise}
+ */
+ var scanChunk = function(begin) {
+ // the second arg to slice is an exclusive end index, so we +1 batch size.
+ var end = begin + importer.DefaultMediaScanner.SCAN_BATCH_SIZE + 1;
+ return Promise.all(
+ entries.slice(begin, end).map(handleFileEntry))
+ .then(
+ function() {
+ if (end < entries.length) {
+ return scanChunk(end);
+ }
+ });
+ };
+
+ return scanChunk(0);
+};
+
/**
* Notifies all listeners at some point in the near future.
*
@@ -136,55 +204,21 @@ importer.DefaultMediaScanner.prototype.notify_ = function(event, result) {
};
/**
- * Resolves the entry by either:
- * a) recursing on it (when a directory)
- * b) adding it to the results (when a media type file)
- * c) ignoring it, if neither a or b
- *
- * @param {!importer.DefaultScanResult} scan
- * @param {!importer.DirectoryWatcher} watcher
- * @param {!Entry} entry
- *
- * @return {!Promise}
- * @private
- */
-importer.DefaultMediaScanner.prototype.scanEntry_ =
- function(scan, watcher, entry) {
-
- if (entry.isDirectory) {
- return this.scanDirectory_(
- scan,
- watcher,
- /** @type {!DirectoryEntry} */ (entry));
- }
-
- // Since this entry is by client code (and presumably the user)
- // we add it directly (skipping over the history dupe check).
- return this.onUniqueFileFound_(scan, /** @type {!FileEntry} */ (entry));
-};
-
-/**
- * Finds all files beneath directory.
+ * Finds all files media files beneath directory AND adds directory
+ * watchers for each encountered directory.
*
- * @param {!importer.DefaultScanResult} scan
+ * @param {!DirectoryEntry} directory
* @param {!importer.DirectoryWatcher} watcher
- * @param {!DirectoryEntry} entry
- * @return {!Promise}
+ * @return {!Promise<!Array<!FileEntry>>}
* @private
*/
-importer.DefaultMediaScanner.prototype.scanDirectory_ =
- function(scan, watcher, entry) {
- // Collect promises for all files being added to results.
- // The directory scan promise can't resolve until all
- // file entries are completely promised.
- var promises = [];
+importer.DefaultMediaScanner.prototype.crawlDirectory_ =
+ function(directory, watcher) {
+ var mediaFiles = [];
return fileOperationUtil.findEntriesRecursively(
- entry,
- /**
- * @param {!Entry} entry
- * @this {importer.DefaultMediaScanner}
- */
+ directory,
+ /** @param {!Entry} entry */
function(entry) {
if (watcher.triggered) {
return;
@@ -195,14 +229,14 @@ importer.DefaultMediaScanner.prototype.scanDirectory_ =
// function findEntriesRecursively does that. So we
// just watch the directory for modifications, and that's it.
watcher.addDirectory(/** @type {!DirectoryEntry} */(entry));
- return;
+ } else if (importer.isEligibleType(entry)) {
+ mediaFiles.push(/** @type {!FileEntry} */ (entry));
}
-
- promises.push(
- this.onFileEntryFound_(scan, /** @type {!FileEntry} */(entry)));
-
- }.bind(this))
- .then(Promise.all.bind(Promise, promises));
+ })
+ .then(
+ function() {
+ return mediaFiles;
+ });
};
/**
@@ -343,7 +377,7 @@ importer.DefaultScanResult = function(hashGenerator) {
/**
* List of file entries found while scanning.
- * @private {!Array.<!FileEntry>}
+ * @private {!Array<!FileEntry>}
*/
this.fileEntries_ = [];
« no previous file with comments | « no previous file | ui/file_manager/file_manager/background/js/media_scanner_unittest.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698