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
FSVolume()52 fs_volume* FSVolume() const { return fFSVolume; }
ID()53 dev_t ID() const { return fFSVolume->id; }
RootDirectory()54 Directory* RootDirectory() const { return fRootDirectory; }
55
MountType()56 ::MountType MountType() const { return fMountType; }
57
SetPackageFSRoot(::PackageFSRoot * root)58 void SetPackageFSRoot(::PackageFSRoot* root)
59 { fPackageFSRoot = root; }
PackageFSRoot()60 ::PackageFSRoot* PackageFSRoot() const
61 { return fPackageFSRoot; }
62
MountPointDeviceID()63 dev_t MountPointDeviceID() const
64 { return fMountPoint.deviceID; }
MountPointNodeID()65 ino_t MountPointNodeID() const
66 { return fMountPoint.nodeID; }
67
68 status_t Mount(const char* parameterString);
69 void Unmount();
70
FindNode(ino_t nodeID)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
FindIndex(const StringKey & name)90 Index* FindIndex(const StringKey& name) const
91 { return fIndices.Lookup(name); }
GetIndexDirIterator()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
ReadLock()210 Volume::ReadLock() const
211 {
212 return rw_lock_read_lock(&fLock) == B_OK;
213 }
214
215
216 void
ReadUnlock()217 Volume::ReadUnlock() const
218 {
219 rw_lock_read_unlock(&fLock);
220 }
221
222
223 bool
WriteLock()224 Volume::WriteLock()
225 {
226 return rw_lock_write_lock(&fLock) == B_OK;
227 }
228
229
230 void
WriteUnlock()231 Volume::WriteUnlock()
232 {
233 rw_lock_write_unlock(&fLock);
234 }
235
236
237 bool
IsWriteLocked()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