xref: /haiku/src/servers/package/Volume.h (revision 0754c319592cd8a523959d85fb06ab23c64a98a6)
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 			bool				_CheckActivePackagesMatchLatestState(
164 									PackageFSGetPackageInfosRequest* request);
165 			void				_SetLatestState(VolumeState* state,
166 									bool isActive);
167 			void				_DumpState(VolumeState* state);
168 
169 			status_t			_AddRepository(BSolver* solver,
170 									BSolverRepository& repository,
171 							 		bool activeOnly, bool installed);
172 
173 			status_t			_OpenPackagesSubDirectory(
174 									const RelativePath& path, bool create,
175 									BDirectory& _directory);
176 
177 			void				_CommitTransaction(BMessage* message,
178 									const BActivationTransaction* transaction,
179 									const PackageSet& packagesAlreadyAdded,
180 									const PackageSet& packagesAlreadyRemoved,
181 									BCommitTransactionResult& _result);
182 
183 private:
184 			BString				fPath;
185 			PackageFSMountType	fMountType;
186 			node_ref			fRootDirectoryRef;
187 			PackagesDirectory*	fPackagesDirectories;
188 			uint32				fPackagesDirectoryCount;
189 			Root*				fRoot;
190 			Listener*			fListener;
191 			PackageFileManager*	fPackageFileManager;
192 			VolumeState*		fLatestState;
193 			VolumeState*		fActiveState;
194 			int64				fChangeCount;
195 			BLocker				fLock;
196 			BLocker				fPendingNodeMonitorEventsLock;
197 			NodeMonitorEventList fPendingNodeMonitorEvents;
198 			bigtime_t			fNodeMonitorEventHandleTime;
199 			PackageSet			fPackagesToBeActivated;
200 			PackageSet			fPackagesToBeDeactivated;
201 			BMessage			fLocationInfoReply;
202 									// only accessed in the application thread
203 			int32				fPendingPackageJobCount;
204 };
205 
206 
207 class Volume::Listener {
208 public:
209 	virtual						~Listener();
210 
211 	virtual	void				VolumeNodeMonitorEventOccurred(Volume* volume)
212 									= 0;
213 };
214 
215 
216 #endif	// VOLUME_H
217