1/*
2 * Copyright 2009-2013, 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/OpenHashTable.h>
17
18#include "String.h"
19#include "StringKey.h"
20
21
22class AttributeCookie;
23class AttributeDirectoryCookie;
24class AttributeIndexer;
25class Directory;
26class PackageNode;
27
28
29// internal node flags
30enum {
31	NODE_FLAG_KNOWN_TO_VFS		= 0x01,
32	NODE_FLAG_VFS_INIT_ERROR	= 0x02,
33		// used by subclasses
34};
35
36
37class Node : public BReferenceable, public DoublyLinkedListLinkImpl<Node> {
38public:
39								Node(ino_t id);
40	virtual						~Node();
41
42	inline	bool				ReadLock();
43	inline	void				ReadUnlock();
44	inline	bool				WriteLock();
45	inline	void				WriteUnlock();
46
47			ino_t				ID() const		{ return fID; }
48			Directory*			Parent() const	{ return fParent; }
49			const String&		Name() const	{ return fName; }
50
51			Node*&				NameHashTableNext()
52									{ return fNameHashTableNext; }
53			Node*&				IDHashTableNext()
54									{ return fIDHashTableNext; }
55
56	virtual	status_t			Init(Directory* parent, const String& name);
57
58	virtual	status_t			VFSInit(dev_t deviceID);
59									// base class version must be called on
60									// success
61	virtual	void				VFSUninit();
62									// base class version must be called
63	inline	bool				IsKnownToVFS() const;
64	inline	bool				HasVFSInitError() const;
65
66			void				SetID(ino_t id);
67			void				SetParent(Directory* parent);
68
69	virtual	mode_t				Mode() const = 0;
70	virtual	uid_t				UserID() const;
71	virtual	gid_t				GroupID() const;
72	virtual	timespec			ModifiedTime() const = 0;
73	virtual	off_t				FileSize() const = 0;
74
75	virtual	status_t			Read(off_t offset, void* buffer,
76									size_t* bufferSize) = 0;
77	virtual	status_t			Read(io_request* request) = 0;
78
79	virtual	status_t			ReadSymlink(void* buffer,
80									size_t* bufferSize) = 0;
81
82	virtual	status_t			OpenAttributeDirectory(
83									AttributeDirectoryCookie*& _cookie);
84	virtual	status_t			OpenAttribute(const StringKey& name,
85									int openMode, AttributeCookie*& _cookie);
86
87	virtual	status_t			IndexAttribute(AttributeIndexer* indexer);
88	virtual	void*				IndexCookieForAttribute(const StringKey& name)
89									const;
90
91protected:
92			rw_lock				fLock;
93			ino_t				fID;
94			Directory*			fParent;
95			String				fName;
96			Node*				fNameHashTableNext;
97			Node*				fIDHashTableNext;
98			uint32				fFlags;
99};
100
101
102bool
103Node::ReadLock()
104{
105	return rw_lock_read_lock(&fLock) == B_OK;
106}
107
108
109void
110Node::ReadUnlock()
111{
112	rw_lock_read_unlock(&fLock);
113}
114
115
116bool
117Node::WriteLock()
118{
119	return rw_lock_write_lock(&fLock) == B_OK;
120}
121
122
123void
124Node::WriteUnlock()
125{
126	rw_lock_write_unlock(&fLock);
127}
128
129
130bool
131Node::IsKnownToVFS() const
132{
133	return (fFlags & NODE_FLAG_KNOWN_TO_VFS) != 0;
134}
135
136
137bool
138Node::HasVFSInitError() const
139{
140	return (fFlags & NODE_FLAG_VFS_INIT_ERROR) != 0;
141}
142
143
144// #pragma mark -
145
146
147struct NodeNameHashDefinition {
148	typedef StringKey	KeyType;
149	typedef	Node		ValueType;
150
151	size_t HashKey(const StringKey& key) const
152	{
153		return key.Hash();
154	}
155
156	size_t Hash(const Node* value) const
157	{
158		return value->Name().Hash();
159	}
160
161	bool Compare(const StringKey& key, const Node* value) const
162	{
163		return key == value->Name();
164	}
165
166	Node*& GetLink(Node* value) const
167	{
168		return value->NameHashTableNext();
169	}
170};
171
172
173struct NodeIDHashDefinition {
174	typedef ino_t	KeyType;
175	typedef	Node	ValueType;
176
177	size_t HashKey(ino_t key) const
178	{
179		return (uint64)(key >> 32) ^ (uint32)key;
180	}
181
182	size_t Hash(const Node* value) const
183	{
184		return HashKey(value->ID());
185	}
186
187	bool Compare(ino_t key, const Node* value) const
188	{
189		return value->ID() == key;
190	}
191
192	Node*& GetLink(Node* value) const
193	{
194		return value->IDHashTableNext();
195	}
196};
197
198typedef DoublyLinkedList<Node> NodeList;
199
200typedef BOpenHashTable<NodeNameHashDefinition> NodeNameHashTable;
201typedef BOpenHashTable<NodeIDHashDefinition> NodeIDHashTable;
202
203typedef AutoLocker<Node, AutoLockerReadLocking<Node> > NodeReadLocker;
204typedef AutoLocker<Node, AutoLockerWriteLocking<Node> > NodeWriteLocker;
205
206
207#endif	// NODE_H
208