xref: /haiku/src/servers/package/Volume.h (revision a22fa0c977d48d26c3d7394b9e188a52e2bf11e2)
126296b0aSIngo Weinhold /*
232cae724SIngo Weinhold  * Copyright 2013-2014, 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>
726296b0aSIngo Weinhold  */
826296b0aSIngo Weinhold #ifndef VOLUME_H
926296b0aSIngo Weinhold #define VOLUME_H
1026296b0aSIngo Weinhold 
1126296b0aSIngo Weinhold 
123d53bd47SIngo Weinhold #include <Handler.h>
138fb3930aSIngo Weinhold #include <Locker.h>
14e6216e37SIngo Weinhold #include <Message.h>
1526296b0aSIngo Weinhold #include <String.h>
1626296b0aSIngo Weinhold 
1738c62dfbSIngo Weinhold #include <package/ActivationTransaction.h>
1838c62dfbSIngo Weinhold #include <package/DaemonClient.h>
19b254217aSIngo Weinhold #include <package/packagefs.h>
208fb3930aSIngo Weinhold #include <util/DoublyLinkedList.h>
2126296b0aSIngo Weinhold 
2223733521SIngo Weinhold #include "FSUtils.h"
233d53bd47SIngo Weinhold #include "Package.h"
243d53bd47SIngo Weinhold 
2526296b0aSIngo Weinhold 
2632cae724SIngo Weinhold // Locking Policy
2732cae724SIngo Weinhold // ==============
2832cae724SIngo Weinhold //
2932cae724SIngo Weinhold // A Volume object is accessed by two threads:
3032cae724SIngo Weinhold // 1. The application thread: initially (c'tor and Init()) and when handling a
3132cae724SIngo Weinhold //    location info request (HandleGetLocationInfoRequest()).
3232cae724SIngo Weinhold // 2. The corresponding Root object's job thread (any other operation).
3332cae724SIngo Weinhold //
3432cae724SIngo Weinhold // The only thread synchronization needed is for the status information accessed
3532cae724SIngo Weinhold // by HandleGetLocationInfoRequest() and modified by the job thread. The data
362dbf8167SIngo Weinhold // are encapsulated in a VolumeState, which is protected by Volume::fLock. The
372dbf8167SIngo Weinhold // lock must be held by the app thread when accessing the data (it reads only)
382dbf8167SIngo Weinhold // and by the job thread when modifying the data (not needed when reading).
3932cae724SIngo Weinhold 
4032cae724SIngo Weinhold 
4138c62dfbSIngo Weinhold using BPackageKit::BPrivate::BActivationTransaction;
4238c62dfbSIngo Weinhold using BPackageKit::BPrivate::BDaemonClient;
4338c62dfbSIngo Weinhold 
4426296b0aSIngo Weinhold class BDirectory;
4526296b0aSIngo Weinhold 
46933e7b32SIngo Weinhold class CommitTransactionHandler;
472dbf8167SIngo Weinhold class PackageFileManager;
4826296b0aSIngo Weinhold class Root;
49273763d0SIngo Weinhold class VolumeState;
5026296b0aSIngo Weinhold 
5192b6d585SIngo Weinhold namespace BPackageKit {
5292b6d585SIngo Weinhold 	class BSolver;
5392b6d585SIngo Weinhold 	class BSolverRepository;
5492b6d585SIngo Weinhold }
5592b6d585SIngo Weinhold 
5638c62dfbSIngo Weinhold using BPackageKit::BPackageInstallationLocation;
5738c62dfbSIngo Weinhold using BPackageKit::BSolver;
5838c62dfbSIngo Weinhold using BPackageKit::BSolverRepository;
5938c62dfbSIngo Weinhold 
6026296b0aSIngo Weinhold 
613d53bd47SIngo Weinhold class Volume : public BHandler {
6226296b0aSIngo Weinhold public:
639e409614SIngo Weinhold 			class Listener;
649e409614SIngo Weinhold 
659e409614SIngo Weinhold public:
668fb3930aSIngo Weinhold 								Volume(BLooper* looper);
673d53bd47SIngo Weinhold 	virtual						~Volume();
6826296b0aSIngo Weinhold 
693d53bd47SIngo Weinhold 			status_t			Init(const node_ref& rootDirectoryRef,
703d53bd47SIngo Weinhold 									node_ref& _packageRootRef);
719e409614SIngo Weinhold 			status_t			InitPackages(Listener* listener);
728fb3930aSIngo Weinhold 
7392b6d585SIngo Weinhold 			status_t			AddPackagesToRepository(
7492b6d585SIngo Weinhold 									BSolverRepository& repository,
7592b6d585SIngo Weinhold 									bool activeOnly);
7692b6d585SIngo Weinhold 			void				InitialVerify(Volume* nextVolume,
7792b6d585SIngo Weinhold 									Volume* nextNextVolume);
78e6216e37SIngo Weinhold 			void				HandleGetLocationInfoRequest(BMessage* message);
7985d2badfSIngo Weinhold 			void				HandleCommitTransactionRequest(
8085d2badfSIngo Weinhold 									BMessage* message);
8192b6d585SIngo Weinhold 
8232cae724SIngo Weinhold 			void				PackageJobPending();
8332cae724SIngo Weinhold 			void				PackageJobFinished();
8432cae724SIngo Weinhold 			bool				IsPackageJobPending() const;
8532cae724SIngo Weinhold 
868fb3930aSIngo Weinhold 			void				Unmounted();
873d53bd47SIngo Weinhold 
883d53bd47SIngo Weinhold 	virtual	void				MessageReceived(BMessage* message);
8926296b0aSIngo Weinhold 
9026296b0aSIngo Weinhold 			const BString&		Path() const
9126296b0aSIngo Weinhold 									{ return fPath; }
9226296b0aSIngo Weinhold 			PackageFSMountType	MountType() const
9326296b0aSIngo Weinhold 									{ return fMountType; }
9438c62dfbSIngo Weinhold 			BPackageInstallationLocation Location() const;
953d53bd47SIngo Weinhold 
963d53bd47SIngo Weinhold 			const node_ref&		RootDirectoryRef() const
973d53bd47SIngo Weinhold 									{ return fRootDirectoryRef; }
9826296b0aSIngo Weinhold 			dev_t				DeviceID() const
993d53bd47SIngo Weinhold 									{ return fRootDirectoryRef.device; }
10026296b0aSIngo Weinhold 			ino_t				RootDirectoryID() const
1013d53bd47SIngo Weinhold 									{ return fRootDirectoryRef.node; }
1023d53bd47SIngo Weinhold 
103c8dd5bbdSIngo Weinhold 			const node_ref&		PackagesDirectoryRef() const;
1043d53bd47SIngo Weinhold 			dev_t				PackagesDeviceID() const
105c8dd5bbdSIngo Weinhold 									{ return PackagesDirectoryRef().device; }
1063d53bd47SIngo Weinhold 			ino_t				PackagesDirectoryID() const
107c8dd5bbdSIngo Weinhold 									{ return PackagesDirectoryRef().node; }
10826296b0aSIngo Weinhold 
10926296b0aSIngo Weinhold 			Root*				GetRoot() const
11026296b0aSIngo Weinhold 									{ return fRoot; }
11126296b0aSIngo Weinhold 			void				SetRoot(Root* root)
11226296b0aSIngo Weinhold 									{ fRoot = root; }
11326296b0aSIngo Weinhold 
114870e93acSIngo Weinhold 			int64				ChangeCount() const
115870e93acSIngo Weinhold 									{ return fChangeCount; }
116870e93acSIngo Weinhold 
11732cae724SIngo Weinhold 			PackageFileNameHashTable::Iterator PackagesByFileNameIterator()
11832cae724SIngo Weinhold 									const;
11938c62dfbSIngo Weinhold 
1203d53bd47SIngo Weinhold 			int					OpenRootDirectory() const;
1213d53bd47SIngo Weinhold 
1228fb3930aSIngo Weinhold 			void				ProcessPendingNodeMonitorEvents();
1238fb3930aSIngo Weinhold 
124a6c7f5e3SIngo Weinhold 			bool				HasPendingPackageActivationChanges() const;
125a6c7f5e3SIngo Weinhold 			void				ProcessPendingPackageActivationChanges();
12638c62dfbSIngo Weinhold 			void				ClearPackageActivationChanges();
12738c62dfbSIngo Weinhold 			const PackageSet&	PackagesToBeActivated() const
12838c62dfbSIngo Weinhold 									{ return fPackagesToBeActivated; }
12938c62dfbSIngo Weinhold 			const PackageSet&	PackagesToBeDeactivated() const
13038c62dfbSIngo Weinhold 									{ return fPackagesToBeDeactivated; }
13138c62dfbSIngo Weinhold 
13238c62dfbSIngo Weinhold 			status_t			CreateTransaction(
13338c62dfbSIngo Weinhold 									BPackageInstallationLocation location,
13438c62dfbSIngo Weinhold 									BActivationTransaction& _transaction,
13538c62dfbSIngo Weinhold 									BDirectory& _transactionDirectory);
13638c62dfbSIngo Weinhold 			void				CommitTransaction(
13738c62dfbSIngo Weinhold 									const BActivationTransaction& transaction,
13838c62dfbSIngo Weinhold 									const PackageSet& packagesAlreadyAdded,
13938c62dfbSIngo Weinhold 									const PackageSet& packagesAlreadyRemoved,
1400de3219eSIngo Weinhold 									BCommitTransactionResult& _result);
141a6c7f5e3SIngo Weinhold 
1428fb3930aSIngo Weinhold private:
1438fb3930aSIngo Weinhold 			struct NodeMonitorEvent;
144c8dd5bbdSIngo Weinhold 			struct PackagesDirectory;
1458fb3930aSIngo Weinhold 
14623733521SIngo Weinhold 			typedef FSUtils::RelativePath RelativePath;
14785d2badfSIngo Weinhold 			typedef DoublyLinkedList<NodeMonitorEvent> NodeMonitorEventList;
148a6c7f5e3SIngo Weinhold 
1493d53bd47SIngo Weinhold private:
1503d53bd47SIngo Weinhold 			void				_HandleEntryCreatedOrRemoved(
1513d53bd47SIngo Weinhold 									const BMessage* message, bool created);
1523d53bd47SIngo Weinhold 			void				_HandleEntryMoved(const BMessage* message);
1538fb3930aSIngo Weinhold 			void				_QueueNodeMonitorEvent(const BString& name,
1548fb3930aSIngo Weinhold 									bool wasCreated);
1553d53bd47SIngo Weinhold 
1563d53bd47SIngo Weinhold 			void				_PackagesEntryCreated(const char* name);
1573d53bd47SIngo Weinhold 			void				_PackagesEntryRemoved(const char* name);
1583d53bd47SIngo Weinhold 
1593d53bd47SIngo Weinhold 			status_t			_ReadPackagesDirectory();
1602dbf8167SIngo Weinhold 			status_t			_InitLatestState();
1612dbf8167SIngo Weinhold 			status_t			_InitLatestStateFromActivatedPackages();
1623d53bd47SIngo Weinhold 			status_t			_GetActivePackages(int fd);
163*a22fa0c9SAlexander G. M. Smith 			void				_RunQueuedScripts(); // TODO: Never called, fix?
1642dbf8167SIngo Weinhold 			bool				_CheckActivePackagesMatchLatestState(
1652dbf8167SIngo Weinhold 									PackageFSGetPackageInfosRequest* request);
1662dbf8167SIngo Weinhold 			void				_SetLatestState(VolumeState* state,
1672dbf8167SIngo Weinhold 									bool isActive);
1682dbf8167SIngo Weinhold 			void				_DumpState(VolumeState* state);
1693d53bd47SIngo Weinhold 
17092b6d585SIngo Weinhold 			status_t			_AddRepository(BSolver* solver,
17192b6d585SIngo Weinhold 									BSolverRepository& repository,
17292b6d585SIngo Weinhold 							 		bool activeOnly, bool installed);
17392b6d585SIngo Weinhold 
17485d2badfSIngo Weinhold 			status_t			_OpenPackagesSubDirectory(
17585d2badfSIngo Weinhold 									const RelativePath& path, bool create,
17685d2badfSIngo Weinhold 									BDirectory& _directory);
17785d2badfSIngo Weinhold 
1780de3219eSIngo Weinhold 			void				_CommitTransaction(BMessage* message,
1790de3219eSIngo Weinhold 									const BActivationTransaction* transaction,
1800de3219eSIngo Weinhold 									const PackageSet& packagesAlreadyAdded,
1810de3219eSIngo Weinhold 									const PackageSet& packagesAlreadyRemoved,
1820de3219eSIngo Weinhold 									BCommitTransactionResult& _result);
1830de3219eSIngo Weinhold 
18426296b0aSIngo Weinhold private:
18526296b0aSIngo Weinhold 			BString				fPath;
18626296b0aSIngo Weinhold 			PackageFSMountType	fMountType;
1873d53bd47SIngo Weinhold 			node_ref			fRootDirectoryRef;
188c8dd5bbdSIngo Weinhold 			PackagesDirectory*	fPackagesDirectories;
189c8dd5bbdSIngo Weinhold 			uint32				fPackagesDirectoryCount;
19026296b0aSIngo Weinhold 			Root*				fRoot;
1919e409614SIngo Weinhold 			Listener*			fListener;
1922dbf8167SIngo Weinhold 			PackageFileManager*	fPackageFileManager;
1932dbf8167SIngo Weinhold 			VolumeState*		fLatestState;
1942dbf8167SIngo Weinhold 			VolumeState*		fActiveState;
195870e93acSIngo Weinhold 			int64				fChangeCount;
1962dbf8167SIngo Weinhold 			BLocker				fLock;
1978fb3930aSIngo Weinhold 			BLocker				fPendingNodeMonitorEventsLock;
1988fb3930aSIngo Weinhold 			NodeMonitorEventList fPendingNodeMonitorEvents;
19938c62dfbSIngo Weinhold 			bigtime_t			fNodeMonitorEventHandleTime;
200a6c7f5e3SIngo Weinhold 			PackageSet			fPackagesToBeActivated;
201a6c7f5e3SIngo Weinhold 			PackageSet			fPackagesToBeDeactivated;
202e6216e37SIngo Weinhold 			BMessage			fLocationInfoReply;
20332cae724SIngo Weinhold 									// only accessed in the application thread
2047a35d803SIngo Weinhold 			int32				fPendingPackageJobCount;
20526296b0aSIngo Weinhold };
20626296b0aSIngo Weinhold 
20726296b0aSIngo Weinhold 
2089e409614SIngo Weinhold class Volume::Listener {
2099e409614SIngo Weinhold public:
2109e409614SIngo Weinhold 	virtual						~Listener();
2119e409614SIngo Weinhold 
2129e409614SIngo Weinhold 	virtual	void				VolumeNodeMonitorEventOccurred(Volume* volume)
2139e409614SIngo Weinhold 									= 0;
2149e409614SIngo Weinhold };
2159e409614SIngo Weinhold 
2169e409614SIngo Weinhold 
21726296b0aSIngo Weinhold #endif	// VOLUME_H
218