126296b0aSIngo Weinhold /* 2*f32d5c5cSAndrew Lindesay * Copyright 2013-2021, Haiku, Inc. All Rights Reserved. 326296b0aSIngo Weinhold * Distributed under the terms of the MIT License. 426296b0aSIngo Weinhold * 526296b0aSIngo Weinhold * Authors: 626296b0aSIngo Weinhold * Ingo Weinhold <ingo_weinhold@gmx.de> 7*f32d5c5cSAndrew Lindesay * Andrew Lindesay <apl@lindesay.co.nz> 826296b0aSIngo Weinhold */ 926296b0aSIngo Weinhold #ifndef VOLUME_H 1026296b0aSIngo Weinhold #define VOLUME_H 1126296b0aSIngo Weinhold 1226296b0aSIngo Weinhold 133d53bd47SIngo Weinhold #include <Handler.h> 148fb3930aSIngo Weinhold #include <Locker.h> 15e6216e37SIngo Weinhold #include <Message.h> 1626296b0aSIngo Weinhold #include <String.h> 1726296b0aSIngo Weinhold 1838c62dfbSIngo Weinhold #include <package/ActivationTransaction.h> 1938c62dfbSIngo Weinhold #include <package/DaemonClient.h> 20b254217aSIngo Weinhold #include <package/packagefs.h> 218fb3930aSIngo Weinhold #include <util/DoublyLinkedList.h> 2226296b0aSIngo Weinhold 2323733521SIngo Weinhold #include "FSUtils.h" 243d53bd47SIngo Weinhold #include "Package.h" 253d53bd47SIngo Weinhold 2626296b0aSIngo Weinhold 2732cae724SIngo Weinhold // Locking Policy 2832cae724SIngo Weinhold // ============== 2932cae724SIngo Weinhold // 3032cae724SIngo Weinhold // A Volume object is accessed by two threads: 3132cae724SIngo Weinhold // 1. The application thread: initially (c'tor and Init()) and when handling a 3232cae724SIngo Weinhold // location info request (HandleGetLocationInfoRequest()). 3332cae724SIngo Weinhold // 2. The corresponding Root object's job thread (any other operation). 3432cae724SIngo Weinhold // 3532cae724SIngo Weinhold // The only thread synchronization needed is for the status information accessed 3632cae724SIngo Weinhold // by HandleGetLocationInfoRequest() and modified by the job thread. The data 372dbf8167SIngo Weinhold // are encapsulated in a VolumeState, which is protected by Volume::fLock. The 382dbf8167SIngo Weinhold // lock must be held by the app thread when accessing the data (it reads only) 392dbf8167SIngo Weinhold // and by the job thread when modifying the data (not needed when reading). 4032cae724SIngo Weinhold 4132cae724SIngo Weinhold 4238c62dfbSIngo Weinhold using BPackageKit::BPrivate::BActivationTransaction; 4338c62dfbSIngo Weinhold using BPackageKit::BPrivate::BDaemonClient; 4438c62dfbSIngo Weinhold 4526296b0aSIngo Weinhold class BDirectory; 4626296b0aSIngo Weinhold 47933e7b32SIngo Weinhold class CommitTransactionHandler; 482dbf8167SIngo Weinhold class PackageFileManager; 4926296b0aSIngo Weinhold class Root; 50273763d0SIngo Weinhold class VolumeState; 5126296b0aSIngo Weinhold 5292b6d585SIngo Weinhold namespace BPackageKit { 5392b6d585SIngo Weinhold class BSolver; 5492b6d585SIngo Weinhold class BSolverRepository; 5592b6d585SIngo Weinhold } 5692b6d585SIngo Weinhold 5738c62dfbSIngo Weinhold using BPackageKit::BPackageInstallationLocation; 5838c62dfbSIngo Weinhold using BPackageKit::BSolver; 5938c62dfbSIngo Weinhold using BPackageKit::BSolverRepository; 6038c62dfbSIngo Weinhold 6126296b0aSIngo Weinhold 623d53bd47SIngo Weinhold class Volume : public BHandler { 6326296b0aSIngo Weinhold public: 649e409614SIngo Weinhold class Listener; 659e409614SIngo Weinhold 669e409614SIngo Weinhold public: 678fb3930aSIngo Weinhold Volume(BLooper* looper); 683d53bd47SIngo Weinhold virtual ~Volume(); 6926296b0aSIngo Weinhold 703d53bd47SIngo Weinhold status_t Init(const node_ref& rootDirectoryRef, 713d53bd47SIngo Weinhold node_ref& _packageRootRef); 729e409614SIngo Weinhold status_t InitPackages(Listener* listener); 738fb3930aSIngo Weinhold 7492b6d585SIngo Weinhold status_t AddPackagesToRepository( 7592b6d585SIngo Weinhold BSolverRepository& repository, 7692b6d585SIngo Weinhold bool activeOnly); 7792b6d585SIngo Weinhold void InitialVerify(Volume* nextVolume, 7892b6d585SIngo Weinhold Volume* nextNextVolume); 79e6216e37SIngo Weinhold void HandleGetLocationInfoRequest(BMessage* message); 8085d2badfSIngo Weinhold void HandleCommitTransactionRequest( 8185d2badfSIngo Weinhold BMessage* message); 8292b6d585SIngo Weinhold 8332cae724SIngo Weinhold void PackageJobPending(); 8432cae724SIngo Weinhold void PackageJobFinished(); 8532cae724SIngo Weinhold bool IsPackageJobPending() const; 8632cae724SIngo Weinhold 878fb3930aSIngo Weinhold void Unmounted(); 883d53bd47SIngo Weinhold 893d53bd47SIngo Weinhold virtual void MessageReceived(BMessage* message); 9026296b0aSIngo Weinhold Path()9126296b0aSIngo Weinhold const BString& Path() const 9226296b0aSIngo Weinhold { return fPath; } MountType()9326296b0aSIngo Weinhold PackageFSMountType MountType() const 9426296b0aSIngo Weinhold { return fMountType; } 9538c62dfbSIngo Weinhold BPackageInstallationLocation Location() const; 963d53bd47SIngo Weinhold RootDirectoryRef()973d53bd47SIngo Weinhold const node_ref& RootDirectoryRef() const 983d53bd47SIngo Weinhold { return fRootDirectoryRef; } DeviceID()9926296b0aSIngo Weinhold dev_t DeviceID() const 1003d53bd47SIngo Weinhold { return fRootDirectoryRef.device; } RootDirectoryID()10126296b0aSIngo Weinhold ino_t RootDirectoryID() const 1023d53bd47SIngo Weinhold { return fRootDirectoryRef.node; } 1033d53bd47SIngo Weinhold 104c8dd5bbdSIngo Weinhold const node_ref& PackagesDirectoryRef() const; PackagesDeviceID()1053d53bd47SIngo Weinhold dev_t PackagesDeviceID() const 106c8dd5bbdSIngo Weinhold { return PackagesDirectoryRef().device; } PackagesDirectoryID()1073d53bd47SIngo Weinhold ino_t PackagesDirectoryID() const 108c8dd5bbdSIngo Weinhold { return PackagesDirectoryRef().node; } 10926296b0aSIngo Weinhold GetRoot()11026296b0aSIngo Weinhold Root* GetRoot() const 11126296b0aSIngo Weinhold { return fRoot; } SetRoot(Root * root)11226296b0aSIngo Weinhold void SetRoot(Root* root) 11326296b0aSIngo Weinhold { fRoot = root; } 11426296b0aSIngo Weinhold ChangeCount()115870e93acSIngo Weinhold int64 ChangeCount() const 116870e93acSIngo Weinhold { return fChangeCount; } 117870e93acSIngo Weinhold 11832cae724SIngo Weinhold PackageFileNameHashTable::Iterator PackagesByFileNameIterator() 11932cae724SIngo Weinhold const; 12038c62dfbSIngo Weinhold 1213d53bd47SIngo Weinhold int OpenRootDirectory() const; 1223d53bd47SIngo Weinhold 1238fb3930aSIngo Weinhold void ProcessPendingNodeMonitorEvents(); 1248fb3930aSIngo Weinhold 125a6c7f5e3SIngo Weinhold bool HasPendingPackageActivationChanges() const; 126a6c7f5e3SIngo Weinhold void ProcessPendingPackageActivationChanges(); 12738c62dfbSIngo Weinhold void ClearPackageActivationChanges(); PackagesToBeActivated()12838c62dfbSIngo Weinhold const PackageSet& PackagesToBeActivated() const 12938c62dfbSIngo Weinhold { return fPackagesToBeActivated; } PackagesToBeDeactivated()13038c62dfbSIngo Weinhold const PackageSet& PackagesToBeDeactivated() const 13138c62dfbSIngo Weinhold { return fPackagesToBeDeactivated; } 13238c62dfbSIngo Weinhold 13338c62dfbSIngo Weinhold status_t CreateTransaction( 13438c62dfbSIngo Weinhold BPackageInstallationLocation location, 13538c62dfbSIngo Weinhold BActivationTransaction& _transaction, 13638c62dfbSIngo Weinhold BDirectory& _transactionDirectory); 13738c62dfbSIngo Weinhold void CommitTransaction( 13838c62dfbSIngo Weinhold const BActivationTransaction& transaction, 13938c62dfbSIngo Weinhold const PackageSet& packagesAlreadyAdded, 14038c62dfbSIngo Weinhold const PackageSet& packagesAlreadyRemoved, 1410de3219eSIngo Weinhold BCommitTransactionResult& _result); 142a6c7f5e3SIngo Weinhold 1438fb3930aSIngo Weinhold private: 1448fb3930aSIngo Weinhold struct NodeMonitorEvent; 145c8dd5bbdSIngo Weinhold struct PackagesDirectory; 1468fb3930aSIngo Weinhold 14723733521SIngo Weinhold typedef FSUtils::RelativePath RelativePath; 14885d2badfSIngo Weinhold typedef DoublyLinkedList<NodeMonitorEvent> NodeMonitorEventList; 149a6c7f5e3SIngo Weinhold 1503d53bd47SIngo Weinhold private: 1513d53bd47SIngo Weinhold void _HandleEntryCreatedOrRemoved( 1523d53bd47SIngo Weinhold const BMessage* message, bool created); 1533d53bd47SIngo Weinhold void _HandleEntryMoved(const BMessage* message); 1548fb3930aSIngo Weinhold void _QueueNodeMonitorEvent(const BString& name, 1558fb3930aSIngo Weinhold bool wasCreated); 1563d53bd47SIngo Weinhold 1573d53bd47SIngo Weinhold void _PackagesEntryCreated(const char* name); 1583d53bd47SIngo Weinhold void _PackagesEntryRemoved(const char* name); 1593d53bd47SIngo Weinhold 1603d53bd47SIngo Weinhold status_t _ReadPackagesDirectory(); 1612dbf8167SIngo Weinhold status_t _InitLatestState(); 1622dbf8167SIngo Weinhold status_t _InitLatestStateFromActivatedPackages(); 1633d53bd47SIngo Weinhold status_t _GetActivePackages(int fd); 164a22fa0c9SAlexander G. M. Smith void _RunQueuedScripts(); // TODO: Never called, fix? 1652dbf8167SIngo Weinhold bool _CheckActivePackagesMatchLatestState( 1662dbf8167SIngo Weinhold PackageFSGetPackageInfosRequest* request); 1672dbf8167SIngo Weinhold void _SetLatestState(VolumeState* state, 1682dbf8167SIngo Weinhold bool isActive); 1692dbf8167SIngo Weinhold void _DumpState(VolumeState* state); 1703d53bd47SIngo Weinhold 17192b6d585SIngo Weinhold status_t _AddRepository(BSolver* solver, 17292b6d585SIngo Weinhold BSolverRepository& repository, 17392b6d585SIngo Weinhold bool activeOnly, bool installed); 17492b6d585SIngo Weinhold 17585d2badfSIngo Weinhold status_t _OpenPackagesSubDirectory( 17685d2badfSIngo Weinhold const RelativePath& path, bool create, 17785d2badfSIngo Weinhold BDirectory& _directory); 17885d2badfSIngo Weinhold 1790de3219eSIngo Weinhold void _CommitTransaction(BMessage* message, 1800de3219eSIngo Weinhold const BActivationTransaction* transaction, 1810de3219eSIngo Weinhold const PackageSet& packagesAlreadyAdded, 1820de3219eSIngo Weinhold const PackageSet& packagesAlreadyRemoved, 1830de3219eSIngo Weinhold BCommitTransactionResult& _result); 1840de3219eSIngo Weinhold 185*f32d5c5cSAndrew Lindesay static void _CollectPackageNamesAdded( 186*f32d5c5cSAndrew Lindesay const VolumeState* oldState, 187*f32d5c5cSAndrew Lindesay const VolumeState* newState, 188*f32d5c5cSAndrew Lindesay BStringList& addedPackageNames); 189*f32d5c5cSAndrew Lindesay 19026296b0aSIngo Weinhold private: 19126296b0aSIngo Weinhold BString fPath; 19226296b0aSIngo Weinhold PackageFSMountType fMountType; 1933d53bd47SIngo Weinhold node_ref fRootDirectoryRef; 194c8dd5bbdSIngo Weinhold PackagesDirectory* fPackagesDirectories; 195c8dd5bbdSIngo Weinhold uint32 fPackagesDirectoryCount; 19626296b0aSIngo Weinhold Root* fRoot; 1979e409614SIngo Weinhold Listener* fListener; 1982dbf8167SIngo Weinhold PackageFileManager* fPackageFileManager; 1992dbf8167SIngo Weinhold VolumeState* fLatestState; 2002dbf8167SIngo Weinhold VolumeState* fActiveState; 201870e93acSIngo Weinhold int64 fChangeCount; 2022dbf8167SIngo Weinhold BLocker fLock; 2038fb3930aSIngo Weinhold BLocker fPendingNodeMonitorEventsLock; 2048fb3930aSIngo Weinhold NodeMonitorEventList fPendingNodeMonitorEvents; 20538c62dfbSIngo Weinhold bigtime_t fNodeMonitorEventHandleTime; 206a6c7f5e3SIngo Weinhold PackageSet fPackagesToBeActivated; 207a6c7f5e3SIngo Weinhold PackageSet fPackagesToBeDeactivated; 208e6216e37SIngo Weinhold BMessage fLocationInfoReply; 20932cae724SIngo Weinhold // only accessed in the application thread 2107a35d803SIngo Weinhold int32 fPendingPackageJobCount; 21126296b0aSIngo Weinhold }; 21226296b0aSIngo Weinhold 21326296b0aSIngo Weinhold 2149e409614SIngo Weinhold class Volume::Listener { 2159e409614SIngo Weinhold public: 2169e409614SIngo Weinhold virtual ~Listener(); 2179e409614SIngo Weinhold 2189e409614SIngo Weinhold virtual void VolumeNodeMonitorEventOccurred(Volume* volume) 2199e409614SIngo Weinhold = 0; 2209e409614SIngo Weinhold }; 2219e409614SIngo Weinhold 2229e409614SIngo Weinhold 22326296b0aSIngo Weinhold #endif // VOLUME_H 224