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