1/* 2 * Copyright 2009-2011, 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 "Index.h" 18#include "Node.h" 19#include "NodeListener.h" 20#include "PackageDomain.h" 21#include "PackageLinksListener.h" 22#include "Query.h" 23 24 25class Directory; 26class PackageFSRoot; 27class UnpackingNode; 28 29typedef IndexHashTable::Iterator IndexDirIterator; 30 31 32enum MountType { 33 MOUNT_TYPE_SYSTEM, 34 MOUNT_TYPE_COMMON, 35 MOUNT_TYPE_HOME, 36 MOUNT_TYPE_CUSTOM 37}; 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 // node listeners -- volume must be write-locked 74 void AddNodeListener(NodeListener* listener, 75 Node* node); 76 void RemoveNodeListener(NodeListener* listener); 77 78 // query support -- volume must be write-locked 79 void AddQuery(Query* query); 80 void RemoveQuery(Query* query); 81 void UpdateLiveQueries(Node* node, 82 const char* attribute, int32 type, 83 const void* oldKey, size_t oldLength, 84 const void* newKey, size_t newLength); 85 86 Index* FindIndex(const char* name) const 87 { return fIndices.Lookup(name); } 88 IndexDirIterator GetIndexDirIterator() const 89 { return fIndices.GetIterator(); } 90 91 // VFS wrappers 92 status_t GetVNode(ino_t nodeID, Node*& _node); 93 status_t PutVNode(ino_t nodeID); 94 status_t RemoveVNode(ino_t nodeID); 95 status_t PublishVNode(Node* node); 96 97 status_t AddPackageDomain(const char* path); 98 99private: 100 // PackageLinksListener 101 virtual void PackageLinkNodeAdded(Node* node); 102 virtual void PackageLinkNodeRemoved(Node* node); 103 virtual void PackageLinkNodeChanged(Node* node, 104 uint32 statFields, 105 const OldNodeAttributes& oldAttributes); 106 107private: 108 struct Job; 109 struct AddPackageDomainJob; 110 struct DomainDirectoryEventJob; 111 struct PackageLoaderErrorOutput; 112 struct PackageLoaderContentHandler; 113 struct DomainDirectoryListener; 114 struct ShineThroughDirectory; 115 116 friend struct AddPackageDomainJob; 117 friend struct DomainDirectoryEventJob; 118 friend struct DomainDirectoryListener; 119 120 typedef DoublyLinkedList<Job> JobList; 121 typedef DoublyLinkedList<PackageDomain> PackageDomainList; 122 123private: 124 static status_t _PackageLoaderEntry(void* data); 125 status_t _PackageLoader(); 126 127 void _TerminatePackageLoader(); 128 129 void _PushJob(Job* job); 130 131 status_t _AddInitialPackageDomain(const char* path); 132 status_t _AddPackageDomain(PackageDomain* domain, 133 bool notify); 134 void _RemovePackageDomain(PackageDomain* domain); 135 status_t _LoadPackage(Package* package); 136 137 status_t _AddPackageContent(Package* package, 138 bool notify); 139 void _RemovePackageContent(Package* package, 140 PackageNode* endNode, bool notify); 141 142 status_t _AddPackageContentRootNode(Package* package, 143 PackageNode* node, bool notify); 144 void _RemovePackageContentRootNode(Package* package, 145 PackageNode* packageNode, 146 PackageNode* endPackageNode, bool notify); 147 148 status_t _AddPackageNode(Directory* directory, 149 PackageNode* packageNode, bool notify, 150 Node*& _node); 151 void _RemovePackageNode(Directory* directory, 152 PackageNode* packageNode, Node* node, 153 bool notify); 154 155 status_t _CreateUnpackingNode(mode_t mode, 156 Directory* parent, const char* name, 157 UnpackingNode*& _node); 158 // does *not* return a reference 159 void _RemoveNode(Node* node); 160 void _RemoveNodeAndVNode(Node* node); 161 // caller must hold a reference 162 163 void _DomainListenerEventOccurred( 164 PackageDomain* domain, 165 const KMessage* event); 166 void _DomainEntryCreated(PackageDomain* domain, 167 dev_t deviceID, ino_t directoryID, 168 ino_t nodeID, const char* name, 169 bool addContent, bool notify); 170 void _DomainEntryRemoved(PackageDomain* domain, 171 dev_t deviceID, ino_t directoryID, 172 ino_t nodeID, const char* name, 173 bool notify); 174 void _DomainEntryMoved(PackageDomain* domain, 175 dev_t deviceID, ino_t fromDirectoryID, 176 ino_t toDirectoryID, dev_t nodeDeviceID, 177 ino_t nodeID, const char* fromName, 178 const char* name, bool notify); 179 180 status_t _InitMountType(const char* mountType); 181 status_t _CreateShineThroughDirectory(Directory* parent, 182 const char* name, Directory*& _directory); 183 status_t _CreateShineThroughDirectories( 184 const char* shineThroughSetting); 185 status_t _PublishShineThroughDirectories(); 186 187 status_t _AddPackageLinksDirectory(); 188 void _RemovePackageLinksDirectory(); 189 void _AddPackageLinksNode(Node* node); 190 void _RemovePackageLinksNode(Node* node); 191 192 inline Volume* _SystemVolumeIfNotSelf() const; 193 194 void _NotifyNodeAdded(Node* node); 195 void _NotifyNodeRemoved(Node* node); 196 void _NotifyNodeChanged(Node* node, 197 uint32 statFields, 198 const OldNodeAttributes& oldAttributes); 199 200private: 201 mutable rw_lock fLock; 202 fs_volume* fFSVolume; 203 Directory* fRootDirectory; 204 ::PackageFSRoot* fPackageFSRoot; 205 ::MountType fMountType; 206 thread_id fPackageLoader; 207 PackageDomainList fPackageDomains; 208 209 struct { 210 dev_t deviceID; 211 ino_t nodeID; 212 } fMountPoint; 213 214 NodeIDHashTable fNodes; 215 NodeListenerHashTable fNodeListeners; 216 QueryList fQueries; 217 IndexHashTable fIndices; 218 219 JobList fJobQueue; 220 mutex fJobQueueLock; 221 ConditionVariable fJobQueueCondition; 222 223 ino_t fNextNodeID; 224 225 volatile bool fTerminating; 226}; 227 228 229bool 230Volume::ReadLock() const 231{ 232 return rw_lock_read_lock(&fLock) == B_OK; 233} 234 235 236void 237Volume::ReadUnlock() const 238{ 239 rw_lock_read_unlock(&fLock); 240} 241 242 243bool 244Volume::WriteLock() 245{ 246 return rw_lock_write_lock(&fLock) == B_OK; 247} 248 249 250void 251Volume::WriteUnlock() 252{ 253 rw_lock_write_unlock(&fLock); 254} 255 256 257typedef AutoLocker<const Volume, AutoLockerReadLocking<const Volume> > 258 VolumeReadLocker; 259typedef AutoLocker<Volume, AutoLockerWriteLocking<Volume> > VolumeWriteLocker; 260 261 262#endif // VOLUME_H 263