Refactored error code and added transaction abort on error.

This commit is contained in:
Alan Kligman 2012-10-13 13:26:02 -04:00
parent c434385fe4
commit eb4b1b1aa1
1 changed files with 84 additions and 64 deletions

View File

@ -64,32 +64,52 @@ define(function(require) {
var IDB_RO = "readonly"; var IDB_RO = "readonly";
var IDB_RW = "readwrite"; var IDB_RW = "readwrite";
function IDBFSError(type, code) { function PathExistsError(){ Error.apply(this, arguments); }
this.type = type; PathExistsError.prototype = new Error();
this.code = code; PathExistsError.prototype.name = "PathExistsError";
} PathExistsError.prototype.constructor = PathExistsError;
// Types
var T_NONE = 0x0;
var T_OPEN = 0x1;
var T_MKDIR = 0x2;
var T_STAT = 0x3;
var T_RMDIR = 0x4;
var T_CLOSE = 0x5;
var T_READ = 0x6;
var T_UNLINK = 0x7;
// Codes
var E_EXIST = 0x0;
var E_ISDIR = 0x1;
var E_NOENT = 0x2;
var E_BUSY = 0x3;
var E_NOTEMPTY = 0x4;
var E_NOTDIR = 0x5;
var E_BADF = 0x6;
var E_NOT_IMPLEMENTED = 0x7;
function genericIDBErrorHandler(scope, callback) { function IsDirectoryError(){ Error.apply(this, arguments); }
return function(error) { IsDirectoryError.prototype = new Error();
debug.error("[" + scope + "] error: ", error); IsDirectoryError.prototype.name = "IsDirectoryError";
IsDirectoryError.prototype.constructor = IsDirectoryError;
function NoEntryError(){ Error.apply(this, arguments); }
NoEntryError.prototype = new Error();
NoEntryError.prototype.name = "NoEntryError";
NoEntryError.prototype.constructor = NoEntryError;
function BusyError(){ Error.apply(this, arguments); }
BusyError.prototype = new Error();
BusyError.prototype.name = "BusyError";
BusyError.prototype.constructor = BusyError;
function NotEmptyError(){ Error.apply(this, arguments); }
NotEmptyError.prototype = new Error();
NotEmptyError.prototype.name = "NotEmptyError";
NotEmptyError.prototype.constructor = NotEmptyError;
function NotDirectoryError(){ Error.apply(this, arguments); }
NotDirectoryError.prototype = new Error();
NotDirectoryError.prototype.name = "NotADirectoryError";
NotDirectoryError.prototype.constructor = NotDirectoryError;
function BadFileDescriptorError(){ Error.apply(this, arguments); }
BadFileDescriptorError.prototype = new Error();
BadFileDescriptorError.prototype.name = "BadFileDescriptorError";
BadFileDescriptorError.prototype.constructor = BadFileDescriptorError;
function NotImplementedError(){ Error.apply(this, arguments); }
NotImplementedError.prototype = new Error();
NotImplementedError.prototype.name = "NotImplementedError";
NotImplementedError.prototype.constructor = NotImplementedError;
function genericErrorHandler(callback) {
return function(transaction, error) {
debug.error("error: ", error);
if(transaction) {
transaction.abort();
}
if(callback && "function" === typeof callback) { if(callback && "function" === typeof callback) {
callback.call(undefined, error); callback.call(undefined, error);
} }
@ -136,9 +156,9 @@ define(function(require) {
function read(buffer, callback) { function read(buffer, callback) {
debug.info("read -->"); debug.info("read -->");
var onerror = genericIDBErrorHandler("read", callback); var onerror = genericErrorHandler(callback);
if(!start()) { if(!start()) {
onerror(new IDBFSError(T_READ, E_BADF)); onerror(null, new BadFileDescriptorError());
return; return;
} }
transaction = db.transaction([FILE_STORE_NAME], IDB_RO); transaction = db.transaction([FILE_STORE_NAME], IDB_RO);
@ -172,22 +192,22 @@ define(function(require) {
} }
} }
}; };
getRequest.onerror = onerror; getRequest.onerror = onerror.bind(null, transaction);
} else if(MIME_DIRECTORY === ofd.entry["contenttype"]) { } else if(MIME_DIRECTORY === ofd.entry["contenttype"]) {
// NOT IMPLEMENTED // NOT IMPLEMENTED
onerror(new IDBFSError(T_READ, E_NOT_IMPLEMENTED)) onerror(transaction, new NotImplementedError());
} }
} }
function write(buffer, callback) { function write(buffer, callback) {
debug.info("write -->"); debug.info("write -->");
var onerror = genericIDBErrorHandler("write", callback); var onerror = genericErrorHandler(callback);
if(OM_RO === ofd.mode) { if(OM_RO === ofd.mode) {
onerror(new IDBFSError(T_READ, E_BADF)); onerror(null, new BadFileDescriptorError());
return; return;
} }
if(!start()) { if(!start()) {
onerror(new IDBFSError(T_READ, E_BADF)); onerror(null, new BadFileDescriptorError());
return; return;
} }
transaction = db.transaction([METADATA_STORE_NAME, FILE_STORE_NAME], IDB_RW); transaction = db.transaction([METADATA_STORE_NAME, FILE_STORE_NAME], IDB_RW);
@ -223,13 +243,13 @@ define(function(require) {
callback.call(undefined, undefined, size, buffer); callback.call(undefined, undefined, size, buffer);
} }
}; };
writeMetadataRequest.onerror = onerror; writeMetadataRequest.onerror = onerror.bind(null, transaction);
} }
readMetadataRequest.onerror = onerror; readMetadataRequest.onerror = onerror.bind(null, transaction);
}; };
putRequest.onerror = onerror; putRequest.onerror = onerror.bind(null, transaction);
}; };
getRequest.onerror = onerror; getRequest.onerror = onerror.bind(null, transaction);
} }
var SW_SET = "SET"; var SW_SET = "SET";
@ -274,7 +294,7 @@ define(function(require) {
transaction = db.transaction([METADATA_STORE_NAME], IDB_RW); transaction = db.transaction([METADATA_STORE_NAME], IDB_RW);
var store = transaction.objectStore(METADATA_STORE_NAME); var store = transaction.objectStore(METADATA_STORE_NAME);
var nameIndex = store.index(NAME_INDEX); var nameIndex = store.index(NAME_INDEX);
var onerror = genericIDBErrorHandler("mkdir", callback); var onerror = genericErrorHandler(callback);
if(undefined === flags) { if(undefined === flags) {
flags = []; flags = [];
@ -287,17 +307,17 @@ define(function(require) {
var entry = e.target.result; var entry = e.target.result;
if(!entry) { if(!entry) {
if(!_(flags).contains(OF_CREATE)) { if(!_(flags).contains(OF_CREATE)) {
onerror(new IDBFSError(T_OPEN, E_NOENT)); onerror(transaction, new NoEntryError());
return; return;
} else { } else {
entry = makeFileEntry(pathname); entry = makeFileEntry(pathname);
var createRequest = store.put(entry, pathname); var createRequest = store.put(entry, pathname);
createRequest.onsuccess = complete; createRequest.onsuccess = complete;
createRequest.onerror = onerror; createRequest.onerror = onerror.bind(null, transaction);
} }
} else { } else {
if(entry["contenttype"] === MIME_DIRECTORY && mode === OM_RW) { if(entry["contenttype"] === MIME_DIRECTORY && mode === OM_RW) {
onerror(new IDBFSError(T_OPEN, E_ISDIR)); onerror(transaction, new IsDirectoryError());
return; return;
} else { } else {
complete(); complete();
@ -313,14 +333,14 @@ define(function(require) {
} }
} }
}; };
getRequest.onerror = onerror; getRequest.onerror = onerror.bind(null, transaction);
} }
function close(fd, callback) { function close(fd, callback) {
debug.info("close -->"); debug.info("close -->");
var onerror = genericIDBErrorHandler("close", callback); var onerror = genericErrorHandler(callback);
if(!fds.hasOwnProperty(fd.descriptor)) { if(!fds.hasOwnProperty(fd.descriptor)) {
onerror(new IDBFSError(T_CLOSE, E_BADF)); onerror(null, new BadFileDescriptorError());
return; return;
} }
var ofd = fds[fd.descriptor]; var ofd = fds[fd.descriptor];
@ -339,13 +359,13 @@ define(function(require) {
transaction = transaction || db.transaction([METADATA_STORE_NAME], IDB_RW); transaction = transaction || db.transaction([METADATA_STORE_NAME], IDB_RW);
var store = transaction.objectStore(METADATA_STORE_NAME); var store = transaction.objectStore(METADATA_STORE_NAME);
var nameIndex = store.index(NAME_INDEX); var nameIndex = store.index(NAME_INDEX);
var onerror = genericIDBErrorHandler("mkdir", callback); var onerror = genericErrorHandler(callback);
var getRequest = nameIndex.get(pathname); var getRequest = nameIndex.get(pathname);
getRequest.onsuccess = function(e) { getRequest.onsuccess = function(e) {
var result = e.target.result; var result = e.target.result;
if(result) { if(result) {
onerror(new IDBFSError(T_MKDIR, E_EXIST)); onerror(null, new PathExistsError());
} else { } else {
var entry = makeDirectoryEntry(pathname, Date.now()); var entry = makeDirectoryEntry(pathname, Date.now());
var directoryRequest = store.put(entry, pathname); var directoryRequest = store.put(entry, pathname);
@ -355,10 +375,10 @@ define(function(require) {
callback.call(undefined, undefined); callback.call(undefined, undefined);
} }
}; };
directoryRequest.onerror = onerror; directoryRequest.onerror = onerror.bind(null, transaction);
} }
}; };
getRequest.onerror = onerror; getRequest.onerror = onerror.bind(null, transaction);
} }
function rmdir(pathname, callback) { function rmdir(pathname, callback) {
@ -368,20 +388,20 @@ define(function(require) {
var metaStore = transaction.objectStore(METADATA_STORE_NAME); var metaStore = transaction.objectStore(METADATA_STORE_NAME);
var nameIndex = metaStore.index(NAME_INDEX); var nameIndex = metaStore.index(NAME_INDEX);
var parentIndex = metaStore.index(PARENT_INDEX); var parentIndex = metaStore.index(PARENT_INDEX);
var onerror = genericIDBErrorHandler("rmdir", callback); var onerror = genericErrorHandler(callback);
var getRequest = nameIndex.get(pathname); var getRequest = nameIndex.get(pathname);
getRequest.onsuccess = function(e) { getRequest.onsuccess = function(e) {
var result = e.target.result; var result = e.target.result;
if(!result) { if(!result) {
onerror(new IDBFSError(T_RMDIR, E_NOENT)); onerror(transaction, new NoEntryError());
return; return;
} else { } else {
var contentRequest = parentIndex.get(pathname); var contentRequest = parentIndex.get(pathname);
contentRequest.onsuccess = function(e) { contentRequest.onsuccess = function(e) {
var result = e.target.result; var result = e.target.result;
if(result) { if(result) {
onerror(new IDBFSError(T_RMDIR, E_NOTEMPTY)); onerror(transaction, new NotEntry());
return; return;
} else { } else {
var removeRequest = metaStore.delete(pathname); var removeRequest = metaStore.delete(pathname);
@ -391,13 +411,13 @@ define(function(require) {
callback.call(undefined, undefined); callback.call(undefined, undefined);
} }
}; };
removeRequest.onerror = onerror; removeRequest.onerror = onerror.bind(null, transaction);
} }
}; };
contentRequest.onerror = onerror; contentRequest.onerror = onerror.bind(null, transaction);
} }
}; };
getRequest.onerror = onerror; getRequest.onerror = onerror.bind(null, transaction);
} }
function stat(transaction, pathname, callback) { function stat(transaction, pathname, callback) {
@ -406,13 +426,13 @@ define(function(require) {
transaction = transaction || db.transaction([METADATA_STORE_NAME], IDB_RO); transaction = transaction || db.transaction([METADATA_STORE_NAME], IDB_RO);
var store = transaction.objectStore(METADATA_STORE_NAME); var store = transaction.objectStore(METADATA_STORE_NAME);
var nameIndex = store.index(NAME_INDEX); var nameIndex = store.index(NAME_INDEX);
var onerror = genericIDBErrorHandler("stat", callback); var onerror = genericErrorHandler(callback);
var getRequest = nameIndex.get(pathname); var getRequest = nameIndex.get(pathname);
getRequest.onsuccess = function(e) { getRequest.onsuccess = function(e) {
var result = e.target.result; var result = e.target.result;
if(!result) { if(!result) {
onerror(new IDBFSError(T_STAT, E_NOENT)); onerror(transaction, new NoEntryError());
return; return;
} else { } else {
debug.info("stat <--"); debug.info("stat <--");
@ -421,7 +441,7 @@ define(function(require) {
} }
} }
}; };
getRequest.onerror = onerror; getRequest.onerror = onerror.bind(null, transaction);
} }
function link(oldpath, newpath, callback) { function link(oldpath, newpath, callback) {
@ -434,15 +454,15 @@ define(function(require) {
var transaction = db.transaction([METADATA_STORE_NAME], IDB_RW); var transaction = db.transaction([METADATA_STORE_NAME], IDB_RW);
var metaStore = transaction.objectStore(METADATA_STORE_NAME); var metaStore = transaction.objectStore(METADATA_STORE_NAME);
var nameIndex = metaStore.index(NAME_INDEX); var nameIndex = metaStore.index(NAME_INDEX);
var onerror = genericIDBErrorHandler("unlink", callback); var onerror = genericErrorHandler(callback);
stat(transaction, pathname, function(error, entry) { stat(transaction, pathname, function(error, entry) {
if(error) { if(error) {
onerror(new IDBFSError(T_UNLINK, error)); onerror(transaction, error);
return; return;
} }
if(MIME_DIRECTORY === entry["contenttype"]) { if(MIME_DIRECTORY === entry["contenttype"]) {
onerror(new IDBFSError(T_UNLINK, E_ISDIR)); onerror(transaction, new IsDirectoryError());
return; return;
} }
var unlinkRequest = metaStore.delete(entry["name"]); var unlinkRequest = metaStore.delete(entry["name"]);
@ -457,9 +477,9 @@ define(function(require) {
callback.call(undefined, undefined); callback.call(undefined, undefined);
} }
}; };
deleteRequest.onerror = onerror; deleteRequest.onerror = onerror.bind(null, transaction);
}; };
unlinkRequest.onerror = onerror; unlinkRequest.onerror = onerror.bind(null, transaction);
}); });
} }
@ -525,7 +545,7 @@ define(function(require) {
function mount(name, callback, optFormat) { function mount(name, callback, optFormat) {
debug.info("mount -->"); debug.info("mount -->");
optFormat = (IDBFS.FORMAT === optFormat) ? true : false; optFormat = (IDBFS.FORMAT === optFormat) ? true : false;
var onerror = genericIDBErrorHandler("mount", callback); var onerror = genericErrorHandler(callback);
var openRequest = indexedDB.open(name); var openRequest = indexedDB.open(name);
openRequest.onupgradeneeded = function(e) { openRequest.onupgradeneeded = function(e) {
var db = e.target.result; var db = e.target.result;
@ -565,7 +585,7 @@ define(function(require) {
} }
}); });
}; };
clearRequest.onerror = onerror; clearRequest.onerror = onerror.bind(null, transaction);
} else { } else {
debug.info("mount <--"); debug.info("mount <--");
if(callback && "function" === typeof callback) { if(callback && "function" === typeof callback) {
@ -573,7 +593,7 @@ define(function(require) {
} }
} }
}; };
openRequest.onerror = onerror; openRequest.onerror = onerror.bind(null, null);
} }
function umount(fs, callback) { function umount(fs, callback) {