1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef USERLAND_FS_FUSE_ENTRY_H
6#define USERLAND_FS_FUSE_ENTRY_H
7
8#include <new>
9
10#include <RWLockManager.h>
11
12#include <util/DoublyLinkedList.h>
13#include <util/OpenHashTable.h>
14
15#include "String.h"
16
17#include "fuse_api.h"
18
19
20namespace UserlandFS {
21
22struct FUSENode;
23
24
25struct FUSEEntryRef {
26	ino_t		parentID;
27	const char*	name;
28
29	FUSEEntryRef(ino_t parentID, const char* name)
30		:
31		parentID(parentID),
32		name(name)
33	{
34	}
35};
36
37
38struct FUSEEntry : DoublyLinkedListLinkImpl<FUSEEntry> {
39	FUSENode*	parent;
40	char*		name;
41	FUSENode*	node;
42	FUSEEntry*	hashLink;
43
44	FUSEEntry()
45		:
46		name(NULL)
47	{
48	}
49
50	~FUSEEntry()
51	{
52		free(name);
53	}
54
55
56	static FUSEEntry* Create(FUSENode* parent, const char* name, FUSENode* node)
57	{
58		FUSEEntry* entry = new(std::nothrow) FUSEEntry;
59		if (entry == NULL)
60			return NULL;
61
62		char* clonedName = strdup(name);
63		if (clonedName == NULL) {
64			delete entry;
65			return NULL;
66		}
67
68		entry->parent = parent;
69		entry->name = clonedName;
70		entry->node = node;
71
72		return entry;
73	}
74};
75
76
77typedef DoublyLinkedList<FUSEEntry> FUSEEntryList;
78
79
80struct FUSENode : RWLockable {
81	ino_t			id;
82	FUSEEntryList	entries;
83	int				type;
84	int32			refCount;
85	int32			cacheCount;
86	bool			dirty;
87	FUSENode*		hashLink;
88
89	FUSENode(ino_t id, int type)
90		:
91		id(id),
92		type(type),
93		refCount(1),
94		cacheCount(0),
95		dirty(false)
96	{
97	}
98
99	FUSENode* Parent() const
100	{
101		FUSEEntry* entry = entries.Head();
102		return entry != NULL ? entry->parent : NULL;
103	}
104};
105
106
107struct FUSEEntryHashDefinition {
108	typedef FUSEEntryRef	KeyType;
109	typedef	FUSEEntry		ValueType;
110
111	size_t HashKey(const FUSEEntryRef& key) const
112		{ return ((uint32)key.parentID ^ (uint32)(key.parentID >> 32)) * 37
113			+ string_hash(key.name); }
114	size_t Hash(const FUSEEntry* value) const
115		{ return HashKey(FUSEEntryRef(value->parent->id, value->name)); }
116	bool Compare(const FUSEEntryRef& key, const FUSEEntry* value) const
117		{ return value->parent->id == key.parentID
118			&& strcmp(value->name, key.name) == 0; }
119	FUSEEntry*& GetLink(FUSEEntry* value) const
120		{ return value->hashLink; }
121};
122
123
124struct FUSENodeHashDefinition {
125	typedef ino_t		KeyType;
126	typedef	FUSENode	ValueType;
127
128	size_t HashKey(ino_t key) const
129		{ return (uint32)key ^ (uint32)(key >> 32); }
130	size_t Hash(const FUSENode* value) const
131		{ return HashKey(value->id); }
132	bool Compare(ino_t key, const FUSENode* value) const
133		{ return value->id == key; }
134	FUSENode*& GetLink(FUSENode* value) const
135		{ return value->hashLink; }
136};
137
138
139typedef BOpenHashTable<FUSEEntryHashDefinition> FUSEEntryTable;
140typedef BOpenHashTable<FUSENodeHashDefinition> FUSENodeTable;
141
142
143}	// namespace UserlandFS
144
145using UserlandFS::FUSENode;
146
147
148#endif	// USERLAND_FS_FUSE_ENTRY_H
149