mirror of
https://review.haiku-os.org/buildtools
synced 2024-11-23 15:29:11 +01:00
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
This commit is contained in:
parent
392bb39478
commit
f4194f2ee8
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
//#define DBG(x) { x; }
|
//#define DBG(x) { x; }
|
||||||
#define DBG(x)
|
#define DBG(x)
|
||||||
#define OUT printf
|
#define OUT(format...) {printf(format); fflush(stdout);}
|
||||||
|
|
||||||
static const int32 kMaxSymlinks = 32;
|
static const int32 kMaxSymlinks = 32;
|
||||||
|
|
||||||
@ -29,6 +29,14 @@ static const int32 kNodeMonitorLimitIncrement = 512;
|
|||||||
// private BeOS syscall to set the node monitor slot limits
|
// private BeOS syscall to set the node monitor slot limits
|
||||||
extern "C" int _kset_mon_limit_(int num);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// get_dirent_size
|
// get_dirent_size
|
||||||
static inline
|
static inline
|
||||||
int32
|
int32
|
||||||
@ -138,7 +146,7 @@ Entry::SetNode(Node *node)
|
|||||||
fNode = node;
|
fNode = node;
|
||||||
if (fNode) {
|
if (fNode) {
|
||||||
fNode->AddReference();
|
fNode->AddReference();
|
||||||
if (!fNode->GetEntry())
|
if (!fNode->GetEntry() && !is_dot_or_dotdot(fName.c_str()))
|
||||||
fNode->SetEntry(this);
|
fNode->SetEntry(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -379,7 +387,7 @@ Directory::FindEntry(const char *name, Entry **entry)
|
|||||||
{
|
{
|
||||||
entry_ref ref(fStat.st_dev, fStat.st_ino, name);
|
entry_ref ref(fStat.st_dev, fStat.st_ino, name);
|
||||||
if (!fIsComplete)
|
if (!fIsComplete)
|
||||||
return NodeManager::GetDefault()->CreateEntry(ref, entry);
|
return NodeManager::GetDefault()->CreateEntry(ref, NULL, entry);
|
||||||
*entry = NodeManager::GetDefault()->GetEntry(ref);
|
*entry = NodeManager::GetDefault()->GetEntry(ref);
|
||||||
return (*entry ? B_OK : B_ENTRY_NOT_FOUND);
|
return (*entry ? B_OK : B_ENTRY_NOT_FOUND);
|
||||||
}
|
}
|
||||||
@ -869,9 +877,19 @@ NodeManager::GetEntry(const entry_ref &entryRef)
|
|||||||
|
|
||||||
// CreateEntry
|
// CreateEntry
|
||||||
status_t
|
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);
|
Entry *entry = GetEntry(entryRef);
|
||||||
|
|
||||||
|
// If the entry is known, but its node is not the one it should be, we
|
||||||
|
// remove the entry.
|
||||||
|
if (nodeRef && entry && entry->GetNode()
|
||||||
|
&& entry->GetNode()->GetNodeRef() != *nodeRef) {
|
||||||
|
RemoveEntry(entry);
|
||||||
|
entry = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
// entry does not yet exist -- create it
|
// entry does not yet exist -- create it
|
||||||
|
|
||||||
@ -901,8 +919,22 @@ NodeManager::CreateEntry(const entry_ref &entryRef, Entry **_entry)
|
|||||||
delete entry;
|
delete entry;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the node already existed, but points to another entry, we
|
||||||
|
// remove that entry now. We probably missed the respective
|
||||||
|
// B_ENTRY_REMOVED notification.
|
||||||
|
if (node->GetEntry() && node->GetEntry() != entry
|
||||||
|
&& !is_dot_or_dotdot(entry->GetName())) {
|
||||||
|
RemoveEntry(node->GetEntry());
|
||||||
|
|
||||||
|
// reinit node watching
|
||||||
|
StopWatching(node);
|
||||||
|
StartWatching(node);
|
||||||
|
}
|
||||||
|
|
||||||
entry->SetNode(node);
|
entry->SetNode(node);
|
||||||
node->RemoveReference();
|
node->RemoveReference();
|
||||||
|
// reference acquired by _CreateNode()
|
||||||
|
|
||||||
// initialization successful: add the entry to the dir and to the
|
// initialization successful: add the entry to the dir and to the
|
||||||
// entry map
|
// entry map
|
||||||
@ -985,7 +1017,8 @@ OUT("entry removed: `%s'\n", path.c_str());
|
|||||||
|
|
||||||
// MoveEntry
|
// MoveEntry
|
||||||
void
|
void
|
||||||
NodeManager::MoveEntry(Entry *entry, const entry_ref &newRef)
|
NodeManager::MoveEntry(Entry *entry, const entry_ref &newRef,
|
||||||
|
const node_ref &nodeRef)
|
||||||
{
|
{
|
||||||
// get the target directory
|
// get the target directory
|
||||||
node_ref newDirRef;
|
node_ref newDirRef;
|
||||||
@ -998,18 +1031,19 @@ NodeManager::MoveEntry(Entry *entry, const entry_ref &newRef)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the directory and/or the name changed, we remove the old entry and
|
// If the directory, the name, or the node (missed B_ENTRY_REMOVED and
|
||||||
// create a new one.
|
// B_ENTRY_CREATED) changed, we remove the old entry and create a new one.
|
||||||
|
Node *node = entry->GetNode();
|
||||||
if (newDir != entry->GetParent()
|
if (newDir != entry->GetParent()
|
||||||
|| strcmp(newRef.name, entry->GetName()) != 0) {
|
|| strcmp(newRef.name, entry->GetName()) != 0
|
||||||
|
|| (node && node->GetNodeRef() != nodeRef)) {
|
||||||
// get a temporary reference to the node, so it won't be unnecessarily
|
// get a temporary reference to the node, so it won't be unnecessarily
|
||||||
// deleted
|
// deleted
|
||||||
Node *node = entry->GetNode();
|
|
||||||
if (node)
|
if (node)
|
||||||
node->AddReference();
|
node->AddReference();
|
||||||
|
|
||||||
RemoveEntry(entry);
|
RemoveEntry(entry);
|
||||||
CreateEntry(newRef, &entry);
|
CreateEntry(newRef, &nodeRef, &entry);
|
||||||
|
|
||||||
if (node)
|
if (node)
|
||||||
node->RemoveReference();
|
node->RemoveReference();
|
||||||
@ -1141,13 +1175,15 @@ NodeManager::_EntryCreated(BMessage *message)
|
|||||||
{
|
{
|
||||||
// get the info
|
// get the info
|
||||||
node_ref dirNodeRef;
|
node_ref dirNodeRef;
|
||||||
|
node_ref nodeRef;
|
||||||
const char* name;
|
const char* name;
|
||||||
if (message->FindInt32("device", &dirNodeRef.device) != B_OK
|
if (message->FindInt32("device", &dirNodeRef.device) != B_OK
|
||||||
|| message->FindInt64("directory", &dirNodeRef.node) != B_OK
|
|| message->FindInt64("directory", &dirNodeRef.node) != B_OK
|
||||||
// || message->FindInt64("node", &nodeID) != B_OK
|
|| message->FindInt64("node", &nodeRef.node) != B_OK
|
||||||
|| message->FindString("name", &name) != B_OK) {
|
|| message->FindString("name", &name) != B_OK) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
nodeRef.device = dirNodeRef.device;
|
||||||
|
|
||||||
// get the directory
|
// get the directory
|
||||||
Node *node = NodeManager::GetDefault()->GetNode(dirNodeRef);
|
Node *node = NodeManager::GetDefault()->GetNode(dirNodeRef);
|
||||||
@ -1160,7 +1196,7 @@ NodeManager::_EntryCreated(BMessage *message)
|
|||||||
Entry *entry;
|
Entry *entry;
|
||||||
if (dir->FindEntry(name, &entry) != B_OK) {
|
if (dir->FindEntry(name, &entry) != B_OK) {
|
||||||
entry_ref ref(dirNodeRef.device, dirNodeRef.node, name);
|
entry_ref ref(dirNodeRef.device, dirNodeRef.node, name);
|
||||||
NodeManager::GetDefault()->CreateEntry(ref, &entry);
|
NodeManager::GetDefault()->CreateEntry(ref, &nodeRef, &entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1209,13 +1245,13 @@ NodeManager::_EntryMoved(BMessage *message)
|
|||||||
// create it if not present
|
// create it if not present
|
||||||
Entry *entry;
|
Entry *entry;
|
||||||
entry_ref newRef(nodeRef.device, newDirID, name);
|
entry_ref newRef(nodeRef.device, newDirID, name);
|
||||||
NodeManager::GetDefault()->CreateEntry(newRef, &entry);
|
NodeManager::GetDefault()->CreateEntry(newRef, &nodeRef, &entry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// move it
|
// move it
|
||||||
entry_ref newRef(nodeRef.device, newDirID, name);
|
entry_ref newRef(nodeRef.device, newDirID, name);
|
||||||
NodeManager::GetDefault()->MoveEntry(node->GetEntry(), newRef);
|
NodeManager::GetDefault()->MoveEntry(node->GetEntry(), newRef, nodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// _StatChanged
|
// _StatChanged
|
||||||
|
@ -225,11 +225,13 @@ public:
|
|||||||
Node *GetNode(const node_ref &nodeRef);
|
Node *GetNode(const node_ref &nodeRef);
|
||||||
Entry *GetEntry(const entry_ref &entryRef);
|
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);
|
status_t CreateDirectory(const node_ref &nodeRef, Directory **_dir);
|
||||||
|
|
||||||
void RemoveEntry(Entry *entry);
|
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 EntryUnreferenced(Entry *entry);
|
||||||
void NodeUnreferenced(Node *node);
|
void NodeUnreferenced(Node *node);
|
||||||
|
Loading…
Reference in New Issue
Block a user