/* * Copyright 2013-2021, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Ingo Weinhold * Andrew Lindesay */ #ifndef VOLUME_H #define VOLUME_H #include #include #include #include #include #include #include #include #include "FSUtils.h" #include "Package.h" // Locking Policy // ============== // // A Volume object is accessed by two threads: // 1. The application thread: initially (c'tor and Init()) and when handling a // location info request (HandleGetLocationInfoRequest()). // 2. The corresponding Root object's job thread (any other operation). // // The only thread synchronization needed is for the status information accessed // by HandleGetLocationInfoRequest() and modified by the job thread. The data // are encapsulated in a VolumeState, which is protected by Volume::fLock. The // lock must be held by the app thread when accessing the data (it reads only) // and by the job thread when modifying the data (not needed when reading). using BPackageKit::BPrivate::BActivationTransaction; using BPackageKit::BPrivate::BDaemonClient; class BDirectory; class CommitTransactionHandler; class PackageFileManager; class Root; class VolumeState; namespace BPackageKit { class BSolver; class BSolverRepository; } using BPackageKit::BPackageInstallationLocation; using BPackageKit::BSolver; using BPackageKit::BSolverRepository; class Volume : public BHandler { public: class Listener; public: Volume(BLooper* looper); virtual ~Volume(); status_t Init(const node_ref& rootDirectoryRef, node_ref& _packageRootRef); status_t InitPackages(Listener* listener); status_t AddPackagesToRepository( BSolverRepository& repository, bool activeOnly); void InitialVerify(Volume* nextVolume, Volume* nextNextVolume); void HandleGetLocationInfoRequest(BMessage* message); void HandleCommitTransactionRequest( BMessage* message); void PackageJobPending(); void PackageJobFinished(); bool IsPackageJobPending() const; void Unmounted(); virtual void MessageReceived(BMessage* message); const BString& Path() const { return fPath; } PackageFSMountType MountType() const { return fMountType; } BPackageInstallationLocation Location() const; const node_ref& RootDirectoryRef() const { return fRootDirectoryRef; } dev_t DeviceID() const { return fRootDirectoryRef.device; } ino_t RootDirectoryID() const { return fRootDirectoryRef.node; } const node_ref& PackagesDirectoryRef() const; dev_t PackagesDeviceID() const { return PackagesDirectoryRef().device; } ino_t PackagesDirectoryID() const { return PackagesDirectoryRef().node; } Root* GetRoot() const { return fRoot; } void SetRoot(Root* root) { fRoot = root; } int64 ChangeCount() const { return fChangeCount; } PackageFileNameHashTable::Iterator PackagesByFileNameIterator() const; int OpenRootDirectory() const; void ProcessPendingNodeMonitorEvents(); bool HasPendingPackageActivationChanges() const; void ProcessPendingPackageActivationChanges(); void ClearPackageActivationChanges(); const PackageSet& PackagesToBeActivated() const { return fPackagesToBeActivated; } const PackageSet& PackagesToBeDeactivated() const { return fPackagesToBeDeactivated; } status_t CreateTransaction( BPackageInstallationLocation location, BActivationTransaction& _transaction, BDirectory& _transactionDirectory); void CommitTransaction( const BActivationTransaction& transaction, const PackageSet& packagesAlreadyAdded, const PackageSet& packagesAlreadyRemoved, BCommitTransactionResult& _result); private: struct NodeMonitorEvent; struct PackagesDirectory; typedef FSUtils::RelativePath RelativePath; typedef DoublyLinkedList NodeMonitorEventList; private: void _HandleEntryCreatedOrRemoved( const BMessage* message, bool created); void _HandleEntryMoved(const BMessage* message); void _QueueNodeMonitorEvent(const BString& name, bool wasCreated); void _PackagesEntryCreated(const char* name); void _PackagesEntryRemoved(const char* name); status_t _ReadPackagesDirectory(); status_t _InitLatestState(); status_t _InitLatestStateFromActivatedPackages(); status_t _GetActivePackages(int fd); void _RunQueuedScripts(); // TODO: Never called, fix? bool _CheckActivePackagesMatchLatestState( PackageFSGetPackageInfosRequest* request); void _SetLatestState(VolumeState* state, bool isActive); void _DumpState(VolumeState* state); status_t _AddRepository(BSolver* solver, BSolverRepository& repository, bool activeOnly, bool installed); status_t _OpenPackagesSubDirectory( const RelativePath& path, bool create, BDirectory& _directory); void _CommitTransaction(BMessage* message, const BActivationTransaction* transaction, const PackageSet& packagesAlreadyAdded, const PackageSet& packagesAlreadyRemoved, BCommitTransactionResult& _result); static void _CollectPackageNamesAdded( const VolumeState* oldState, const VolumeState* newState, BStringList& addedPackageNames); private: BString fPath; PackageFSMountType fMountType; node_ref fRootDirectoryRef; PackagesDirectory* fPackagesDirectories; uint32 fPackagesDirectoryCount; Root* fRoot; Listener* fListener; PackageFileManager* fPackageFileManager; VolumeState* fLatestState; VolumeState* fActiveState; int64 fChangeCount; BLocker fLock; BLocker fPendingNodeMonitorEventsLock; NodeMonitorEventList fPendingNodeMonitorEvents; bigtime_t fNodeMonitorEventHandleTime; PackageSet fPackagesToBeActivated; PackageSet fPackagesToBeDeactivated; BMessage fLocationInfoReply; // only accessed in the application thread int32 fPendingPackageJobCount; }; class Volume::Listener { public: virtual ~Listener(); virtual void VolumeNodeMonitorEventOccurred(Volume* volume) = 0; }; #endif // VOLUME_H