1 /* 2 * Copyright 2013-2014, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold <ingo_weinhold@gmx.de> 7 */ 8 #ifndef VOLUME_H 9 #define VOLUME_H 10 11 12 #include <Handler.h> 13 #include <Locker.h> 14 #include <Message.h> 15 #include <String.h> 16 17 #include <package/ActivationTransaction.h> 18 #include <package/DaemonClient.h> 19 #include <package/packagefs.h> 20 #include <util/DoublyLinkedList.h> 21 22 #include "FSUtils.h" 23 #include "Package.h" 24 25 26 // Locking Policy 27 // ============== 28 // 29 // A Volume object is accessed by two threads: 30 // 1. The application thread: initially (c'tor and Init()) and when handling a 31 // location info request (HandleGetLocationInfoRequest()). 32 // 2. The corresponding Root object's job thread (any other operation). 33 // 34 // The only thread synchronization needed is for the status information accessed 35 // by HandleGetLocationInfoRequest() and modified by the job thread. The data 36 // are encapsulated in a Volume::State object which contains a lock. The lock 37 // must be held by the app thread when accessing the data (it reads only) and 38 // by the job thread when modifying the data (not needed when reading). 39 40 41 using BPackageKit::BPrivate::BActivationTransaction; 42 using BPackageKit::BPrivate::BDaemonClient; 43 44 class BDirectory; 45 46 class Root; 47 48 namespace BPackageKit { 49 class BSolver; 50 class BSolverRepository; 51 } 52 53 using BPackageKit::BPackageInstallationLocation; 54 using BPackageKit::BSolver; 55 using BPackageKit::BSolverRepository; 56 57 58 class Volume : public BHandler { 59 public: 60 class Listener; 61 62 public: 63 Volume(BLooper* looper); 64 virtual ~Volume(); 65 66 status_t Init(const node_ref& rootDirectoryRef, 67 node_ref& _packageRootRef); 68 status_t InitPackages(Listener* listener); 69 70 status_t AddPackagesToRepository( 71 BSolverRepository& repository, 72 bool activeOnly); 73 void InitialVerify(Volume* nextVolume, 74 Volume* nextNextVolume); 75 void HandleGetLocationInfoRequest(BMessage* message); 76 void HandleCommitTransactionRequest( 77 BMessage* message); 78 79 void PackageJobPending(); 80 void PackageJobFinished(); 81 bool IsPackageJobPending() const; 82 83 void Unmounted(); 84 85 virtual void MessageReceived(BMessage* message); 86 87 const BString& Path() const 88 { return fPath; } 89 PackageFSMountType MountType() const 90 { return fMountType; } 91 BPackageInstallationLocation Location() const; 92 93 const node_ref& RootDirectoryRef() const 94 { return fRootDirectoryRef; } 95 dev_t DeviceID() const 96 { return fRootDirectoryRef.device; } 97 ino_t RootDirectoryID() const 98 { return fRootDirectoryRef.node; } 99 100 const node_ref& PackagesDirectoryRef() const 101 { return fPackagesDirectoryRef; } 102 dev_t PackagesDeviceID() const 103 { return fPackagesDirectoryRef.device; } 104 ino_t PackagesDirectoryID() const 105 { return fPackagesDirectoryRef.node; } 106 107 Root* GetRoot() const 108 { return fRoot; } 109 void SetRoot(Root* root) 110 { fRoot = root; } 111 112 PackageFileNameHashTable::Iterator PackagesByFileNameIterator() 113 const; 114 115 int OpenRootDirectory() const; 116 117 void ProcessPendingNodeMonitorEvents(); 118 119 bool HasPendingPackageActivationChanges() const; 120 void ProcessPendingPackageActivationChanges(); 121 void ClearPackageActivationChanges(); 122 const PackageSet& PackagesToBeActivated() const 123 { return fPackagesToBeActivated; } 124 const PackageSet& PackagesToBeDeactivated() const 125 { return fPackagesToBeDeactivated; } 126 127 status_t CreateTransaction( 128 BPackageInstallationLocation location, 129 BActivationTransaction& _transaction, 130 BDirectory& _transactionDirectory); 131 void CommitTransaction( 132 const BActivationTransaction& transaction, 133 const PackageSet& packagesAlreadyAdded, 134 const PackageSet& packagesAlreadyRemoved, 135 BDaemonClient::BCommitTransactionResult& 136 _result); 137 138 private: 139 struct NodeMonitorEvent; 140 struct State; 141 struct CommitTransactionHandler; 142 143 friend struct CommitTransactionHandler; 144 145 typedef FSUtils::RelativePath RelativePath; 146 typedef DoublyLinkedList<NodeMonitorEvent> NodeMonitorEventList; 147 148 private: 149 void _HandleEntryCreatedOrRemoved( 150 const BMessage* message, bool created); 151 void _HandleEntryMoved(const BMessage* message); 152 void _QueueNodeMonitorEvent(const BString& name, 153 bool wasCreated); 154 155 void _PackagesEntryCreated(const char* name); 156 void _PackagesEntryRemoved(const char* name); 157 158 void _FillInActivationChangeItem( 159 PackageFSActivationChangeItem* item, 160 PackageFSActivationChangeType type, 161 Package* package, char*& nameBuffer); 162 163 void _AddPackage(Package* package); 164 void _RemovePackage(Package* package); 165 166 status_t _ReadPackagesDirectory(); 167 status_t _GetActivePackages(int fd); 168 169 status_t _AddRepository(BSolver* solver, 170 BSolverRepository& repository, 171 bool activeOnly, bool installed); 172 173 status_t _OpenPackagesFile( 174 const RelativePath& subDirectoryPath, 175 const char* fileName, uint32 openMode, 176 BFile& _file, BEntry* _entry = NULL); 177 status_t _OpenPackagesSubDirectory( 178 const RelativePath& path, bool create, 179 BDirectory& _directory); 180 181 status_t _OpenSettingsRootDirectory( 182 BDirectory& _directory); 183 184 status_t _CreateActivationFileContent( 185 const PackageSet& toActivate, 186 const PackageSet& toDeactivate, 187 BString& _content); 188 status_t _WriteActivationFile( 189 const RelativePath& directoryPath, 190 const char* fileName, 191 const PackageSet& toActivate, 192 const PackageSet& toDeactivate, 193 BEntry& _entry); 194 195 status_t _WriteTextFile( 196 const RelativePath& directoryPath, 197 const char* fileName, 198 const BString& content, BEntry& _entry); 199 200 void _ChangePackageActivation( 201 const PackageSet& packagesToActivate, 202 const PackageSet& packagesToDeactivate); 203 // throws Exception 204 205 status_t _ExtractPackageContent(Package* package, 206 const char* contentPath, 207 BDirectory& targetDirectory, 208 BDirectory& _extractedFilesDirectory); 209 210 private: 211 BString fPath; 212 PackageFSMountType fMountType; 213 node_ref fRootDirectoryRef; 214 node_ref fPackagesDirectoryRef; 215 Root* fRoot; 216 Listener* fListener; 217 State* fState; 218 BLocker fPendingNodeMonitorEventsLock; 219 NodeMonitorEventList fPendingNodeMonitorEvents; 220 bigtime_t fNodeMonitorEventHandleTime; 221 PackageSet fPackagesToBeActivated; 222 PackageSet fPackagesToBeDeactivated; 223 BMessage fLocationInfoReply; 224 // only accessed in the application thread 225 }; 226 227 228 class Volume::Listener { 229 public: 230 virtual ~Listener(); 231 232 virtual void VolumeNodeMonitorEventOccurred(Volume* volume) 233 = 0; 234 }; 235 236 237 #endif // VOLUME_H 238