xref: /haiku/src/add-ons/kernel/file_systems/packagefs/volume/Volume.h (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
1 /*
2  * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef VOLUME_H
6 #define VOLUME_H
7 
8 
9 #include <fs_interface.h>
10 
11 #include <condition_variable.h>
12 #include <lock.h>
13 #include <util/AutoLock.h>
14 #include <util/DoublyLinkedList.h>
15 #include <util/KMessage.h>
16 
17 #include <packagefs.h>
18 
19 #include "Index.h"
20 #include "Node.h"
21 #include "NodeListener.h"
22 #include "Package.h"
23 #include "PackageLinksListener.h"
24 #include "PackagesDirectory.h"
25 #include "PackageSettings.h"
26 #include "Query.h"
27 
28 
29 class Directory;
30 class PackageFSRoot;
31 class PackagesDirectory;
32 class UnpackingNode;
33 
34 typedef IndexHashTable::Iterator IndexDirIterator;
35 
36 
37 typedef PackageFSMountType MountType;
38 
39 
40 class Volume : public DoublyLinkedListLinkImpl<Volume>,
41 	private PackageLinksListener {
42 public:
43 								Volume(fs_volume* fsVolume);
44 								~Volume();
45 
46 	inline	bool				ReadLock() const;
47 	inline	void				ReadUnlock() const;
48 	inline	bool				WriteLock();
49 	inline	void				WriteUnlock();
50 	inline	bool				IsWriteLocked() const;
51 
52 			fs_volume*			FSVolume() const	{ return fFSVolume; }
53 			dev_t				ID() const			{ return fFSVolume->id; }
54 			Directory*			RootDirectory() const { return fRootDirectory; }
55 
56 			::MountType			MountType() const	{ return fMountType; }
57 
58 			void				SetPackageFSRoot(::PackageFSRoot* root)
59 									{ fPackageFSRoot = root; }
60 			::PackageFSRoot*	PackageFSRoot() const
61 									{ return fPackageFSRoot; }
62 
63 			dev_t				MountPointDeviceID() const
64 									{ return fMountPoint.deviceID; }
65 			ino_t				MountPointNodeID() const
66 									{ return fMountPoint.nodeID; }
67 
68 			status_t			Mount(const char* parameterString);
69 			void				Unmount();
70 
71 			Node*				FindNode(ino_t nodeID) const
72 									{ return fNodes.Lookup(nodeID); }
73 
74 			status_t			IOCtl(Node* node, uint32 operation,
75 									void* buffer, size_t size);
76 
77 			// node listeners -- volume must be write-locked
78 			void				AddNodeListener(NodeListener* listener,
79 									Node* node);
80 			void				RemoveNodeListener(NodeListener* listener);
81 
82 			// query support -- volume must be write-locked
83 			void				AddQuery(Query* query);
84 			void				RemoveQuery(Query* query);
85 			void				UpdateLiveQueries(Node* node,
86 									const char* attribute, int32 type,
87 									const void* oldKey, size_t oldLength,
88 									const void* newKey, size_t newLength);
89 
90 			Index*				FindIndex(const StringKey& name) const
91 									{ return fIndices.Lookup(name); }
92 			IndexDirIterator	GetIndexDirIterator() const
93 									{ return fIndices.GetIterator(); }
94 
95 			// VFS wrappers
96 			status_t			GetVNode(ino_t nodeID, Node*& _node);
97 			status_t			PutVNode(ino_t nodeID);
98 			status_t			RemoveVNode(ino_t nodeID);
99 			status_t			PublishVNode(Node* node);
100 
101 private:
102 	// PackageLinksListener
103 	virtual	void				PackageLinkNodeAdded(Node* node);
104 	virtual	void				PackageLinkNodeRemoved(Node* node);
105 	virtual	void				PackageLinkNodeChanged(Node* node,
106 									uint32 statFields,
107 									const OldNodeAttributes& oldAttributes);
108 
109 private:
110 			struct ShineThroughDirectory;
111 			struct ActivationChangeRequest;
112 
113 private:
114 			status_t			_LoadOldPackagesStates(
115 									const char* packagesState);
116 
117 			status_t			_AddInitialPackages();
118 			status_t			_AddInitialPackagesFromActivationFile(
119 									PackagesDirectory* packagesDirectory);
120 			status_t			_AddInitialPackagesFromDirectory();
121 			status_t			_LoadAndAddInitialPackage(
122 									PackagesDirectory* packagesDirectory,
123 									const char* name);
124 
125 	inline	void				_AddPackage(Package* package);
126 	inline	void				_RemovePackage(Package* package);
127 			void				_RemoveAllPackages();
128 	inline	Package*			_FindPackage(const char* fileName) const;
129 
130 			status_t			_AddPackageContent(Package* package,
131 									bool notify);
132 			void				_RemovePackageContent(Package* package,
133 									PackageNode* endNode, bool notify);
134 
135 			status_t			_AddPackageContentRootNode(Package* package,
136 									PackageNode* node, bool notify);
137 			void				_RemovePackageContentRootNode(Package* package,
138 									PackageNode* packageNode,
139 									PackageNode* endPackageNode, bool notify);
140 
141 			status_t			_AddPackageNode(Directory* directory,
142 									PackageNode* packageNode, bool notify,
143 									Node*& _node);
144 			void				_RemovePackageNode(Directory* directory,
145 									PackageNode* packageNode, Node* node,
146 									bool notify);
147 
148 			status_t			_CreateUnpackingNode(mode_t mode,
149 									Directory* parent, const String& name,
150 									UnpackingNode*& _node);
151 									// does *not* return a reference
152 			void				_RemoveNode(Node* node);
153 			void				_RemoveNodeAndVNode(Node* node);
154 									// caller must hold a reference
155 
156 			status_t			_LoadPackage(
157 									PackagesDirectory* packagesDirectory,
158 									const char* name, Package*& _package);
159 
160 			status_t			_ChangeActivation(
161 									ActivationChangeRequest& request);
162 
163 			status_t			_InitMountType(const char* mountType);
164 			status_t			_CreateShineThroughDirectory(Directory* parent,
165 									const char* name, Directory*& _directory);
166 			status_t			_CreateShineThroughDirectories(
167 									const char* shineThroughSetting);
168 			status_t			_PublishShineThroughDirectories();
169 
170 			status_t			_AddPackageLinksDirectory();
171 			void				_RemovePackageLinksDirectory();
172 			void				_AddPackageLinksNode(Node* node);
173 			void				_RemovePackageLinksNode(Node* node);
174 
175 	inline	Volume*				_SystemVolumeIfNotSelf() const;
176 
177 			void				_NotifyNodeAdded(Node* node);
178 			void				_NotifyNodeRemoved(Node* node);
179 			void				_NotifyNodeChanged(Node* node,
180 									uint32 statFields,
181 									const OldNodeAttributes& oldAttributes);
182 
183 private:
184 	mutable	rw_lock				fLock;
185 			fs_volume*			fFSVolume;
186 			Directory*			fRootDirectory;
187 			::PackageFSRoot*	fPackageFSRoot;
188 			::MountType			fMountType;
189 			PackagesDirectory*	fPackagesDirectory;
190 			PackagesDirectoryList fPackagesDirectories;
191 			PackagesDirectoryHashTable fPackagesDirectoriesByNodeRef;
192 			PackageSettings		fPackageSettings;
193 
194 			struct {
195 				dev_t			deviceID;
196 				ino_t			nodeID;
197 			} fMountPoint;
198 
199 			NodeIDHashTable		fNodes;
200 			NodeListenerHashTable fNodeListeners;
201 			PackageFileNameHashTable fPackages;
202 			QueryList			fQueries;
203 			IndexHashTable		fIndices;
204 
205 			ino_t				fNextNodeID;
206 };
207 
208 
209 bool
210 Volume::ReadLock() const
211 {
212 	return rw_lock_read_lock(&fLock) == B_OK;
213 }
214 
215 
216 void
217 Volume::ReadUnlock() const
218 {
219 	rw_lock_read_unlock(&fLock);
220 }
221 
222 
223 bool
224 Volume::WriteLock()
225 {
226 	return rw_lock_write_lock(&fLock) == B_OK;
227 }
228 
229 
230 void
231 Volume::WriteUnlock()
232 {
233 	rw_lock_write_unlock(&fLock);
234 }
235 
236 
237 bool
238 Volume::IsWriteLocked() const
239 {
240 	return find_thread(NULL) == fLock.holder;
241 }
242 
243 
244 typedef AutoLocker<const Volume, AutoLockerReadLocking<const Volume> >
245 	VolumeReadLocker;
246 typedef AutoLocker<Volume, AutoLockerWriteLocking<Volume> > VolumeWriteLocker;
247 
248 
249 #endif	// VOLUME_H
250