StatCacheServer changes: * A Node can no longer have a referring "." or ".." Entry (except the root directory), not even temporarily. This rules out cycles when resolving paths. * Made the code more robust against missed node monitoring messages. If an entry is encountered that shouldn't be there, it is removed. As implemented before, a Node could end up with a NULL referring Entry, leading to a crash when an Entry that references the Node was moved. Missing node monitoring messages is actually virtually impossible, since a dedicated looper does nothing else but pushing those into a separate queue, but nevertheless Stippi seems to have managed the trick. :-)
git-svn-id: file:///srv/svn/repos/haiku/buildtools/trunk@21307 a95241bf-73f2-0310-859d-f6bbb57e9c96
Diff
jam/StatCacheServer.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++------------
jam/StatCacheServerImpl.h | 6 ++++--
2 files changed, 54 insertions(+), 16 deletions(-)
@@ -18,7 +18,7 @@
#define DBG(x)
#define OUT printf
#define OUT(format...) {printf(format); fflush(stdout);}
static const int32 kMaxSymlinks = 32;
@@ -29,6 +29,14 @@
extern "C" int _kset_mon_limit_(int num);
static inline bool
is_dot_or_dotdot(const char* name)
{
if (name && name[0] == '.')
return (name[1] == '\0' || name[1] == '.' && name[2] == '\0');
return false;
}
static inline
int32
@@ -138,7 +146,7 @@
fNode = node;
if (fNode) {
fNode->AddReference();
if (!fNode->GetEntry())
if (!fNode->GetEntry() && !is_dot_or_dotdot(fName.c_str()))
fNode->SetEntry(this);
}
}
@@ -379,7 +387,7 @@
{
entry_ref ref(fStat.st_dev, fStat.st_ino, name);
if (!fIsComplete)
return NodeManager::GetDefault()->CreateEntry(ref, entry);
return NodeManager::GetDefault()->CreateEntry(ref, NULL, entry);
*entry = NodeManager::GetDefault()->GetEntry(ref);
return (*entry ? B_OK : B_ENTRY_NOT_FOUND);
}
@@ -869,9 +877,19 @@
status_t
NodeManager::CreateEntry(const entry_ref &entryRef, Entry **_entry)
NodeManager::CreateEntry(const entry_ref &entryRef, const node_ref *nodeRef,
Entry **_entry)
{
Entry *entry = GetEntry(entryRef);
if (nodeRef && entry && entry->GetNode()
&& entry->GetNode()->GetNodeRef() != *nodeRef) {
RemoveEntry(entry);
entry = NULL;
}
if (!entry) {
@@ -900,9 +918,23 @@
if (error != B_OK) {
delete entry;
return error;
}
if (node->GetEntry() && node->GetEntry() != entry
&& !is_dot_or_dotdot(entry->GetName())) {
RemoveEntry(node->GetEntry());
StopWatching(node);
StartWatching(node);
}
entry->SetNode(node);
node->RemoveReference();
@@ -985,7 +1017,8 @@
void
NodeManager::MoveEntry(Entry *entry, const entry_ref &newRef)
NodeManager::MoveEntry(Entry *entry, const entry_ref &newRef,
const node_ref &nodeRef)
{
node_ref newDirRef;
@@ -998,18 +1031,19 @@
return;
}
Node *node = entry->GetNode();
if (newDir != entry->GetParent()
|| strcmp(newRef.name, entry->GetName()) != 0) {
|| strcmp(newRef.name, entry->GetName()) != 0
|| (node && node->GetNodeRef() != nodeRef)) {
Node *node = entry->GetNode();
if (node)
node->AddReference();
RemoveEntry(entry);
CreateEntry(newRef, &entry);
CreateEntry(newRef, &nodeRef, &entry);
if (node)
node->RemoveReference();
@@ -1141,13 +1175,15 @@
{
node_ref dirNodeRef;
node_ref nodeRef;
const char* name;
if (message->FindInt32("device", &dirNodeRef.device) != B_OK
|| message->FindInt64("directory", &dirNodeRef.node) != B_OK
|| message->FindInt64("node", &nodeRef.node) != B_OK
|| message->FindString("name", &name) != B_OK) {
return;
}
nodeRef.device = dirNodeRef.device;
Node *node = NodeManager::GetDefault()->GetNode(dirNodeRef);
@@ -1160,7 +1196,7 @@
Entry *entry;
if (dir->FindEntry(name, &entry) != B_OK) {
entry_ref ref(dirNodeRef.device, dirNodeRef.node, name);
NodeManager::GetDefault()->CreateEntry(ref, &entry);
NodeManager::GetDefault()->CreateEntry(ref, &nodeRef, &entry);
}
}
}
@@ -1209,13 +1245,13 @@
Entry *entry;
entry_ref newRef(nodeRef.device, newDirID, name);
NodeManager::GetDefault()->CreateEntry(newRef, &entry);
NodeManager::GetDefault()->CreateEntry(newRef, &nodeRef, &entry);
return;
}
entry_ref newRef(nodeRef.device, newDirID, name);
NodeManager::GetDefault()->MoveEntry(node->GetEntry(), newRef);
NodeManager::GetDefault()->MoveEntry(node->GetEntry(), newRef, nodeRef);
}
@@ -225,11 +225,13 @@
Node *GetNode(const node_ref &nodeRef);
Entry *GetEntry(const entry_ref &entryRef);
status_t CreateEntry(const entry_ref &entryRef, Entry **_entry);
status_t CreateEntry(const entry_ref &entryRef, const node_ref *nodeRef,
Entry **_entry);
status_t CreateDirectory(const node_ref &nodeRef, Directory **_dir);
void RemoveEntry(Entry *entry);
void MoveEntry(Entry *entry, const entry_ref &newRef);
void MoveEntry(Entry *entry, const entry_ref &newRef,
const node_ref &nodeRef);
void EntryUnreferenced(Entry *entry);
void NodeUnreferenced(Node *node);