1 /* 2 * Copyright 2013-2021, 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 * Andrew Lindesay <apl@lindesay.co.nz> 8 */ 9 #ifndef VOLUME_H 10 #define VOLUME_H 11 12 13 #include <Handler.h> 14 #include <Locker.h> 15 #include <Message.h> 16 #include <String.h> 17 18 #include <package/ActivationTransaction.h> 19 #include <package/DaemonClient.h> 20 #include <package/packagefs.h> 21 #include <util/DoublyLinkedList.h> 22 23 #include "FSUtils.h" 24 #include "Package.h" 25 26 27 // Locking Policy 28 // ============== 29 // 30 // A Volume object is accessed by two threads: 31 // 1. The application thread: initially (c'tor and Init()) and when handling a 32 // location info request (HandleGetLocationInfoRequest()). 33 // 2. The corresponding Root object's job thread (any other operation). 34 // 35 // The only thread synchronization needed is for the status information accessed 36 // by HandleGetLocationInfoRequest() and modified by the job thread. The data 37 // are encapsulated in a VolumeState, which is protected by Volume::fLock. The 38 // lock must be held by the app thread when accessing the data (it reads only) 39 // and by the job thread when modifying the data (not needed when reading). 40 41 42 using BPackageKit::BPrivate::BActivationTransaction; 43 using BPackageKit::BPrivate::BDaemonClient; 44 45 class BDirectory; 46 47 class CommitTransactionHandler; 48 class PackageFileManager; 49 class Root; 50 class VolumeState; 51 52 namespace BPackageKit { 53 class BSolver; 54 class BSolverRepository; 55 } 56 57 using BPackageKit::BPackageInstallationLocation; 58 using BPackageKit::BSolver; 59 using BPackageKit::BSolverRepository; 60 61 62 class Volume : public BHandler { 63 public: 64 class Listener; 65 66 public: 67 Volume(BLooper* looper); 68 virtual ~Volume(); 69 70 status_t Init(const node_ref& rootDirectoryRef, 71 node_ref& _packageRootRef); 72 status_t InitPackages(Listener* listener); 73 74 status_t AddPackagesToRepository( 75 BSolverRepository& repository, 76 bool activeOnly); 77 void InitialVerify(Volume* nextVolume, 78 Volume* nextNextVolume); 79 void HandleGetLocationInfoRequest(BMessage* message); 80 void HandleCommitTransactionRequest( 81 BMessage* message); 82 83 void PackageJobPending(); 84 void PackageJobFinished(); 85 bool IsPackageJobPending() const; 86 87 void Unmounted(); 88 89 virtual void MessageReceived(BMessage* message); 90 Path()91 const BString& Path() const 92 { return fPath; } MountType()93 PackageFSMountType MountType() const 94 { return fMountType; } 95 BPackageInstallationLocation Location() const; 96 RootDirectoryRef()97 const node_ref& RootDirectoryRef() const 98 { return fRootDirectoryRef; } DeviceID()99 dev_t DeviceID() const 100 { return fRootDirectoryRef.device; } RootDirectoryID()101 ino_t RootDirectoryID() const 102 { return fRootDirectoryRef.node; } 103 104 const node_ref& PackagesDirectoryRef() const; PackagesDeviceID()105 dev_t PackagesDeviceID() const 106 { return PackagesDirectoryRef().device; } PackagesDirectoryID()107 ino_t PackagesDirectoryID() const 108 { return PackagesDirectoryRef().node; } 109 GetRoot()110 Root* GetRoot() const 111 { return fRoot; } SetRoot(Root * root)112 void SetRoot(Root* root) 113 { fRoot = root; } 114 ChangeCount()115 int64 ChangeCount() const 116 { return fChangeCount; } 117 118 PackageFileNameHashTable::Iterator PackagesByFileNameIterator() 119 const; 120 121 int OpenRootDirectory() const; 122 123 void ProcessPendingNodeMonitorEvents(); 124 125 bool HasPendingPackageActivationChanges() const; 126 void ProcessPendingPackageActivationChanges(); 127 void ClearPackageActivationChanges(); PackagesToBeActivated()128 const PackageSet& PackagesToBeActivated() const 129 { return fPackagesToBeActivated; } PackagesToBeDeactivated()130 const PackageSet& PackagesToBeDeactivated() const 131 { return fPackagesToBeDeactivated; } 132 133 status_t CreateTransaction( 134 BPackageInstallationLocation location, 135 BActivationTransaction& _transaction, 136 BDirectory& _transactionDirectory); 137 void CommitTransaction( 138 const BActivationTransaction& transaction, 139 const PackageSet& packagesAlreadyAdded, 140 const PackageSet& packagesAlreadyRemoved, 141 BCommitTransactionResult& _result); 142 143 private: 144 struct NodeMonitorEvent; 145 struct PackagesDirectory; 146 147 typedef FSUtils::RelativePath RelativePath; 148 typedef DoublyLinkedList<NodeMonitorEvent> NodeMonitorEventList; 149 150 private: 151 void _HandleEntryCreatedOrRemoved( 152 const BMessage* message, bool created); 153 void _HandleEntryMoved(const BMessage* message); 154 void _QueueNodeMonitorEvent(const BString& name, 155 bool wasCreated); 156 157 void _PackagesEntryCreated(const char* name); 158 void _PackagesEntryRemoved(const char* name); 159 160 status_t _ReadPackagesDirectory(); 161 status_t _InitLatestState(); 162 status_t _InitLatestStateFromActivatedPackages(); 163 status_t _GetActivePackages(int fd); 164 void _RunQueuedScripts(); // TODO: Never called, fix? 165 bool _CheckActivePackagesMatchLatestState( 166 PackageFSGetPackageInfosRequest* request); 167 void _SetLatestState(VolumeState* state, 168 bool isActive); 169 void _DumpState(VolumeState* state); 170 171 status_t _AddRepository(BSolver* solver, 172 BSolverRepository& repository, 173 bool activeOnly, bool installed); 174 175 status_t _OpenPackagesSubDirectory( 176 const RelativePath& path, bool create, 177 BDirectory& _directory); 178 179 void _CommitTransaction(BMessage* message, 180 const BActivationTransaction* transaction, 181 const PackageSet& packagesAlreadyAdded, 182 const PackageSet& packagesAlreadyRemoved, 183 BCommitTransactionResult& _result); 184 185 static void _CollectPackageNamesAdded( 186 const VolumeState* oldState, 187 const VolumeState* newState, 188 BStringList& addedPackageNames); 189 190 private: 191 BString fPath; 192 PackageFSMountType fMountType; 193 node_ref fRootDirectoryRef; 194 PackagesDirectory* fPackagesDirectories; 195 uint32 fPackagesDirectoryCount; 196 Root* fRoot; 197 Listener* fListener; 198 PackageFileManager* fPackageFileManager; 199 VolumeState* fLatestState; 200 VolumeState* fActiveState; 201 int64 fChangeCount; 202 BLocker fLock; 203 BLocker fPendingNodeMonitorEventsLock; 204 NodeMonitorEventList fPendingNodeMonitorEvents; 205 bigtime_t fNodeMonitorEventHandleTime; 206 PackageSet fPackagesToBeActivated; 207 PackageSet fPackagesToBeDeactivated; 208 BMessage fLocationInfoReply; 209 // only accessed in the application thread 210 int32 fPendingPackageJobCount; 211 }; 212 213 214 class Volume::Listener { 215 public: 216 virtual ~Listener(); 217 218 virtual void VolumeNodeMonitorEventOccurred(Volume* volume) 219 = 0; 220 }; 221 222 223 #endif // VOLUME_H 224