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