This commit is contained in:
Andrew Sutherland 2008-07-05 20:37:26 -07:00
Родитель d0f2f5d518
Коммит 9e44f853a0
3 изменённых файлов: 186 добавлений и 30 удалений

Просмотреть файл

@ -52,11 +52,8 @@ var gloda = {
this.strings = document.getElementById("gloda-strings");
},
onMenuItemCommand: function(e) {
GlodaIndexer.init(window);
GlodaIndexer.indexEverything();
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
promptService.alert(window, this.strings.getString("helloMessageTitle"),
this.strings.getString("helloMessage"));
},
};

Просмотреть файл

@ -281,6 +281,33 @@ let GlodaDatastore = {
wrappedStatement.initialize(statement);
return wrappedStatement;
},
/** Simple nested transaction support as a performance optimization. */
_transactionDepth: 0,
_transactionGood: false,
_beginTransaction: function gloda_ds_beginTransaction() {
if (this._transactionDepth == 0) {
this.dbConnection.beginTransaction();
this._transactionGood = true;
}
this._transactionDepth--;
},
_commitTransaction: function gloda_ds_commitTransaction() {
this._transactionDepth--;
if (this._transactionDepth == 0) {
if (this._transactionGood)
this.dbConnection.commitTransaction();
else
this.dbConnection.rollbackTransaction();
}
},
_rollbackTransaction: function gloda_ds_rollbackTransaction() {
this._transactionDepth--;
this._transactionGood = false;
if (this._transactionDepth == 0) {
this.dbConnection.rollbackTransaction();
}
},
/* ********** Attribute Definitions ********** */
/** Maps (attribute def) compound names to the GlodaAttributeDef objects. */
@ -691,7 +718,7 @@ let GlodaDatastore = {
insertMessageAttributes: function gloda_ds_insertMessageAttributes(aMessage,
aAttributes) {
let imas = this._insertMessageAttributeStatement;
this.dbConnection.beginTransaction();
this._beginTransaction();
try {
for (let iAttribute=0; iAttribute < aAttributes.length; iAttribute++) {
let attribValueTuple = aAttributes[iAttribute];
@ -711,10 +738,10 @@ let GlodaDatastore = {
imas.execute();
}
this.dbConnection.commitTransaction();
this._commitTransaction();
}
catch (ex) {
this.dbConnection.rollbackTransaction();
this._rollbackTransaction();
throw ex;
}
},

Просмотреть файл

@ -118,45 +118,177 @@ function fixIterator(aEnum, aIface) {
let GlodaIndexer = {
_datastore: GlodaDatastore,
_log: Log4Moz.Service.getLogger("gloda.indexer"),
_msgwindow: null,
_domWindow: null,
_inited: false,
init: function gloda_index_init(aDOMWindow) {
if (this._inited)
return;
this._domWindow = aDOMWindow;
let mailSession = Cc["@mozilla.org/messenger/services/session;1"].
getService(Ci.nsIMsgMailSession);
this._msgWindow = mailSession.topmostMsgWindow;
},
/** Track whether indexing is active (we have timers in-flight). */
_indexingActive: false,
get indexing() { return this._indexingActive; },
/** You can turn on indexing, but you can't turn it off! */
set indexing(aShouldIndex) {
if (!this._indexingActive && aShouldIndex) {
this._indexingActive = true;
this._domWindow.setTimeout(this._wrapIncrementalIndex, this._indexInterval, this);
}
},
/** The nsIMsgFolder we are indexing, or null if we aren't. */
_indexingFolder: null,
/** The iterator we are using to traverse _indexingFolder. */
_indexingIterator: null,
_indexingCount: 0,
/**
* A list of things yet to index. Contents will be lists matching one of the
* following patterns:
* - ['account', account object]
* - ['folder', folder URI]
* - ['message', folder URI, message key, message ID]
*/
_indexQueue: [],
/**
* The time interval, in milliseconds between performing indexing work.
* This may be altered by user session (in)activity.
*/
_indexInterval: 100,
/**
* Number of indexing 'tokens' we are allowed to consume before yielding for
* each incremental pass. Consider a single token equal to indexing a single
* medium-sized message. This may be altered by user session (in)activity.
*/
_indexTokens: 10,
_wrapIncrementalIndex: function gloda_index_wrapIncrementalIndex(aThis) {
aThis.incrementalIndex();
},
incrementalIndex: function gloda_index_incrementalIndex() {
this._log.debug("index wake-up!");
GlodaDatastore._beginTransaction();
for (let tokensLeft=this._indexTokens; tokensLeft > 0; tokensLeft--) {
if (this._indexingFolder != null) {
try {
this._indexMessage(this._indexingIterator.next());
this._indexingCount++;
if (this._indexingCount % 50 == 1) {
this._log.debug("indexed " + this._indexingCount + " in " +
this._indexingFolder.prettiestName);
}
}
catch (ex) {
this._log.debug("Done with indexing folder because: " + ex);
this._indexingFolder = null;
this._indexingIterator = null;
}
}
else if (this._indexQueue.length) {
let item = this._indexQueue.shift();
let itemType = item[0];
if (itemType == "account") {
this.indexAccount(item[1]);
}
else if (itemType == "folder") {
let folderURI = item[1];
this._log.debug("Folder URI: " + folderURI);
let rdfService = Cc['@mozilla.org/rdf/rdf-service;1'].
getService(Ci.nsIRDFService);
let folder = rdfService.GetResource(folderURI);
if (folder instanceof Ci.nsIMsgFolder) {
this._indexingFolder = folder;
this._log.debug("Starting indexing of folder: " +
folder.prettiestName);
// The msf may need to be created or otherwise updated, updateFolder will
// do this for us. (GetNewMessages would also do it, but we would be
// triggering new message retrieval in that case, which we don't actually
// desire.
// TODO: handle password-protected local cache potentially triggering a
// password prompt here...
try {
//this._indexingFolder.updateFolder(this._msgWindow);
let msgDatabase = folder.getMsgDatabase(this._msgWindow);
this._indexingIterator = Iterator(fixIterator(
//folder.getMessages(this._msgWindow),
msgDatabase.EnumerateMessages(),
Ci.nsIMsgDBHdr));
}
catch (ex) {
this._log.error("Problem indexing folder: " +
folder.prettiestName + ", skipping.");
this._log.error("Error was: " + ex);
this._indexingFolder = null;
this._indexingIterator = null;
}
}
}
}
else {
this._log.info("Done indexing, disabling timer renewal.");
this._indexingActive = false;
break;
}
}
GlodaDatastore._commitTransaction();
if (this.indexing)
this._domWindow.setTimeout(this._wrapIncrementalIndex, this._indexInterval,
this);
},
indexEverything: function glodaIndexEverything() {
this._log.info("Indexing Everything");
this._log.info("Queueing all accounts for indexing.");
let msgAccountManager = Cc["@mozilla.org/messenger/account-manager;1"].
getService(Ci.nsIMsgAccountManager);
let blah = [this.indexAccount(account) for each
this._indexQueue = this._indexQueue.concat(
[["account", account] for each
(account in fixIterator(msgAccountManager.accounts,
Ci.nsIMsgAccount))];
this._log.info("Indexing Everything");
Ci.nsIMsgAccount))]);
this.indexing = true;
},
indexAccount: function glodaIndexAccount(aAccount) {
this._log.info(">>> Indexing Account: " + aAccount.key);
let rootFolder = aAccount.incomingServer.rootFolder;
if (rootFolder instanceof Ci.nsIMsgFolder) {
let blah = [this.indexFolder(folder) for each
(folder in fixIterator(rootFolder.subFolders, Ci.nsIMsgFolder))];
this._log.info("Queueing account folders for indexing: " + aAccount.key);
this._indexQueue = this._indexQueue.concat(
[["folder", folder.URI] for each
(folder in fixIterator(rootFolder.subFolders, Ci.nsIMsgFolder))]);
this.indexing = true;
}
else {
this._log.info(" Skipping Account, root folder not nsIMsgFolder");
this._log.info("Skipping Account, root folder not nsIMsgFolder");
}
this._log.info("<<< Indexing Account: " + aAccount.key);
},
indexFolder: function glodaIndexFolder(aFolder) {
this._log.info(" >>> Indexing Folder: " + aFolder.prettiestName);
for each (let msgHdr in fixIterator(aFolder.getMessages(null),
Ci.nsIMsgDBHdr)) {
this._log.info(" >>> Indexing Message: " + msgHdr.messageId +
" (" + msgHdr.subject + ")");
this.indexMessage(msgHdr);
this._log.info(" <<< Indexing Message: " + msgHdr.messageId);
}
this._log.info(" <<< Indexing Folder: " + aFolder.prettiestName);
this._log.info("Queue-ing folder for indexing: " + aFolder.prettiestName);
this._indexQueue.push(["folder", aFolder.URI]);
this.indexing = true;
},
/**
@ -177,7 +309,7 @@ let GlodaIndexer = {
return aMsgHdr.mime2DecodedSubject;
},
indexMessage: function glodaIndexMessage(aMsgHdr) {
_indexMessage: function gloda_index_indexMessage(aMsgHdr) {
// -- Find/create the conversation the message belongs to.
// Our invariant is that all messages that exist in the database belong to