From 5040fba8bbb8485cf783ef96112bda1ab2bba857 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Thu, 15 Aug 2013 23:21:57 -0400 Subject: [PATCH] Use async DB for Zotero.Translators.init() Zotero.Translators.init() now returns a promise. This will temporarily break all the Zotero.Translators.get* calls. --- .../preferences/preferences_advanced.js | 18 +- chrome/content/zotero/xpcom/schema.js | 53 ++---- .../zotero/xpcom/translation/translator.js | 174 +++++++++--------- 3 files changed, 112 insertions(+), 133 deletions(-) diff --git a/chrome/content/zotero/preferences/preferences_advanced.js b/chrome/content/zotero/preferences/preferences_advanced.js index a5069ee0b..f7b7c949e 100644 --- a/chrome/content/zotero/preferences/preferences_advanced.js +++ b/chrome/content/zotero/preferences/preferences_advanced.js @@ -128,11 +128,13 @@ Zotero_Preferences.Advanced = { null, null, null, {}); if (index == 0) { - Zotero.Schema.resetTranslatorsAndStyles(function (xmlhttp, updated) { + Zotero.Schema.resetTranslatorsAndStyles() + .then(function () { if (Zotero_Preferences.Export) { Zotero_Preferences.Export.populateQuickCopyList(); } - }); + }) + .done(); } }, @@ -152,11 +154,13 @@ Zotero_Preferences.Advanced = { null, null, null, {}); if (index == 0) { - Zotero.Schema.resetTranslators(function () { + Zotero.Schema.resetTranslators() + .then(function () { if (Zotero_Preferences.Export) { Zotero_Preferences.Export.populateQuickCopyList(); } - }); + }) + .done(); } }, @@ -176,11 +180,13 @@ Zotero_Preferences.Advanced = { null, null, null, {}); if (index == 0) { - Zotero.Schema.resetStyles(function (xmlhttp, updated) { + Zotero.Schema.resetStyles() + .then(function () { if (Zotero_Preferences.Export) { Zotero_Preferences.Export.populateQuickCopyList(); } - }); + }) + .done(); } }, diff --git a/chrome/content/zotero/xpcom/schema.js b/chrome/content/zotero/xpcom/schema.js index 316324ff0..0dc21698c 100644 --- a/chrome/content/zotero/xpcom/schema.js +++ b/chrome/content/zotero/xpcom/schema.js @@ -142,13 +142,7 @@ Zotero.Schema = new function(){ // After a delay, start update of bundled files and repo updates Zotero.initializationPromise .delay(5000) - .then(function () { - Zotero.UnresponsiveScriptIndicator.disable(); - return Zotero.Schema.updateBundledFiles(null, false, true) - .finally(function () { - Zotero.UnresponsiveScriptIndicator.enable(); - }); - }) + .then(function () Zotero.Schema.updateBundledFiles(null, false, true)) .done(); return updated; @@ -375,6 +369,7 @@ Zotero.Schema = new function(){ * @param {Boolean} [skipDeleteUpdated] Skip updating of the file deleting version -- * since deleting uses a single version table key, * it should only be updated the last time through + * @return {Promise} */ this.updateBundledFiles = function(mode, skipDeleteUpdate, runRemoteUpdateWhenComplete) { if (_localUpdateInProgress) return Q(); @@ -1038,20 +1033,16 @@ Zotero.Schema = new function(){ var translatorsDir = Zotero.getTranslatorsDirectory(); translatorsDir.remove(true); Zotero.getTranslatorsDirectory(); // recreate directory - Zotero.Translators.init(); - this.updateBundledFiles('translators', null, false); - - var stylesDir = Zotero.getStylesDirectory(); - stylesDir.remove(true); - Zotero.getStylesDirectory(); // recreate directory - Zotero.Styles.init(); - this.updateBundledFiles('styles', null, true) + return Zotero.Translators.init() + .then(function () self.updateBundledFiles('translators', null, false)) .then(function () { - if (callback) { - callback(); - } + var stylesDir = Zotero.getStylesDirectory(); + stylesDir.remove(true); + Zotero.getStylesDirectory(); // recreate directory + Zotero.Styles.init(); + return self.updateBundledFiles('styles', null, true); }) - .done(); + .then(callback); } @@ -1067,14 +1058,9 @@ Zotero.Schema = new function(){ var translatorsDir = Zotero.getTranslatorsDirectory(); translatorsDir.remove(true); Zotero.getTranslatorsDirectory(); // recreate directory - Zotero.Translators.init(); - this.updateBundledFiles('translators', null, true) - .then(function () { - if (callback) { - callback(); - } - }) - .done(); + return Zotero.Translators.init() + .then(function () self.updateBundledFiles('translators', null, true)) + .then(callback); } @@ -1090,14 +1076,9 @@ Zotero.Schema = new function(){ var stylesDir = Zotero.getStylesDirectory(); stylesDir.remove(true); Zotero.getStylesDirectory(); // recreate directory - Zotero.Styles.init(); - this.updateBundledFiles('styles', null, true) - .then(function () { - if (callback) { - callback(); - } - }) - .done(); + return Zotero.Styles.init() + .then(function () self.updateBundledFiles('styles', null, true)) + .then(callback); } @@ -1554,7 +1535,7 @@ Zotero.Schema = new function(){ } // Rebuild caches - Zotero.Translators.init(); + yield Zotero.Translators.init(); Zotero.Styles.init(); } catch (e) { diff --git a/chrome/content/zotero/xpcom/translation/translator.js b/chrome/content/zotero/xpcom/translation/translator.js index 9c5137202..657a27fb8 100644 --- a/chrome/content/zotero/xpcom/translation/translator.js +++ b/chrome/content/zotero/xpcom/translation/translator.js @@ -37,115 +37,105 @@ Zotero.Translators = new function() { /** * Initializes translator cache, loading all relevant translators into memory */ - this.init = function() { + this.init = Q.async(function() { _initialized = true; var start = (new Date()).getTime(); var transactionStarted = false; - Zotero.UnresponsiveScriptIndicator.disable(); + _cache = {"import":[], "export":[], "web":[], "search":[]}; + _translators = {}; - // Use try/finally so that we always reset the unresponsive script warning - try { - _cache = {"import":[], "export":[], "web":[], "search":[]}; - _translators = {}; + var dbCacheResults = yield Zotero.DB.queryAsync("SELECT leafName, translatorJSON, "+ + "code, lastModifiedTime FROM translatorCache"); + var dbCache = {}; + for each(var cacheEntry in dbCacheResults) { + dbCache[cacheEntry.leafName] = cacheEntry; + } + + var i = 0; + var filesInCache = {}; + var contents = Zotero.getTranslatorsDirectory().directoryEntries; + while(contents.hasMoreElements()) { + var file = contents.getNext().QueryInterface(Components.interfaces.nsIFile); + var leafName = file.leafName; + if(!(/^[^.].*\.js$/.test(leafName))) continue; + var lastModifiedTime = file.lastModifiedTime; - var dbCacheResults = Zotero.DB.query("SELECT leafName, translatorJSON, "+ - "code, lastModifiedTime FROM translatorCache"); - var dbCache = {}; - for each(var cacheEntry in dbCacheResults) { - dbCache[cacheEntry.leafName] = cacheEntry; + var dbCacheEntry = false; + if(dbCache[leafName]) { + filesInCache[leafName] = true; + if(dbCache[leafName].lastModifiedTime == lastModifiedTime) { + dbCacheEntry = dbCache[file.leafName]; + } } - var i = 0; - var filesInCache = {}; - var contents = Zotero.getTranslatorsDirectory().directoryEntries; - while(contents.hasMoreElements()) { - var file = contents.getNext().QueryInterface(Components.interfaces.nsIFile); - var leafName = file.leafName; - if(!(/^[^.].*\.js$/.test(leafName))) continue; - var lastModifiedTime = file.lastModifiedTime; - - var dbCacheEntry = false; - if(dbCache[leafName]) { - filesInCache[leafName] = true; - if(dbCache[leafName].lastModifiedTime == lastModifiedTime) { - dbCacheEntry = dbCache[file.leafName]; - } - } - - if(dbCacheEntry) { - // get JSON from cache if possible - var translator = new Zotero.Translator(file, dbCacheEntry.translatorJSON, dbCacheEntry.code); - filesInCache[leafName] = true; + // TODO: use async load method instead of constructor + if(dbCacheEntry) { + // get JSON from cache if possible + var translator = new Zotero.Translator(file, dbCacheEntry.translatorJSON, dbCacheEntry.code); + filesInCache[leafName] = true; + } else { + // otherwise, load from file + var translator = new Zotero.Translator(file); + } + + if(translator.translatorID) { + if(_translators[translator.translatorID]) { + // same translator is already cached + translator.logError('Translator with ID '+ + translator.translatorID+' already loaded from "'+ + _translators[translator.translatorID].file.leafName+'"'); } else { - // otherwise, load from file - var translator = new Zotero.Translator(file); - } - - if(translator.translatorID) { - if(_translators[translator.translatorID]) { - // same translator is already cached - translator.logError('Translator with ID '+ - translator.translatorID+' already loaded from "'+ - _translators[translator.translatorID].file.leafName+'"'); - } else { - // add to cache - _translators[translator.translatorID] = translator; - for(var type in TRANSLATOR_TYPES) { - if(translator.translatorType & TRANSLATOR_TYPES[type]) { - _cache[type].push(translator); - } - } - - if(!dbCacheEntry) { - // Add cache misses to DB - if(!transactionStarted) { - transactionStarted = true; - Zotero.DB.beginTransaction(); - } - Zotero.Translators.cacheInDB(leafName, translator.metadataString, translator.cacheCode ? translator.code : null, lastModifiedTime); - delete translator.metadataString; + // add to cache + _translators[translator.translatorID] = translator; + for(var type in TRANSLATOR_TYPES) { + if(translator.translatorType & TRANSLATOR_TYPES[type]) { + _cache[type].push(translator); } } - } - - i++; - } - - // Remove translators from DB as necessary - for(var leafName in dbCache) { - if(!filesInCache[leafName]) { - Zotero.DB.query("DELETE FROM translatorCache WHERE leafName = ?", [leafName]); + + if(!dbCacheEntry) { + yield Zotero.Translators.cacheInDB( + leafName, + translator.metadataString, + translator.cacheCode ? translator.code : null, + lastModifiedTime + ); + delete translator.metadataString; + } } } - // Close transaction - if(transactionStarted) { - Zotero.DB.commitTransaction(); - } - - // Sort by priority - var collation = Zotero.getLocaleCollation(); - var cmp = function (a, b) { - if (a.priority > b.priority) { - return 1; - } - else if (a.priority < b.priority) { - return -1; - } - return collation.compareString(1, a.label, b.label); - } - for(var type in _cache) { - _cache[type].sort(cmp); + i++; + } + + // Remove translators from DB as necessary + for(var leafName in dbCache) { + if(!filesInCache[leafName]) { + yield Zotero.DB.queryAsync( + "DELETE FROM translatorCache WHERE leafName = ?", [leafName] + ); } } - finally { - Zotero.UnresponsiveScriptIndicator.enable(); + + // Sort by priority + var collation = Zotero.getLocaleCollation(); + var cmp = function (a, b) { + if (a.priority > b.priority) { + return 1; + } + else if (a.priority < b.priority) { + return -1; + } + return collation.compareString(1, a.label, b.label); + } + for(var type in _cache) { + _cache[type].sort(cmp); } Zotero.debug("Cached "+i+" translators in "+((new Date()).getTime() - start)+" ms"); - } + }); /** * Gets the translator that corresponds to a given ID @@ -414,8 +404,10 @@ Zotero.Translators = new function() { } this.cacheInDB = function(fileName, metadataJSON, code, lastModifiedTime) { - Zotero.DB.query("REPLACE INTO translatorCache VALUES (?, ?, ?, ?)", - [fileName, metadataJSON, code, lastModifiedTime]); + return Zotero.DB.queryAsync( + "REPLACE INTO translatorCache VALUES (?, ?, ?, ?)", + [fileName, metadataJSON, code, lastModifiedTime] + ); } }