⛏️ index : buildtools.git

author Ingo Weinhold <ingo_weinhold@gmx.de> 2007-06-03 16:25:35.0 +00:00:00
committer Ingo Weinhold <ingo_weinhold@gmx.de> 2007-06-03 16:25:35.0 +00:00:00
commit
f4194f2ee8f5173adc1be5c9b318307cdb1d1f13 [patch]
tree
058df1a4df9f9b37161db9b62d2e1e040e4fbf86
parent
392bb3947870476529eaf728d18c80ffa7e7a279
download
f4194f2ee8f5173adc1be5c9b318307cdb1d1f13.tar.gz

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(-)

diff --git a/jam/StatCacheServer.cpp b/jam/StatCacheServer.cpp
index a7db582..862069c 100644
--- a/jam/StatCacheServer.cpp
+++ b/jam/StatCacheServer.cpp
@@ -18,7 +18,7 @@

//#define DBG(x) { x; }
#define DBG(x)
#define OUT printf
#define OUT(format...) {printf(format); fflush(stdout);}

static const int32 kMaxSymlinks = 32;

@@ -29,6 +29,14 @@
// private BeOS syscall to set the  node monitor slot limits
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
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 @@

// CreateEntry
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 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) {
		// entry does not yet exist -- create it

@@ -900,9 +918,23 @@
			if (error != B_OK) {
				delete entry;
				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);
			node->RemoveReference();
				// reference acquired by _CreateNode()

			// initialization successful: add the entry to the dir and to the
			// entry map
@@ -985,7 +1017,8 @@

// MoveEntry
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
	node_ref newDirRef;
@@ -998,18 +1031,19 @@
		return;
	}

	// If the directory and/or the name changed, we remove the old entry and
	// create a new one.
	// If the directory, the name, or the node (missed B_ENTRY_REMOVED and
	// B_ENTRY_CREATED) changed, we remove the old entry and create a new one.
	Node *node = entry->GetNode();
	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
		// deleted
		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 @@
{
	// get the info
	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", &nodeID) != B_OK
		|| message->FindInt64("node", &nodeRef.node) != B_OK
		|| message->FindString("name", &name) != B_OK) {
		return;
	}
	nodeRef.device = dirNodeRef.device;

	// get the directory
	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 @@
		// create it if not present
		Entry *entry;
		entry_ref newRef(nodeRef.device, newDirID, name);
		NodeManager::GetDefault()->CreateEntry(newRef, &entry);
		NodeManager::GetDefault()->CreateEntry(newRef, &nodeRef, &entry);
		return;
	}

	// move it
	entry_ref newRef(nodeRef.device, newDirID, name);
	NodeManager::GetDefault()->MoveEntry(node->GetEntry(), newRef);
	NodeManager::GetDefault()->MoveEntry(node->GetEntry(), newRef, nodeRef);
}

// _StatChanged
diff --git a/jam/StatCacheServerImpl.h b/jam/StatCacheServerImpl.h
index 1137016..14cd3af 100644
--- a/jam/StatCacheServerImpl.h
+++ b/jam/StatCacheServerImpl.h
@@ -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);