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 VolumeState, which is protected by Volume::fLock. The 37 // lock must be held by the app thread when accessing the data (it reads only) 38 // and 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 CommitTransactionHandler; 47 class PackageFileManager; 48 class Root; 49 class VolumeState; 50 51 namespace BPackageKit { 52 class BSolver; 53 class BSolverRepository; 54 } 55 56 using BPackageKit::BPackageInstallationLocation; 57 using BPackageKit::BSolver; 58 using BPackageKit::BSolverRepository; 59 60 61 class Volume : public BHandler { 62 public: 63 class Listener; 64 65 public: 66 Volume(BLooper* looper); 67 virtual ~Volume(); 68 69 status_t Init(const node_ref& rootDirectoryRef, 70 node_ref& _packageRootRef); 71 status_t InitPackages(Listener* listener); 72 73 status_t AddPackagesToRepository( 74 BSolverRepository& repository, 75 bool activeOnly); 76 void InitialVerify(Volume* nextVolume, 77 Volume* nextNextVolume); 78 void HandleGetLocationInfoRequest(BMessage* message); 79 void HandleCommitTransactionRequest( 80 BMessage* message); 81 82 void PackageJobPending(); 83 void PackageJobFinished(); 84 bool IsPackageJobPending() const; 85 86 void Unmounted(); 87 88 virtual void MessageReceived(BMessage* message); 89 90 const BString& Path() const 91 { return fPath; } 92 PackageFSMountType MountType() const 93 { return fMountType; } 94 BPackageInstallationLocation Location() const; 95 96 const node_ref& RootDirectoryRef() const 97 { return fRootDirectoryRef; } 98 dev_t DeviceID() const 99 { return fRootDirectoryRef.device; } 100 ino_t RootDirectoryID() const 101 { return fRootDirectoryRef.node; } 102 103 const node_ref& PackagesDirectoryRef() const; 104 dev_t PackagesDeviceID() const 105 { return PackagesDirectoryRef().device; } 106 ino_t PackagesDirectoryID() const 107 { return PackagesDirectoryRef().node; } 108 109 Root* GetRoot() const 110 { return fRoot; } 111 void SetRoot(Root* root) 112 { fRoot = root; } 113 114 int64 ChangeCount() const 115 { return fChangeCount; } 116 117 PackageFileNameHashTable::Iterator PackagesByFileNameIterator() 118 const; 119 120 int OpenRootDirectory() const; 121 122 void ProcessPendingNodeMonitorEvents(); 123 124 bool HasPendingPackageActivationChanges() const; 125 void ProcessPendingPackageActivationChanges(); 126 void ClearPackageActivationChanges(); 127 const PackageSet& PackagesToBeActivated() const 128 { return fPackagesToBeActivated; } 129 const PackageSet& PackagesToBeDeactivated() const 130 { return fPackagesToBeDeactivated; } 131 132 status_t CreateTransaction( 133 BPackageInstallationLocation location, 134 BActivationTransaction& _transaction, 135 BDirectory& _transactionDirectory); 136 void CommitTransaction( 137 const BActivationTransaction& transaction, 138 const PackageSet& packagesAlreadyAdded, 139 const PackageSet& packagesAlreadyRemoved, 140 BCommitTransactionResult& _result); 141 142 private: 143 struct NodeMonitorEvent; 144 struct PackagesDirectory; 145 146 typedef FSUtils::RelativePath RelativePath; 147 typedef DoublyLinkedList<NodeMonitorEvent> NodeMonitorEventList; 148 149 private: 150 void _HandleEntryCreatedOrRemoved( 151 const BMessage* message, bool created); 152 void _HandleEntryMoved(const BMessage* message); 153 void _QueueNodeMonitorEvent(const BString& name, 154 bool wasCreated); 155 156 void _PackagesEntryCreated(const char* name); 157 void _PackagesEntryRemoved(const char* name); 158 159 status_t _ReadPackagesDirectory(); 160 status_t _InitLatestState(); 161 status_t _InitLatestStateFromActivatedPackages(); 162 status_t _GetActivePackages(int fd); 163 void _RunQueuedScripts(); 164 bool _CheckActivePackagesMatchLatestState( 165 PackageFSGetPackageInfosRequest* request); 166 void _SetLatestState(VolumeState* state, 167 bool isActive); 168 void _DumpState(VolumeState* state); 169 170 status_t _AddRepository(BSolver* solver, 171 BSolverRepository& repository, 172 bool activeOnly, bool installed); 173 174 status_t _OpenPackagesSubDirectory( 175 const RelativePath& path, bool create, 176 BDirectory& _directory); 177 178 void _CommitTransaction(BMessage* message, 179 const BActivationTransaction* transaction, 180 const PackageSet& packagesAlreadyAdded, 181 const PackageSet& packagesAlreadyRemoved, 182 BCommitTransactionResult& _result); 183 184 private: 185 BString fPath; 186 PackageFSMountType fMountType; 187 node_ref fRootDirectoryRef; 188 PackagesDirectory* fPackagesDirectories; 189 uint32 fPackagesDirectoryCount; 190 Root* fRoot; 191 Listener* fListener; 192 PackageFileManager* fPackageFileManager; 193 VolumeState* fLatestState; 194 VolumeState* fActiveState; 195 int64 fChangeCount; 196 BLocker fLock; 197 BLocker fPendingNodeMonitorEventsLock; 198 NodeMonitorEventList fPendingNodeMonitorEvents; 199 bigtime_t fNodeMonitorEventHandleTime; 200 PackageSet fPackagesToBeActivated; 201 PackageSet fPackagesToBeDeactivated; 202 BMessage fLocationInfoReply; 203 // only accessed in the application thread 204 int32 fPendingPackageJobCount; 205 }; 206 207 208 class Volume::Listener { 209 public: 210 virtual ~Listener(); 211 212 virtual void VolumeNodeMonitorEventOccurred(Volume* volume) 213 = 0; 214 }; 215 216 217 #endif // VOLUME_H 218