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