xref: /haiku/src/servers/package/Volume.h (revision f32d5c5ca53c502f59f7d260ec5bd0546a577283)
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