Example #1
0
/*!	This method recursively iterates through the descendents of the given
	package root node and adds all package nodes to the node tree in
	pre-order.
	Due to limited kernel stack space we avoid deep recursive function calls
	and rather use the package node stack implied by the tree.
*/
status_t
Volume::_AddPackageContentRootNode(Package* package,
	PackageNode* rootPackageNode, bool notify)
{
	PackageNode* packageNode = rootPackageNode;
	Directory* directory = fRootDirectory;
	directory->WriteLock();

	do {
		Node* node;
		status_t error = _AddPackageNode(directory, packageNode, notify, node);
			// returns B_OK with a NULL node, when skipping the node
		if (error != B_OK) {
			// unlock all directories
			while (directory != NULL) {
				directory->WriteUnlock();
				directory = directory->Parent();
			}

			// remove the added package nodes
			_RemovePackageContentRootNode(package, rootPackageNode, packageNode,
				notify);
			RETURN_ERROR(error);
		}

		// recurse into directory, unless we're supposed to skip the node
		if (node != NULL) {
			if (PackageDirectory* packageDirectory
					= dynamic_cast<PackageDirectory*>(packageNode)) {
				if (packageDirectory->FirstChild() != NULL) {
					directory = dynamic_cast<Directory*>(node);
					packageNode = packageDirectory->FirstChild();
					directory->WriteLock();
					continue;
				}
			}
		}

		// continue with the next available (ancestors's) sibling
		do {
			PackageDirectory* packageDirectory = packageNode->Parent();
			PackageNode* sibling = packageDirectory != NULL
				? packageDirectory->NextChild(packageNode) : NULL;

			if (sibling != NULL) {
				packageNode = sibling;
				break;
			}

			// no more siblings -- go back up the tree
			packageNode = packageDirectory;
			directory->WriteUnlock();
			directory = directory->Parent();
				// the parent is still locked, so this is safe
		} while (packageNode != NULL);
	} while (packageNode != NULL);

	return B_OK;
}
Example #2
0
/*!	Recursively iterates through the descendents of the given package root node
	and removes all package nodes from the node tree in post-order, until
	encountering \a endPackageNode (if non-null).
	Due to limited kernel stack space we avoid deep recursive function calls
	and rather use the package node stack implied by the tree.
*/
void
Volume::_RemovePackageContentRootNode(Package* package,
	PackageNode* rootPackageNode, PackageNode* endPackageNode, bool notify)
{
	PackageNode* packageNode = rootPackageNode;
	Directory* directory = fRootDirectory;
	directory->WriteLock();

	do {
		if (packageNode == endPackageNode)
			break;

		// recurse into directory
		if (PackageDirectory* packageDirectory
				= dynamic_cast<PackageDirectory*>(packageNode)) {
			if (packageDirectory->FirstChild() != NULL) {
				if (Directory* childDirectory = dynamic_cast<Directory*>(
						directory->FindChild(packageNode->Name()))) {
					directory = childDirectory;
					packageNode = packageDirectory->FirstChild();
					directory->WriteLock();
					continue;
				}
			}
		}

		// continue with the next available (ancestors's) sibling
		do {
			PackageDirectory* packageDirectory = packageNode->Parent();
			PackageNode* sibling = packageDirectory != NULL
				? packageDirectory->NextChild(packageNode) : NULL;

			// we're done with the node -- remove it
			_RemovePackageNode(directory, packageNode,
				directory->FindChild(packageNode->Name()), notify);

			if (sibling != NULL) {
				packageNode = sibling;
				break;
			}

			// no more siblings -- go back up the tree
			packageNode = packageDirectory;
			directory->WriteUnlock();
			directory = directory->Parent();
				// the parent is still locked, so this is safe
		} while (packageNode != NULL/* && packageNode != rootPackageNode*/);
	} while (packageNode != NULL/* && packageNode != rootPackageNode*/);
}