Self-destruct if a transaction is open while trying to scrape, switch collections, click a toolbar button or select an item, and display an error prompting user to restart

This should prevent any chance of data loss from transaction rollback if Firefox crashes, since it removes almost all possibility of modifying Zotero data after an error.

Also replaced commitAllTransactions() call in DB shutdown observer with rollbackAllTransactions(), since the extra safety precaution now shouldn't be necessary.
This commit is contained in:
Dan Stillman 2007-04-25 05:53:32 +00:00
parent a757891ff1
commit a24318ec6a
28 changed files with 192 additions and 50 deletions

View File

@ -117,6 +117,15 @@ var Zotero_Browser = new function() {
* ID as the argument
*/
function scrapeThisPage(saveLocation) {
if (!Zotero.stateCheck()) {
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapeError"));
var desc = Zotero.getString("ingester.scrapeError.transactionInProgress.previousError")
+ ' ' + Zotero.getString("general.restartFirefoxAndTryAgain");
Zotero_Browser.progress.addDescription(desc);
Zotero_Browser.progress.show();
Zotero_Browser.progress.startCloseTimer(8000);
return;
}
_getTabObject(this.tabbrowser.selectedBrowser).translate(saveLocation);
}

View File

@ -85,6 +85,7 @@ var ZoteroPane = new function()
this.showAttachmentNotFoundDialog = showAttachmentNotFoundDialog;
this.relinkAttachment = relinkAttachment;
this.reportErrors = reportErrors;
this.displayErrorMessage = displayErrorMessage;
const DEFAULT_ZPANE_HEIGHT = 300;
const COLLECTIONS_HEIGHT = 125; // minimum height of the collections pane and toolbar
@ -467,6 +468,11 @@ var ZoteroPane = new function()
*/
function newItem(typeID, data)
{
if (!Zotero.stateCheck()) {
this.displayErrorMessage(true);
return;
}
var item = new Zotero.Item(typeID);
for (var i in data)
@ -704,6 +710,11 @@ var ZoteroPane = new function()
function itemSelected()
{
if (!Zotero.stateCheck()) {
this.displayErrorMessage();
return;
}
if (this.itemsView && this.itemsView.selection.count == 1 && this.itemsView.selection.currentIndex != -1)
{
var item = this.itemsView._getItemAtRow(this.itemsView.selection.currentIndex);
@ -1453,15 +1464,23 @@ var ZoteroPane = new function()
function setItemsPaneMessage(msg) {
var elem = document.getElementById('zotero-items-pane-message-box');
while (elem.hasChildNodes()) {
elem.removeChild(elem.firstChild);
}
var msgParts = msg.split("\n\n");
for (var i=0; i<msgParts.length; i++) {
var desc = document.createElement('description');
desc.appendChild(document.createTextNode(msgParts[i]));
elem.appendChild(desc);
}
document.getElementById('zotero-items-pane-content').selectedIndex = 1;
var elem = document.getElementById('zotero-items-pane-message');
elem.value = msg;
}
function clearItemsPaneMessage() {
document.getElementById('zotero-items-pane-content').selectedIndex = 0;
document.getElementById('zotero-items-pane-message').value = '';
}
@ -1527,6 +1546,11 @@ var ZoteroPane = new function()
function newNote(popup, parent, text) {
if (!Zotero.stateCheck()) {
this.displayErrorMessage(true);
return;
}
if (!popup) {
try {
// trim
@ -1629,6 +1653,11 @@ var ZoteroPane = new function()
function addItemFromPage() {
if (!Zotero.stateCheck()) {
this.displayErrorMessage(true);
return;
}
var progressWin = new Zotero.ProgressWindow();
progressWin.changeHeadline(Zotero.getString('ingester.scraping'));
var icon = 'chrome://zotero/skin/treeitem-webpage.png';
@ -1668,6 +1697,11 @@ var ZoteroPane = new function()
*/
function addAttachmentFromPage(link, itemID, noParent)
{
if (!Zotero.stateCheck()) {
this.displayErrorMessage(true);
return;
}
if (!noParent) {
var progressWin = new Zotero.ProgressWindow();
progressWin.changeHeadline(Zotero.getString('save.' + (link ? 'link' : 'attachment')));
@ -1832,6 +1866,38 @@ var ZoteroPane = new function()
var win = ww.openWindow(null, "chrome://zotero/content/errorReport.xul",
"zotero-error-report", "chrome,centerscreen,modal", io);
}
/*
* Display an error message saying that an error has occurred and Firefox
* needs to be restarted.
*
* If |popup| is TRUE, display in popup progress window; otherwise, display
* as items pane message
*/
function displayErrorMessage(popup) {
var reportErrorsStr = Zotero.getString('errorReport.reportErrors');
var reportInstructions =
Zotero.getString('errorReport.reportInstructions', reportErrorsStr)
// Display as popup progress window
if (popup) {
var pw = new Zotero.ProgressWindow();
pw.changeHeadline(Zotero.getString('general.errorHasOccurred'));
var desc = Zotero.getString('general.restartFirefox') + ' '
+ reportInstructions;
pw.addDescription(desc);
pw.show();
pw.startCloseTimer(8000);
}
// Display as items pane message
else {
var msg = Zotero.getString('general.errorHasOccurred') + ' '
+ Zotero.getString('general.restartFirefox') + '\n\n'
+ reportInstructions;
self.setItemsPaneMessage(msg);
}
}
}
window.addEventListener("load", function(e) { ZoteroPane.onLoad(e); }, false);

View File

@ -118,7 +118,7 @@
<menuseparator id="zotero-tb-actions-separator"/>
<menuitem id="zotero-tb-actions-prefs" label="&zotero.toolbar.preferences.label;"
oncommand="window.openDialog('chrome://zotero/content/preferences/preferences.xul', 'zotero-prefs', 'chrome,titlebar,toolbar,' + Zotero.Prefs.get('browser.preferences.instantApply', true) ? 'dialog=no' : 'modal')"/>
<menuitem id="zotero-tb-actions-reportErrors" label="&zotero.toolbar.reportErrors;" command="cmd_zotero_reportErrors" disabled="true"/>
<menuitem id="zotero-tb-actions-reportErrors" command="cmd_zotero_reportErrors" disabled="true"/>
<menuitem id="zotero-tb-actions-documentation" label="&zotero.toolbar.documentation.label;" oncommand="window.open('http://www.zotero.org/documentation/', '', 'menubar=yes,location=yes,toolbar=yes,personalbar=yes,resizable=yes,scrollbars=yes,status=yes');"/>
<menuitem id="zotero-tb-actions-about" label="&zotero.toolbar.about.label;" oncommand="window.openDialog('chrome://zotero/content/about.xul', 'about', 'chrome')"/>
</menupopup>
@ -265,9 +265,7 @@
<!-- Label for displaying messages when items pane is hidden
(e.g. "Advanced search mode — press Enter to search.")-->
<box id="zotero-items-pane-message-box" pack="center" align="center">
<label id="zotero-items-pane-message" />
</box>
<vbox id="zotero-items-pane-message-box" pack="center" align="center"/>
</deck>
</vbox>
@ -352,6 +350,11 @@
break;
}
// Set "Report Errors..." label via property rather than DTD entity,
// since we need to reference it in script elsewhere
document.getElementById('zotero-tb-actions-reportErrors').setAttribute('label',
Zotero.getString('errorReport.reportErrors'));
// Used for loading the changelog after upgrades
if (Zotero.initialURL) {
gBrowser.selectedTab = gBrowser.addTab(Zotero.initialURL);

View File

@ -68,7 +68,7 @@ function onDataDirUpdate(event) {
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(window,
Zotero.getString('general.restartRequired'),
Zotero.getString('general.restartFirefox.singular'),
Zotero.getString('general.restartRequiredForChange'),
buttonFlags,
Zotero.getString('general.restartNow'),
null, null, null, {});

View File

@ -403,6 +403,8 @@ Zotero.DBConnection.prototype.transactionInProgress = function () {
/**
* Safety function used on shutdown to make sure we're not stuck in the
* middle of a transaction
*
* NOTE: No longer used
*/
Zotero.DBConnection.prototype.commitAllTransactions = function () {
if (this.transactionInProgress()) {
@ -418,6 +420,23 @@ Zotero.DBConnection.prototype.commitAllTransactions = function () {
}
/*
* Used on shutdown to rollback all open transactions
*/
Zotero.DBConnection.prototype.rollbackAllTransactions = function () {
if (this.transactionInProgress()) {
var level = this._transactionNestingLevel;
this._transactionNestingLevel = 0;
try {
this.rollbackTransaction();
}
catch (e) {}
return level ? level : true;
}
return false;
}
Zotero.DBConnection.prototype.tableExists = function (table) {
return this._getDBConnection().tableExists(table);
}
@ -530,7 +549,9 @@ Zotero.DBConnection.prototype.observe = function(subject, topic, data) {
return;
}
var level = this.commitAllTransactions();
// NOTE: disabled
//var level = this.commitAllTransactions();
var level = this.rollbackAllTransactions()
if (level) {
level = level === true ? '0' : level;
this._debug("A transaction in DB '" + this._dbName + "' was still open! (level " + level + ")", 2);
@ -776,8 +797,8 @@ Zotero.DBConnection.prototype._getDBConnection = function () {
// Register shutdown handler to call this.onShutdown() for DB backup
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
observerService.addObserver(this, "xpcom-shutdown", false);
observerService = null;
return this._connection;
}

View File

@ -96,6 +96,24 @@ Zotero.ItemTreeView.prototype.setTree = function(treebox)
// Generate the tree contents in a timer to allow message above to display
var paneLoader = function(obj) {
// If a DB transaction is open, display error message and bail
if (!Zotero.stateCheck()) {
if (obj._ownerDocument.defaultView.ZoteroPane) {
obj._ownerDocument.defaultView.ZoteroPane.displayErrorMessage();
/*
var reportErrorsStr = Zotero.getString('errorReport.reportErrors');
var reportInstructions =
Zotero.getString('errorReport.reportInstructions', reportErrorsStr)
var msg = Zotero.getString('general.errorHasOccurred') + ' '
+ Zotero.getString('general.restartFirefox') + '\n\n'
+ reportInstructions;
obj._ownerDocument.defaultView.ZoteroPane.setItemsPaneMessage(msg);
*/
}
return;
}
obj.refresh();
// Add a keypress listener for expand/collapse

View File

@ -97,7 +97,7 @@ Zotero.ProgressWindowSet = new function() {
for (var i=0; i<_progressWindows.length; i++) {
// Pass |requireMouseOver| so that the window only closes
// if the mouse was over it at some point
_progressWindows[i].instance.startCloseTimer(true);
_progressWindows[i].instance.startCloseTimer(null, true);
}
}
}
@ -246,7 +246,7 @@ Zotero.ProgressWindow = function(_window){
}
function startCloseTimer(requireMouseOver) {
function startCloseTimer(ms, requireMouseOver) {
if (_windowLoaded || _windowLoading) {
if (requireMouseOver && !_mouseWasOver) {
return;
@ -256,7 +256,11 @@ Zotero.ProgressWindow = function(_window){
_disableTimeout();
}
_timeoutID = _progressWindow.setTimeout(_timeout, 2500);
if (typeof ms != 'number') {
ms = 2500;
}
_timeoutID = _progressWindow.setTimeout(_timeout, ms);
}
}

View File

@ -34,6 +34,7 @@ const ZOTERO_CONFIG = {
var Zotero = new function(){
// Privileged (public) methods
this.init = init;
this.stateCheck = stateCheck;
//this.shutdown = shutdown;
this.getProfileDirectory = getProfileDirectory;
this.getZoteroDirectory = getZoteroDirectory;
@ -223,6 +224,17 @@ var Zotero = new function(){
}
function stateCheck() {
if (Zotero.DB.transactionInProgress()) {
this.initialized = false;
this.skipLoading = true;
return false;
}
return true;
}
/*
function shutdown(subject, topic, data){
// Called twice otherwise, for some reason
@ -350,7 +362,7 @@ var Zotero = new function(){
}
var index = ps.confirmEx(win,
Zotero.getString('general.restartRequired'),
Zotero.getString('general.restartFirefox.singular'),
Zotero.getString('general.restartRequiredForChange'),
buttonFlags,
Zotero.getString('general.restartNow'),
forceRestartNow ? null : Zotero.getString('general.restartLater'),

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -63,7 +63,6 @@
<!ENTITY zotero.toolbar.import.label "Import...">
<!ENTITY zotero.toolbar.export.label "Export Library...">
<!ENTITY zotero.toolbar.preferences.label "Preferences...">
<!ENTITY zotero.toolbar.reportErrors "Report Errors...">
<!ENTITY zotero.toolbar.documentation.label "Documentation">
<!ENTITY zotero.toolbar.about.label "About Zotero">
<!ENTITY zotero.toolbar.advancedSearch "Advanced Search">

View File

@ -2,14 +2,19 @@ general.error = Error
general.dontShowWarningAgain = Don't show this warning again.
general.locate = Locate...
general.restartRequired = Restart Required
general.restartFirefox.singular = Firefox must be restarted for the change to take effect.
general.restartFirefox.plural = Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange = Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges = Firefox must be restarted for the changes to take effect.
general.restartNow = Restart now
general.restartLater = Restart later
general.errorHasOccurred = An error has occurred.
general.restartFirefox = Please restart Firefox.
general.restartFirefoxAndTryAgain = Please restart Firefox and try again.
upgrade.failed = Upgrading of the Zotero database failed:
upgrade.advanceMessage = Press %S to upgrade now.
errorReport.reportErrors = Report Errors...
errorReport.reportInstructions = You can report this error by selecting "%S" from the Actions (gear) menu.
errorReport.followingErrors = The following errors have occurred:
errorReport.advanceMessage = Press %S to send an error report to the Zotero developers.
errorReport.stepsToReproduce = Steps to Reproduce:
@ -293,6 +298,7 @@ ingester.scrapeComplete = Item Saved
ingester.scrapeError = Could Not Save Item
ingester.scrapeErrorDescription = An error occurred while saving this item. Check %S for more information.
ingester.scrapeErrorDescription.linkText = Known Translator Issues
ingester.scrapeError.transactionInProgress.previousError = The saving process failed due to a previous Zotero error.
db.dbCorrupted = The Zotero database '%S' appears to have become corrupted.
db.dbCorrupted.restart = Please restart Firefox to attempt an automatic restore from the last backup.

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,7 +1,7 @@
general.dontShowWarningAgain=Don't show this warning again.
general.locate=Locate...
general.restartFirefox.singular=Firefox must be restarted for the change to take effect.
general.restartFirefox.plural=Firefox must be restarted for the changes to take effect.
general.restartRequiredForChange=Firefox must be restarted for the change to take effect.
general.restartRequiredForChanges=Firefox must be restarted for the changes to take effect.
general.restartNow=Restart now
general.restartLater=Restart later

View File

@ -1,5 +1,5 @@
description {
margin-bottom: 1.5em;
margin: 0 0 1.5em;
}
/* Intro pane */

View File

@ -264,6 +264,10 @@
-moz-appearance: listbox;
}
#zotero-items-pane-message-box description:not(:first-child) {
margin-top: .75em;
}
#zotero-annotate-tb-add
{