1// StatCacheServerImpl.h
2
3#ifndef STAT_CACHE_SERVER_IMPL_H
4#define STAT_CACHE_SERVER_IMPL_H
5
6#include <hash_map>
7#include <string>
8
9#include <Entry.h>
10#include <MessageQueue.h>
11#include <Node.h>
12#include <OS.h>
13
14class Directory;
15class Entry;
16class Node;
17class SymLink;
18
19// NodeRefHash
20struct NodeRefHash
21{
22	size_t operator()(const node_ref &nodeRef) const;
23};
24
25// EntryRefHash
26struct EntryRefHash
27{
28	size_t operator()(const entry_ref &entryRef) const;
29};
30
31// Referencable
32class Referencable {
33public:
34	Referencable()
35		: fReferenceCount(1),
36		  fReferenceBaseCount(0)
37	{
38	}
39
40	virtual ~Referencable()
41	{
42	}
43
44	void AddReference()
45	{
46		fReferenceCount++;
47	}
48
49	bool RemoveReference()
50	{
51		if (--fReferenceCount <= fReferenceBaseCount) {
52			Unreferenced();
53			return true;
54		}
55		return false;
56	}
57
58	int32 CountReferences() const
59	{
60		return fReferenceCount;
61	}
62
63protected:
64	virtual void Unreferenced() {};
65
66protected:
67	int32	fReferenceCount;
68	int32	fReferenceBaseCount;
69	bool	fDeleteWhenUnreferenced;
70};
71
72// Entry
73class Entry : public Referencable {
74public:
75	Entry();
76	~Entry();
77
78	status_t SetTo(Directory *parent, const char *name);
79
80	Directory *GetParent() const;
81
82	const char *GetName() const;
83
84	void SetNode(Node *node);
85	Node *GetNode() const;
86
87	void SetPrevious(Entry *entry);
88	Entry *GetPrevious() const;
89	void SetNext(Entry *entry);
90	Entry *GetNext() const;
91
92	entry_ref GetEntryRef() const;
93	status_t GetPath(string& path);
94
95protected:
96	virtual void Unreferenced();
97
98private:
99	Directory	*fParent;
100	string		fName;
101	Node		*fNode;
102	Entry		*fPrevious;
103	Entry		*fNext;
104};
105
106// Node
107class Node : public Referencable {
108public:
109	Node(const struct stat &st);
110	virtual ~Node();
111
112	virtual status_t SetTo(Entry *entry);
113
114	status_t GetPath(string& path);
115
116	const struct stat &GetStat() const;
117	status_t GetStat(struct stat *st);
118	status_t UpdateStat();
119	void MarkStatInvalid();
120
121	void SetEntry(Entry *entry);
122	Entry *GetEntry() const;
123
124	node_ref GetNodeRef() const;
125
126protected:
127	virtual void Unreferenced();
128
129protected:
130	Entry		*fEntry;
131	struct stat	fStat;
132	bool		fStatValid;
133};
134
135// Directory
136class Directory : public Node {
137public:
138	Directory(const struct stat &st);
139	~Directory();
140
141	virtual status_t SetTo(Entry *entry);
142
143	status_t FindEntry(const char *name, Entry **entry);
144	Entry *GetFirstEntry() const;
145	Entry *GetNextEntry(Entry *entry) const;
146
147	status_t ReadAllEntries();
148
149	bool IsComplete() const;
150
151	void AddEntry(Entry *entry);
152	void RemoveEntry(Entry *entry);
153
154private:
155	Entry	*fFirstEntry;
156	Entry	*fLastEntry;
157	bool	fIsComplete;
158};
159
160// SymLink
161class SymLink : public Node {
162public:
163	SymLink(const struct stat &st);
164	~SymLink();
165
166	virtual status_t SetTo(Entry *entry);
167
168	const char *GetTarget() const;
169
170private:
171	string	fTarget;
172};
173
174// NodeMonitor
175class NodeMonitor : public BLooper {
176public:
177	NodeMonitor();
178	virtual ~NodeMonitor();
179
180	status_t Init();
181
182	virtual void MessageReceived(BMessage *message);
183
184	status_t StartWatching(Node *node);
185	status_t StopWatching(Node *node);
186
187	status_t GetNextMonitoringMessage(BMessage **message);
188
189private:
190	int32			fCurrentNodeMonitorLimit;
191	BMessageQueue	fMessageQueue;
192	sem_id			fMessageCountSem;
193};
194
195// PathResolver
196class PathResolver {
197public:
198	PathResolver();
199
200	status_t FindEntry(const char *path, bool traverse, Entry **_entry);
201	status_t FindEntry(Entry *entry, const char *path, bool traverse,
202		Entry **_entry);
203	status_t FindNode(const char *path, bool traverse, Node **node);
204
205	status_t ResolveSymlink(Node *node, Node **_node);
206	status_t ResolveSymlink(Node *node, Entry **entry);
207	status_t ResolveSymlink(Entry *entry, Entry **_entry);
208
209private:
210	int32	fSymLinkCounter;
211};
212
213// NodeManager
214class NodeManager : public BLocker {
215public:
216	NodeManager();
217	~NodeManager();
218
219	static NodeManager *GetDefault();
220
221	status_t Init();
222
223	Directory *GetRootDirectory() const;
224
225	Node *GetNode(const node_ref &nodeRef);
226	Entry *GetEntry(const entry_ref &entryRef);
227
228	status_t CreateEntry(const entry_ref &entryRef, const node_ref *nodeRef,
229		Entry **_entry);
230	status_t CreateDirectory(const node_ref &nodeRef, Directory **_dir);
231
232	void RemoveEntry(Entry *entry);
233	void MoveEntry(Entry *entry, const entry_ref &newRef,
234		const node_ref &nodeRef);
235
236	void EntryUnreferenced(Entry *entry);
237	void NodeUnreferenced(Node *node);
238
239	status_t StartWatching(Node *node);
240	status_t StopWatching(Node *node);
241
242private:
243	static int32 _NodeMonitoringProcessorEntry(void *data);
244	int32 _NodeMonitoringProcessor();
245
246	status_t _CreateNode(Entry *entry, Node **_node);
247
248	void _EntryCreated(BMessage *message);
249	void _EntryRemoved(BMessage *message);
250	void _EntryMoved(BMessage *message);
251	void _StatChanged(BMessage *message);
252
253private:
254	typedef hash_map<entry_ref, Entry*, EntryRefHash> EntryMap;
255	typedef hash_map<node_ref, Node*, NodeRefHash> NodeMap;
256
257	EntryMap	fEntries;
258	NodeMap		fNodes;
259	Directory	*fRootDirectory;
260	NodeMonitor	*fNodeMonitor;
261	thread_id	fNodeMonitoringProcessor;
262
263	static NodeManager	sManager;
264};
265
266#endif	// STAT_CACHE_SERVER_IMPL_H
267