More file sync fixes

This commit is contained in:
Dan Stillman 2013-02-19 05:55:42 -05:00
parent 918cb2ef1b
commit 6c28e61032
5 changed files with 121 additions and 141 deletions

View file

@ -289,6 +289,7 @@ Zotero.Sync.Storage = new function () {
]));
}
else {
result = result.exception;
Zotero.debug("File " + result.type + " sync failed "
+ "for library " + libraryID);
finalPromises.push([libraryID, queuePromise]);
@ -378,7 +379,7 @@ Zotero.Sync.Storage = new function () {
var request = new Zotero.Sync.Storage.Request(
(item.libraryID ? item.libraryID : 0) + '/' + item.key, callbacks
);
if (queue == 'upload') {
if (queue.type == 'upload') {
request.setMaxSize(Zotero.Attachments.getTotalFileSize(item));
}
queue.addRequest(request, highPriority);

View file

@ -49,6 +49,8 @@ Zotero.Sync.Storage.Queue = function (type, libraryID) {
this._localChanges = false;
this._remoteChanges = false;
this._conflicts = [];
this._cachedPercentage;
this._cachedPercentageTime;
}
Zotero.Sync.Storage.Queue.prototype.__defineGetter__('name', function () {
@ -158,11 +160,18 @@ Zotero.Sync.Storage.Queue.prototype.__defineGetter__('percentage', function () {
return 100;
}
// Cache percentage for a second
if (this._cachedPercentage && (new Date() - this._cachedPercentageTime) < 1000) {
return this._cachedPercentage;
}
var completedRequests = 0;
for each(var request in this._requests) {
completedRequests += request.percentage / 100;
}
return Math.round((completedRequests / this.totalRequests) * 100);
this._cachedPercentage = Math.round((completedRequests / this.totalRequests) * 100);
this._cachedPercentageTime = new Date();
return this._cachedPercentage;
});
@ -288,7 +297,7 @@ Zotero.Sync.Storage.Queue.prototype.advance = function () {
);
}
})
.fail(function (e) {
.catch(function (e) {
self.error(e);
});
@ -330,7 +339,7 @@ Zotero.Sync.Storage.Queue.prototype.advance = function () {
);
}
})
.fail(function (e) {
.catch(function (e) {
self.error(e);
});
@ -362,7 +371,6 @@ Zotero.Sync.Storage.Queue.prototype.error = function (e) {
this._error = e;
}
Zotero.debug(e, 1);
Components.utils.reportError(e.message ? e.message : e);
this.stop();
}

View file

@ -208,7 +208,6 @@ Zotero.Sync.Storage.Request.prototype.start = function () {
};
})
.then(function (results) {
Zotero.debug('!!!!');
Zotero.debug(results);
if (results.localChanges) {
@ -263,7 +262,7 @@ Zotero.Sync.Storage.Request.prototype.isFinished = function () {
* (usually total bytes)
*/
Zotero.Sync.Storage.Request.prototype.onProgress = function (channel, progress, progressMax) {
Zotero.debug(progress + "/" + progressMax + " for request " + this.name);
//Zotero.debug(progress + "/" + progressMax + " for request " + this.name);
if (!this._running) {
Zotero.debug("Trying to update finished request " + this.name + " in "

View file

@ -68,20 +68,22 @@ Zotero.Sync.Storage.WebDAV = (function () {
return false;
}
if (req.responseXML) {
// TODO: other stuff, but this makes us forward-compatible
try {
var mtime = req.responseXML.getElementsByTagName('mtime')[0]
}
catch (e) {
Zotero.debug(e);
var mtime = "";
}
var seconds = false;
var seconds = false;
var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
.createInstance(Components.interfaces.nsIDOMParser);
try {
var xml = parser.parseFromString(req.responseText, "text/xml");
var mtime = xml.getElementsByTagName('mtime')[0].textContent;
}
else {
catch (e) {
Zotero.debug(e);
var mtime = false;
}
// TEMP
if (!mtime) {
mtime = req.responseText;
var seconds = true;
seconds = true;
}
var invalid = false;
@ -106,13 +108,15 @@ Zotero.Sync.Storage.WebDAV = (function () {
+ "' for item " + Zotero.Items.getLibraryKeyHash(item);
Zotero.debug(msg, 1);
Components.utils.reportError(msg);
deleteStorageFiles([item.key + ".prop"]);
throw _defaultError;
return deleteStorageFiles([item.key + ".prop"])
.then(function (results) {
throw new Error(_defaultError);
});
}
return new Date(parseInt(mtime));
})
.fail(function (e) {
.catch(function (e) {
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
Zotero.debug(req.responseText);
throw new Error("Unexpected status code " + e.status + " in " + funcName);
@ -138,8 +142,8 @@ Zotero.Sync.Storage.WebDAV = (function () {
+ '<hash>' + hash + '</hash>'
+ '</properties>';
return Zotero.HTTP.promise("PUT", uri, prop,
{ debug: true, successCodes: [200, 201, 204] })
return Zotero.HTTP.promise("PUT", uri,
{ body: prop, debug: true, successCodes: [200, 201, 204] })
.then(function (req) {
return { mtime: mtime, hash: hash };
})
@ -459,7 +463,7 @@ Zotero.Sync.Storage.WebDAV = (function () {
* 'deleted', 'missing', and 'error',
* each containing filenames
*/
function deleteStorageFiles(files, callback) {
function deleteStorageFiles(files) {
var results = {
deleted: [],
missing: [],
@ -467,114 +471,90 @@ Zotero.Sync.Storage.WebDAV = (function () {
};
if (files.length == 0) {
if (callback) {
callback(results);
}
return;
return Q.resolve(results);
}
for (var i=0; i<files.length; i++) {
let last = (i == files.length - 1);
let fileName = files[i];
let deleteURI = rootURI;
// This should never happen, but let's be safe
if (!deleteURI.spec.match(/\/$/)) {
if (callback) {
callback(deleted);
}
Zotero.Sync.Storage.EventManager.error(
"Root URI does not end in slash in "
+ "Zotero.Sync.Storage.WebDAV.deleteStorageFiles()"
);
}
deleteURI.QueryInterface(Components.interfaces.nsIURL);
deleteURI.fileName = files[i];
deleteURI.QueryInterface(Components.interfaces.nsIURI);
Zotero.HTTP.WebDAV.doDelete(deleteURI, function (req) {
switch (req.status) {
case 204:
// IIS 5.1 and Sakai return 200
case 200:
var fileDeleted = true;
break;
case 404:
var fileDeleted = false;
break;
default:
if (last && callback) {
callback(results);
}
results.error.push(fileName);
var msg = "An error occurred attempting to delete "
+ "'" + fileName
+ "' (" + req.status + " " + req.statusText + ").";
Zotero.Sync.Storage.EventManager.error(msg);
}
// If an item file URI, get the property URI
var deletePropURI = getPropertyURIFromItemURI(deleteURI);
if (!deletePropURI) {
if (fileDeleted) {
results.deleted.push(fileName);
}
else {
results.missing.push(fileName);
}
if (last && callback) {
callback(results);
}
return;
}
// If property file appears separately in delete queue,
// remove it, since we're taking care of it here
var propIndex = files.indexOf(deletePropURI.fileName);
if (propIndex > i) {
delete files[propIndex];
i--;
last = (i == files.length - 1);
}
// Delete property file
Zotero.HTTP.WebDAV.doDelete(deletePropURI, function (req) {
let deleteURI = _rootURI.clone();
// This should never happen, but let's be safe
if (!deleteURI.spec.match(/\/$/)) {
throw new Error(
"Root URI does not end in slash in "
+ "Zotero.Sync.Storage.WebDAV.deleteStorageFiles()"
);
}
results = Q.resolve(results);
files.forEach(function (fileName) {
results = results.then(function (results) {
let deleteURI = _rootURI.clone();
deleteURI.QueryInterface(Components.interfaces.nsIURL);
deleteURI.fileName = fileName;
deleteURI.QueryInterface(Components.interfaces.nsIURI);
return Zotero.HTTP.promise("DELETE", deleteURI, { successCodes: [200, 204, 404] })
.then(function (req) {
switch (req.status) {
case 204:
// IIS 5.1 and Sakai return 200
case 200:
results.deleted.push(fileName);
var fileDeleted = true;
break;
case 404:
if (fileDeleted) {
results.deleted.push(fileName);
}
else {
results.missing.push(fileName);
}
var fileDeleted = false;
break;
default:
var error = true;
}
if (last && callback) {
callback(results);
// If an item file URI, get the property URI
var deletePropURI = getPropertyURIFromItemURI(deleteURI);
if (!deletePropURI) {
if (fileDeleted) {
results.deleted.push(fileName);
}
else {
results.missing.push(fileName);
}
return results;
}
if (error) {
results.error.push(fileName);
var msg = "An error occurred attempting to delete "
+ "'" + fileName
+ "' (" + req.status + " " + req.statusText + ").";
Zotero.Sync.Storage.EventManager.error(msg);
// If property file appears separately in delete queue,
// remove it, since we're taking care of it here
var propIndex = files.indexOf(deletePropURI.fileName);
if (propIndex > i) {
delete files[propIndex];
i--;
last = (i == files.length - 1);
}
// Delete property file
return Zotero.HTTP.promise("DELETE", deletePropURI, { successCodes: [200, 204, 404] })
.then(function (req) {
switch (req.status) {
case 204:
// IIS 5.1 and Sakai return 200
case 200:
results.deleted.push(fileName);
break;
case 404:
if (fileDeleted) {
results.deleted.push(fileName);
}
else {
results.missing.push(fileName);
}
break;
}
});
})
.catch(function (e) {
results.error.push(fileName);
var msg = "An error occurred attempting to delete "
+ "'" + fileName
+ "' (" + e.status + " " + e.xmlhttp.statusText + ").";
});
});
}
});
return results;
}
@ -888,9 +868,10 @@ Zotero.Sync.Storage.WebDAV = (function () {
Components.utils.reportError(msg);
// Delete the orphaned prop file
deleteStorageFiles([item.key + ".prop"]);
deferred.resolve(false);
deleteStorageFiles([item.key + ".prop"])
.finally(function (results) {
deferred.resolve(false);
});
return;
}
else if (status != 200) {
@ -1474,27 +1455,23 @@ Zotero.Sync.Storage.WebDAV = (function () {
*
* @param {Function} callback Passed number of files deleted
*/
obj._purgeDeletedStorageFiles = function (callback) {
obj._purgeDeletedStorageFiles = function () {
if (!this._active) {
return false;
return Q(false);
}
Zotero.debug("Purging deleted storage files");
var files = Zotero.Sync.Storage.getDeletedFiles();
if (!files) {
Zotero.debug("No files to delete remotely");
if (callback) {
callback();
}
return false;
return Q(false);
}
// TODO: promisify
// Add .zip extension
var files = files.map(function (file) file + ".zip");
deleteStorageFiles(files, function (results) {
return deleteStorageFiles(files)
.then(function (results) {
// Remove deleted and nonexistent files from storage delete log
var toPurge = results.deleted.concat(results.missing);
if (toPurge.length > 0) {
@ -1516,11 +1493,7 @@ Zotero.Sync.Storage.WebDAV = (function () {
Zotero.DB.commitTransaction();
}
if (callback) {
callback(results.deleted.length);
}
Zotero.Sync.Storage.EventManager.success();
return results.deleted.length;
});
};
@ -1647,12 +1620,10 @@ Zotero.Sync.Storage.WebDAV = (function () {
}
}
deleteStorageFiles(deleteFiles, function (results) {
deleteStorageFiles(deleteFiles)
.then(function (results) {
Zotero.Prefs.set("lastWebDAVOrphanPurge", Math.round(new Date().getTime() / 1000))
if (callback) {
callback(results);
}
Zotero.Sync.Storage.EventManager.success();
Zotero.debug(results);
});
}, { Depth: 1 });
};

View file

@ -553,8 +553,11 @@ Zotero.Sync.Runner = new function () {
Zotero.debug("File sync is finished");
if (results.errors.length) {
Zotero.debug(results.errors, 1);
for each(var e in results.errors) {
Components.utils.reportError(e);
}
Zotero.Sync.Runner.setErrors(results.errors);
return;
}
@ -716,9 +719,7 @@ Zotero.Sync.Runner = new function () {
* library-specific sync error icons across all windows
*/
this.setErrors = function (errors) {
Zotero.debug(errors);
errors = [this.parseSyncError(e) for each(e in errors)];
Zotero.debug(errors);
_errorsByLibrary = {};
var primaryError = this.getPrimaryError(errors);