1/*
2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef NODE_H
6#define NODE_H
7
8
9#include <fs_interface.h>
10
11#include <AutoLocker.h>
12#include <Referenceable.h>
13
14#include <lock.h>
15#include <util/DoublyLinkedList.h>
16#include <util/khash.h>
17#include <util/OpenHashTable.h>
18
19
20class AttributeCookie;
21class AttributeDirectoryCookie;
22class AttributeIndexer;
23class Directory;
24class PackageNode;
25
26
27// node flags
28enum {
29	NODE_FLAG_KEEP_NAME		= 0x01,
30		// Init(): Take over ownership of the given name (i.e. free in
31		// destructor).
32	NODE_FLAG_CONST_NAME	= 0x02,
33		// Init(): The given name is a constant that won't go away during the
34		// lifetime of the object. No need to copy.
35	NODE_FLAG_OWNS_NAME		= NODE_FLAG_KEEP_NAME,
36	NODE_FLAG_KNOWN_TO_VFS	= 0x04,
37		// internal flag
38};
39
40
41class Node : public BReferenceable, public DoublyLinkedListLinkImpl<Node> {
42public:
43								Node(ino_t id);
44	virtual						~Node();
45
46	inline	bool				ReadLock();
47	inline	void				ReadUnlock();
48	inline	bool				WriteLock();
49	inline	void				WriteUnlock();
50
51			ino_t				ID() const		{ return fID; }
52			Directory*			Parent() const	{ return fParent; }
53			const char*			Name() const	{ return fName; }
54
55			Node*&				NameHashTableNext()
56									{ return fNameHashTableNext; }
57			Node*&				IDHashTableNext()
58									{ return fIDHashTableNext; }
59
60	virtual	status_t			Init(Directory* parent, const char* name,
61									uint32 flags);
62									// If specified to keep the name, it does
63									// so also on error.
64
65	virtual	status_t			VFSInit(dev_t deviceID);
66									// base class version must be called on
67									// success
68	virtual	void				VFSUninit();
69									// base class version must be called
70	inline	bool				IsKnownToVFS() const;
71
72			void				SetID(ino_t id);
73			void				SetParent(Directory* parent);
74
75	virtual	mode_t				Mode() const = 0;
76	virtual	uid_t				UserID() const;
77	virtual	gid_t				GroupID() const;
78	virtual	timespec			ModifiedTime() const = 0;
79	virtual	off_t				FileSize() const = 0;
80
81	virtual	status_t			Read(off_t offset, void* buffer,
82									size_t* bufferSize) = 0;
83	virtual	status_t			Read(io_request* request) = 0;
84
85	virtual	status_t			ReadSymlink(void* buffer,
86									size_t* bufferSize) = 0;
87
88	virtual	status_t			OpenAttributeDirectory(
89									AttributeDirectoryCookie*& _cookie);
90	virtual	status_t			OpenAttribute(const char* name, int openMode,
91									AttributeCookie*& _cookie);
92
93	virtual	status_t			IndexAttribute(AttributeIndexer* indexer);
94	virtual	void*				IndexCookieForAttribute(const char* name) const;
95
96protected:
97			rw_lock				fLock;
98			ino_t				fID;
99			Directory*			fParent;
100			char*				fName;
101			Node*				fNameHashTableNext;
102			Node*				fIDHashTableNext;
103			uint32				fFlags;
104};
105
106
107bool
108Node::ReadLock()
109{
110	return rw_lock_read_lock(&fLock) == B_OK;
111}
112
113
114void
115Node::ReadUnlock()
116{
117	rw_lock_read_unlock(&fLock);
118}
119
120
121bool
122Node::WriteLock()
123{
124	return rw_lock_write_lock(&fLock) == B_OK;
125}
126
127
128void
129Node::WriteUnlock()
130{
131	rw_lock_write_unlock(&fLock);
132}
133
134
135bool
136Node::IsKnownToVFS() const
137{
138	return (fFlags & NODE_FLAG_KNOWN_TO_VFS) != 0;
139}
140
141
142// #pragma mark -
143
144
145struct NodeNameHashDefinition {
146	typedef const char*		KeyType;
147	typedef	Node			ValueType;
148
149	size_t HashKey(const char* key) const
150	{
151		return hash_hash_string(key);
152	}
153
154	size_t Hash(const Node* value) const
155	{
156		return HashKey(value->Name());
157	}
158
159	bool Compare(const char* key, const Node* value) const
160	{
161		return strcmp(value->Name(), key) == 0;
162	}
163
164	Node*& GetLink(Node* value) const
165	{
166		return value->NameHashTableNext();
167	}
168};
169
170
171struct NodeIDHashDefinition {
172	typedef ino_t	KeyType;
173	typedef	Node	ValueType;
174
175	size_t HashKey(ino_t key) const
176	{
177		return (uint64)(key >> 32) ^ (uint32)key;
178	}
179
180	size_t Hash(const Node* value) const
181	{
182		return HashKey(value->ID());
183	}
184
185	bool Compare(ino_t key, const Node* value) const
186	{
187		return value->ID() == key;
188	}
189
190	Node*& GetLink(Node* value) const
191	{
192		return value->IDHashTableNext();
193	}
194};
195
196typedef DoublyLinkedList<Node> NodeList;
197
198typedef BOpenHashTable<NodeNameHashDefinition> NodeNameHashTable;
199typedef BOpenHashTable<NodeIDHashDefinition> NodeIDHashTable;
200
201typedef AutoLocker<Node, AutoLockerReadLocking<Node> > NodeReadLocker;
202typedef AutoLocker<Node, AutoLockerWriteLocking<Node> > NodeWriteLocker;
203
204
205#endif	// NODE_H
206