Remove package related dependencies from Node

* Move package related methods from Node to new interface UnpackingNode.
* LeafNode and Directory derive from UnpackingNode now.
* Adjust Volume implementation accordingly.
This commit is contained in:
Ingo Weinhold
2011-11-25 06:17:55 +01:00
parent 5167a80703
commit 20142717e7
10 changed files with 106 additions and 30 deletions
@@ -99,6 +99,13 @@ Directory::FileSize() const
}
Node*
Directory::GetNode()
{
return this;
}
status_t
Directory::AddPackageNode(PackageNode* packageNode)
{
@@ -8,6 +8,7 @@
#include "Node.h"
#include "PackageDirectory.h"
#include "UnpackingNode.h"
struct DirectoryIterator : DoublyLinkedListLinkImpl<DirectoryIterator> {
@@ -23,7 +24,7 @@ struct DirectoryIterator : DoublyLinkedListLinkImpl<DirectoryIterator> {
typedef DoublyLinkedList<DirectoryIterator> DirectoryIteratorList;
class Directory : public Node {
class Directory : public Node, public UnpackingNode {
public:
Directory(ino_t id);
virtual ~Directory();
@@ -39,6 +40,8 @@ public:
virtual timespec ModifiedTime() const;
virtual off_t FileSize() const;
virtual Node* GetNode();
virtual status_t AddPackageNode(PackageNode* packageNode);
virtual void RemovePackageNode(PackageNode* packageNode);
@@ -30,6 +30,7 @@ HAIKU_PACKAGE_FS_SOURCES =
Resolvable.cpp
UnpackingAttributeCookie.cpp
UnpackingAttributeDirectoryCookie.cpp
UnpackingNode.cpp
Version.cpp
Volume.cpp
;
@@ -98,6 +98,13 @@ LeafNode::FileSize() const
}
Node*
LeafNode::GetNode()
{
return this;
}
status_t
LeafNode::AddPackageNode(PackageNode* packageNode)
{
@@ -8,9 +8,10 @@
#include "Node.h"
#include "PackageLeafNode.h"
#include "UnpackingNode.h"
class LeafNode : public Node {
class LeafNode : public Node, public UnpackingNode {
public:
LeafNode(ino_t id);
virtual ~LeafNode();
@@ -26,6 +27,8 @@ public:
virtual timespec ModifiedTime() const;
virtual off_t FileSize() const;
virtual Node* GetNode();
virtual status_t AddPackageNode(PackageNode* packageNode);
virtual void RemovePackageNode(PackageNode* packageNode);
@@ -53,11 +53,6 @@ public:
virtual timespec ModifiedTime() const = 0;
virtual off_t FileSize() const = 0;
virtual status_t AddPackageNode(PackageNode* packageNode) = 0;
virtual void RemovePackageNode(PackageNode* packageNode) = 0;
virtual PackageNode* GetPackageNode() = 0;
virtual status_t Read(off_t offset, void* buffer,
size_t* bufferSize) = 0;
virtual status_t Read(io_request* request) = 0;
@@ -0,0 +1,12 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "UnpackingNode.h"
UnpackingNode::~UnpackingNode()
{
}
@@ -0,0 +1,29 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef UNPACKING_NODE_H
#define UNPACKING_NODE_H
#include <SupportDefs.h>
class Node;
class PackageNode;
class UnpackingNode {
public:
virtual ~UnpackingNode();
virtual Node* GetNode() = 0;
virtual status_t AddPackageNode(PackageNode* packageNode) = 0;
virtual void RemovePackageNode(PackageNode* packageNode) = 0;
virtual PackageNode* GetPackageNode() = 0;
};
#endif // UNPACKING_NODE_H
@@ -949,17 +949,26 @@ Volume::_AddPackageNode(Directory* directory, PackageNode* packageNode,
bool notify, Node*& _node)
{
bool newNode = false;
UnpackingNode* unpackingNode;
Node* node = directory->FindChild(packageNode->Name());
if (node == NULL) {
status_t error = _CreateNode(packageNode->Mode(), directory,
packageNode->Name(), node);
if (node != NULL) {
unpackingNode = dynamic_cast<UnpackingNode*>(node);
if (unpackingNode == NULL)
RETURN_ERROR(B_BAD_VALUE);
} else {
status_t error = _CreateUnpackingNode(packageNode->Mode(), directory,
packageNode->Name(), unpackingNode);
if (error != B_OK)
RETURN_ERROR(error);
node = unpackingNode->GetNode();
newNode = true;
}
BReference<Node> nodeReference(node);
status_t error = node->AddPackageNode(packageNode);
status_t error = unpackingNode->AddPackageNode(packageNode);
if (error != B_OK) {
// remove the node, if created before
if (newNode)
@@ -971,7 +980,7 @@ Volume::_AddPackageNode(Directory* directory, PackageNode* packageNode,
if (newNode) {
notify_entry_created(ID(), directory->ID(), node->Name(),
node->ID());
} else if (packageNode == node->GetPackageNode()) {
} else if (packageNode == unpackingNode->GetPackageNode()) {
// The new package node has become the one representing the node.
// Send stat changed notification for directories and entry
// removed + created notifications for files and symlinks.
@@ -999,15 +1008,19 @@ void
Volume::_RemovePackageNode(Directory* directory, PackageNode* packageNode,
Node* node, bool notify)
{
UnpackingNode* unpackingNode = dynamic_cast<UnpackingNode*>(node);
if (unpackingNode == NULL)
return;
BReference<Node> nodeReference(node);
PackageNode* headPackageNode = node->GetPackageNode();
node->RemovePackageNode(packageNode);
PackageNode* headPackageNode = unpackingNode->GetPackageNode();
unpackingNode->RemovePackageNode(packageNode);
// If the node doesn't have any more package nodes attached, remove it
// completely.
bool nodeRemoved = false;
if (node->GetPackageNode() == NULL) {
if (unpackingNode->GetPackageNode() == NULL) {
// we get and put the vnode to notify the VFS
// TODO: We should probably only do that, if the node is known to the
// VFS in the first place.
@@ -1050,19 +1063,21 @@ Volume::_RemovePackageNode(Directory* directory, PackageNode* packageNode,
status_t
Volume::_CreateNode(mode_t mode, Directory* parent, const char* name,
Node*& _node)
Volume::_CreateUnpackingNode(mode_t mode, Directory* parent, const char* name,
UnpackingNode*& _node)
{
Node* node;
UnpackingNode* unpackingNode;
if (S_ISREG(mode) || S_ISLNK(mode))
node = new(std::nothrow) LeafNode(fNextNodeID++);
unpackingNode = new(std::nothrow) LeafNode(fNextNodeID++);
else if (S_ISDIR(mode))
node = new(std::nothrow) Directory(fNextNodeID++);
unpackingNode = new(std::nothrow) Directory(fNextNodeID++);
else
RETURN_ERROR(B_UNSUPPORTED);
if (node == NULL)
if (unpackingNode == NULL)
RETURN_ERROR(B_NO_MEMORY);
Node* node = unpackingNode->GetNode();
BReference<Node> nodeReference(node, true);
status_t error = node->Init(parent, name);
@@ -1075,7 +1090,7 @@ Volume::_CreateNode(mode_t mode, Directory* parent, const char* name,
nodeReference.Detach();
// we keep the initial node reference for this table
_node = node;
_node = unpackingNode;
return B_OK;
}
@@ -1327,23 +1342,25 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
}
// create the directory
Node* directory;
error = _CreateNode(S_IFDIR, fRootDirectory, directoryName, directory);
UnpackingNode* directory;
error = _CreateUnpackingNode(S_IFDIR, fRootDirectory, directoryName,
directory);
if (error != B_OK)
RETURN_ERROR(error);
// publish its vnode, so the VFS will find it without asking us
error = PublishVNode(directory);
Node* directoryNode = directory->GetNode();
error = PublishVNode(directoryNode);
if (error != B_OK) {
_RemoveNode(directory);
_RemoveNode(directoryNode);
RETURN_ERROR(error);
}
// bind the directory
error = vfs_bind_mount_directory(st.st_dev, st.st_ino, fFSVolume->id,
directory->ID());
directoryNode->ID());
PutVNode(directory->ID());
PutVNode(directoryNode->ID());
// release our reference again -- on success
// vfs_bind_mount_directory() got one
@@ -21,6 +21,7 @@
class Directory;
class Node;
class PackageFSRoot;
class UnpackingNode;
enum MountType {
@@ -117,8 +118,9 @@ private:
PackageNode* packageNode, Node* node,
bool notify);
status_t _CreateNode(mode_t mode, Directory* parent,
const char* name, Node*& _node);
status_t _CreateUnpackingNode(mode_t mode,
Directory* parent, const char* name,
UnpackingNode*& _node);
// does *not* return a reference
void _RemoveNode(Node* node);