fix poor performance of fscache watcher handler

pull/282/head
nightwing 2016-03-28 00:21:01 +04:00
rodzic 498a9b072f
commit aa2eaf0ff4
1 zmienionych plików z 113 dodań i 85 usunięć

Wyświetl plik

@ -82,6 +82,9 @@ define(function(require, exports, module) {
node.status = "pending"; node.status = "pending";
return; return;
} }
var parentPath = e.path;
if (!parentPath.endsWith("/"))
parentPath += "/";
// update cache // update cache
if (!node) { if (!node) {
if (!showHidden && isFileHidden(e.path)) if (!showHidden && isFileHidden(e.path))
@ -96,61 +99,78 @@ define(function(require, exports, module) {
// Indicate this directory has been fully read // Indicate this directory has been fully read
model.setAttribute(node, "status", "loaded"); model.setAttribute(node, "status", "loaded");
var wasOpen = startUpdate(node); var ondisk = Object.create(null);
node.children = null; var toRemove = [];
var existing = node.map || {}; var toCreate = [];
node.map = {}; var orphanAppand = [];
var existing = node.map || (node.map = Object.create(null));
// Fill Parent
var ondisk = {}, toAppend = [];
e.result[1].forEach(function(stat) { e.result[1].forEach(function(stat) {
if (!stat.name || !showHidden && isFileHidden(stat.name)) if (!stat.name || !showHidden && isFileHidden(stat.name))
return; return;
var name = stat.name; var name = stat.name;
var path = (e.path + "/" + name).replace("//", "/"); var path = parentPath + name;
ondisk[name] = 1; ondisk[name] = 1;
// if (existing[name]) return;
if (existing[name])
updateNodeStat(path, stat, existing[name]);
else
toCreate.push(stat);
if (orphans[path]) { if (orphans[path]) {
toAppend.push(path); if (existing[name])
delete orphans[path];
else
orphanAppand.push(path);
} }
createNode(path, stat, existing[name], true);
}); });
for (var name in existing) { Object.keys(existing).forEach(function(name) {
if (!ondisk[name]) {
// onreaddir can be called before copied nodes are written to disk // onreaddir can be called before copied nodes are written to disk
// in this case we don't want to lose "predicted" state // in this case we don't want to lose "predicted" state
if (existing[name] && existing[name].status === "predicted") if (existing[name] && existing[name].status === "predicted")
node.map[name] = existing[name]; ondisk[name] = 1;
else { if (!ondisk[name])
delete existing[name]; toRemove.push(name);
});
if (!toCreate.length && !toRemove.length && !orphanAppand.length)
return;
var wasOpen = startUpdate(node);
node.children = null;
// Fill Parent
toCreate.forEach(function(stat) {
createNode(parentPath + stat.name, stat, null, true);
});
toRemove.forEach(function(name) {
var currentNode = existing[name];
delete existing[name];
emit("remove", { emit("remove", {
path: e.path + "/" + name, path: parentPath + name,
node: existing[name], node: currentNode,
parent: node parent: node
}); });
} });
}
}
emit("readdir", { path : e.path, parent : node, orphan: orphan }); emit("readdir", { path : e.path, parent : node, orphan: orphan });
endUpdate(node, wasOpen); endUpdate(node, wasOpen);
toAppend.forEach(function(path) { orphanAppand.forEach(function(path) {
emit("orphan-append", {path: path}); emit("orphan-append", {path: path});
}); });
} }
fs.on("afterReaddir", onreaddir, plugin); fs.on("afterReaddir", onreaddir, plugin);
function onstat(e) { function onstat(e) {
var stat; if (e.error) return;
if (!e.error) {
// update cache // update cache
var stat = e.result[1];
var there = true; var there = true;
var node = findNode(e.path); var node = findNode(e.path);
var parent = findNode(dirname(e.path)); var parent = findNode(dirname(e.path));
@ -164,26 +184,28 @@ define(function(require, exports, module) {
there = false; there = false;
} }
if (there != !!e.result[1]) { if (there != !!stat) {
if (there) { if (there) {
if (!node.link) if (!node.link)
deleteNode(node); deleteNode(node);
} }
else { else {
stat = e.result[1];
if (typeof stat != "object") if (typeof stat != "object")
stat = null; stat = null;
createNode(e.path, stat); createNode(e.path, stat);
} }
} }
else if (there) { else if (there) {
stat = e.result[1];
if (typeof stat != "object") if (typeof stat != "object")
stat = null; stat = null;
if (!stat && node)
return;
if (stat && node)
updateNodeStat(e.path, stat, node);
else
createNode(e.path, stat, node); createNode(e.path, stat, node);
} }
} }
}
fs.on("afterStat", onstat, plugin); fs.on("afterStat", onstat, plugin);
fs.on("afterReadFile", function(e) { fs.on("afterReadFile", function(e) {
var err = e.result[0]; var err = e.result[0];
@ -518,14 +540,8 @@ define(function(require, exports, module) {
updateNode = orphans[path]; updateNode = orphans[path];
delete orphans[path]; delete orphans[path];
} }
var original_stat;
if (stat && stat.link) {
original_stat = stat;
stat = stat.linkStat;
}
var parts = path.split("/"); var parts = path.split("/");
var name = parts[parts.length - 1];
var node = model.root.map[parts[0] == "~" ? "~" : ""]; var node = model.root.map[parts[0] == "~" ? "~" : ""];
if (!node) { if (!node) {
node = orphans[parts[0]]; node = orphans[parts[0]];
@ -544,7 +560,7 @@ define(function(require, exports, module) {
var map = node.map; var map = node.map;
if (!map) { if (!map) {
map = node.map = {}; map = node.map = Object.create(null);
} }
parent = node; parent = node;
node = map[p]; node = map[p];
@ -571,8 +587,32 @@ define(function(require, exports, module) {
node = {label: parts[parts.length - 1], path: path}; node = {label: parts[parts.length - 1], path: path};
orphans[path] = node; orphans[path] = node;
} }
node.path = path;
updateNodeStat(path, stat, node);
node.children = null;
if (!updating) {
if (!modified.length)
modified.push(parent);
var wasOpen = startUpdate(modified[0]);
modified.forEach(function(n) {
if (n != model.root)
n.children = null;
});
endUpdate(modified[0], wasOpen);
}
model._signal("createNode", node);
return node;
}
function updateNodeStat(path, stat, node) {
node.path = path;
var original_stat;
if (stat && stat.link) {
original_stat = stat;
stat = stat.linkStat;
}
if (stat) { if (stat) {
var isFolder = stat && /(directory|folder)$/.test(stat.mime); var isFolder = stat && /(directory|folder)$/.test(stat.mime);
if (isFolder) { if (isFolder) {
@ -596,25 +636,13 @@ define(function(require, exports, module) {
delete node.isFolder; delete node.isFolder;
} }
if (node.isFolder && !node.map) if (node.isFolder && !node.map) {
node.map = {}; node.map = Object.create(null);
else if (!node.isFolder && node.map) node.children = null;
delete node.map; } else if (!node.isFolder && node.map) {
delete node.map;
node.children = null; node.children = null;
if (!updating) {
if (!modified.length)
modified.push(parent);
var wasOpen = startUpdate(modified[0]);
modified.forEach(function(n) {
if (n != model.root)
n.children = null;
});
endUpdate(modified[0], wasOpen);
} }
model._signal("createNode", node);
return node;
} }
function deleteNode(node, silent) { function deleteNode(node, silent) {
@ -677,7 +705,7 @@ define(function(require, exports, module) {
map: {} map: {}
}; };
var root = {}; var root = {};
root.map = {}; root.map = Object.create(null);
root.map[""] = model.projectDir; root.map[""] = model.projectDir;
model.setRoot(root); model.setRoot(root);
// fs.readdir("/", function(){}); // fs.readdir("/", function(){});