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