1/*
2 * Copyright 2013-2021, 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 *		Andrew Lindesay <apl@lindesay.co.nz>
8 */
9#ifndef VOLUME_H
10#define VOLUME_H
11
12
13#include <Handler.h>
14#include <Locker.h>
15#include <Message.h>
16#include <String.h>
17
18#include <package/ActivationTransaction.h>
19#include <package/DaemonClient.h>
20#include <package/packagefs.h>
21#include <util/DoublyLinkedList.h>
22
23#include "FSUtils.h"
24#include "Package.h"
25
26
27// Locking Policy
28// ==============
29//
30// A Volume object is accessed by two threads:
31// 1. The application thread: initially (c'tor and Init()) and when handling a
32//    location info request (HandleGetLocationInfoRequest()).
33// 2. The corresponding Root object's job thread (any other operation).
34//
35// The only thread synchronization needed is for the status information accessed
36// by HandleGetLocationInfoRequest() and modified by the job thread. The data
37// are encapsulated in a VolumeState, which is protected by Volume::fLock. The
38// lock must be held by the app thread when accessing the data (it reads only)
39// and by the job thread when modifying the data (not needed when reading).
40
41
42using BPackageKit::BPrivate::BActivationTransaction;
43using BPackageKit::BPrivate::BDaemonClient;
44
45class BDirectory;
46
47class CommitTransactionHandler;
48class PackageFileManager;
49class Root;
50class VolumeState;
51
52namespace BPackageKit {
53	class BSolver;
54	class BSolverRepository;
55}
56
57using BPackageKit::BPackageInstallationLocation;
58using BPackageKit::BSolver;
59using BPackageKit::BSolverRepository;
60
61
62class Volume : public BHandler {
63public:
64			class Listener;
65
66public:
67								Volume(BLooper* looper);
68	virtual						~Volume();
69
70			status_t			Init(const node_ref& rootDirectoryRef,
71									node_ref& _packageRootRef);
72			status_t			InitPackages(Listener* listener);
73
74			status_t			AddPackagesToRepository(
75									BSolverRepository& repository,
76									bool activeOnly);
77			void				InitialVerify(Volume* nextVolume,
78									Volume* nextNextVolume);
79			void				HandleGetLocationInfoRequest(BMessage* message);
80			void				HandleCommitTransactionRequest(
81									BMessage* message);
82
83			void				PackageJobPending();
84			void				PackageJobFinished();
85			bool				IsPackageJobPending() const;
86
87			void				Unmounted();
88
89	virtual	void				MessageReceived(BMessage* message);
90
91			const BString&		Path() const
92									{ return fPath; }
93			PackageFSMountType	MountType() const
94									{ return fMountType; }
95			BPackageInstallationLocation Location() const;
96
97			const node_ref&		RootDirectoryRef() const
98									{ return fRootDirectoryRef; }
99			dev_t				DeviceID() const
100									{ return fRootDirectoryRef.device; }
101			ino_t				RootDirectoryID() const
102									{ return fRootDirectoryRef.node; }
103
104			const node_ref&		PackagesDirectoryRef() const;
105			dev_t				PackagesDeviceID() const
106									{ return PackagesDirectoryRef().device; }
107			ino_t				PackagesDirectoryID() const
108									{ return PackagesDirectoryRef().node; }
109
110			Root*				GetRoot() const
111									{ return fRoot; }
112			void				SetRoot(Root* root)
113									{ fRoot = root; }
114
115			int64				ChangeCount() const
116									{ return fChangeCount; }
117
118			PackageFileNameHashTable::Iterator PackagesByFileNameIterator()
119									const;
120
121			int					OpenRootDirectory() const;
122
123			void				ProcessPendingNodeMonitorEvents();
124
125			bool				HasPendingPackageActivationChanges() const;
126			void				ProcessPendingPackageActivationChanges();
127			void				ClearPackageActivationChanges();
128			const PackageSet&	PackagesToBeActivated() const
129									{ return fPackagesToBeActivated; }
130			const PackageSet&	PackagesToBeDeactivated() const
131									{ return fPackagesToBeDeactivated; }
132
133			status_t			CreateTransaction(
134									BPackageInstallationLocation location,
135									BActivationTransaction& _transaction,
136									BDirectory& _transactionDirectory);
137			void				CommitTransaction(
138									const BActivationTransaction& transaction,
139									const PackageSet& packagesAlreadyAdded,
140									const PackageSet& packagesAlreadyRemoved,
141									BCommitTransactionResult& _result);
142
143private:
144			struct NodeMonitorEvent;
145			struct PackagesDirectory;
146
147			typedef FSUtils::RelativePath RelativePath;
148			typedef DoublyLinkedList<NodeMonitorEvent> NodeMonitorEventList;
149
150private:
151			void				_HandleEntryCreatedOrRemoved(
152									const BMessage* message, bool created);
153			void				_HandleEntryMoved(const BMessage* message);
154			void				_QueueNodeMonitorEvent(const BString& name,
155									bool wasCreated);
156
157			void				_PackagesEntryCreated(const char* name);
158			void				_PackagesEntryRemoved(const char* name);
159
160			status_t			_ReadPackagesDirectory();
161			status_t			_InitLatestState();
162			status_t			_InitLatestStateFromActivatedPackages();
163			status_t			_GetActivePackages(int fd);
164			void				_RunQueuedScripts(); // TODO: Never called, fix?
165			bool				_CheckActivePackagesMatchLatestState(
166									PackageFSGetPackageInfosRequest* request);
167			void				_SetLatestState(VolumeState* state,
168									bool isActive);
169			void				_DumpState(VolumeState* state);
170
171			status_t			_AddRepository(BSolver* solver,
172									BSolverRepository& repository,
173							 		bool activeOnly, bool installed);
174
175			status_t			_OpenPackagesSubDirectory(
176									const RelativePath& path, bool create,
177									BDirectory& _directory);
178
179			void				_CommitTransaction(BMessage* message,
180									const BActivationTransaction* transaction,
181									const PackageSet& packagesAlreadyAdded,
182									const PackageSet& packagesAlreadyRemoved,
183									BCommitTransactionResult& _result);
184
185	static	void				_CollectPackageNamesAdded(
186									const VolumeState* oldState,
187									const VolumeState* newState,
188									BStringList& addedPackageNames);
189
190private:
191			BString				fPath;
192			PackageFSMountType	fMountType;
193			node_ref			fRootDirectoryRef;
194			PackagesDirectory*	fPackagesDirectories;
195			uint32				fPackagesDirectoryCount;
196			Root*				fRoot;
197			Listener*			fListener;
198			PackageFileManager*	fPackageFileManager;
199			VolumeState*		fLatestState;
200			VolumeState*		fActiveState;
201			int64				fChangeCount;
202			BLocker				fLock;
203			BLocker				fPendingNodeMonitorEventsLock;
204			NodeMonitorEventList fPendingNodeMonitorEvents;
205			bigtime_t			fNodeMonitorEventHandleTime;
206			PackageSet			fPackagesToBeActivated;
207			PackageSet			fPackagesToBeDeactivated;
208			BMessage			fLocationInfoReply;
209									// only accessed in the application thread
210			int32				fPendingPackageJobCount;
211};
212
213
214class Volume::Listener {
215public:
216	virtual						~Listener();
217
218	virtual	void				VolumeNodeMonitorEventOccurred(Volume* volume)
219									= 0;
220};
221
222
223#endif	// VOLUME_H
224