xref: /haiku/src/servers/package/Volume.h (revision 830f67ef991407f287dbc1238aa5f5906d90c991)
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 
42 using BPackageKit::BPrivate::BActivationTransaction;
43 using BPackageKit::BPrivate::BDaemonClient;
44 
45 class BDirectory;
46 
47 class CommitTransactionHandler;
48 class PackageFileManager;
49 class Root;
50 class VolumeState;
51 
52 namespace BPackageKit {
53 	class BSolver;
54 	class BSolverRepository;
55 }
56 
57 using BPackageKit::BPackageInstallationLocation;
58 using BPackageKit::BSolver;
59 using BPackageKit::BSolverRepository;
60 
61 
62 class Volume : public BHandler {
63 public:
64 			class Listener;
65 
66 public:
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 
143 private:
144 			struct NodeMonitorEvent;
145 			struct PackagesDirectory;
146 
147 			typedef FSUtils::RelativePath RelativePath;
148 			typedef DoublyLinkedList<NodeMonitorEvent> NodeMonitorEventList;
149 
150 private:
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 
190 private:
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 
214 class Volume::Listener {
215 public:
216 	virtual						~Listener();
217 
218 	virtual	void				VolumeNodeMonitorEventOccurred(Volume* volume)
219 									= 0;
220 };
221 
222 
223 #endif	// VOLUME_H
224