xref: /haiku/src/servers/package/Volume.h (revision 5e96d7d537fbec23bad4ae9b4c8e7b02e769f0c6)
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 Volume::State object which contains a lock. The lock
37 // must be held by the app thread when accessing the data (it reads only) and
38 // 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 Root;
47 
48 namespace BPackageKit {
49 	class BSolver;
50 	class BSolverRepository;
51 }
52 
53 using BPackageKit::BPackageInstallationLocation;
54 using BPackageKit::BSolver;
55 using BPackageKit::BSolverRepository;
56 
57 
58 class Volume : public BHandler {
59 public:
60 			class Listener;
61 
62 public:
63 								Volume(BLooper* looper);
64 	virtual						~Volume();
65 
66 			status_t			Init(const node_ref& rootDirectoryRef,
67 									node_ref& _packageRootRef);
68 			status_t			InitPackages(Listener* listener);
69 
70 			status_t			AddPackagesToRepository(
71 									BSolverRepository& repository,
72 									bool activeOnly);
73 			void				InitialVerify(Volume* nextVolume,
74 									Volume* nextNextVolume);
75 			void				HandleGetLocationInfoRequest(BMessage* message);
76 			void				HandleCommitTransactionRequest(
77 									BMessage* message);
78 
79 			void				PackageJobPending();
80 			void				PackageJobFinished();
81 			bool				IsPackageJobPending() const;
82 
83 			void				Unmounted();
84 
85 	virtual	void				MessageReceived(BMessage* message);
86 
87 			const BString&		Path() const
88 									{ return fPath; }
89 			PackageFSMountType	MountType() const
90 									{ return fMountType; }
91 			BPackageInstallationLocation Location() const;
92 
93 			const node_ref&		RootDirectoryRef() const
94 									{ return fRootDirectoryRef; }
95 			dev_t				DeviceID() const
96 									{ return fRootDirectoryRef.device; }
97 			ino_t				RootDirectoryID() const
98 									{ return fRootDirectoryRef.node; }
99 
100 			const node_ref&		PackagesDirectoryRef() const
101 									{ return fPackagesDirectoryRef; }
102 			dev_t				PackagesDeviceID() const
103 									{ return fPackagesDirectoryRef.device; }
104 			ino_t				PackagesDirectoryID() const
105 									{ return fPackagesDirectoryRef.node; }
106 
107 			Root*				GetRoot() const
108 									{ return fRoot; }
109 			void				SetRoot(Root* root)
110 									{ fRoot = root; }
111 
112 			PackageFileNameHashTable::Iterator PackagesByFileNameIterator()
113 									const;
114 
115 			int					OpenRootDirectory() const;
116 
117 			void				ProcessPendingNodeMonitorEvents();
118 
119 			bool				HasPendingPackageActivationChanges() const;
120 			void				ProcessPendingPackageActivationChanges();
121 			void				ClearPackageActivationChanges();
122 			const PackageSet&	PackagesToBeActivated() const
123 									{ return fPackagesToBeActivated; }
124 			const PackageSet&	PackagesToBeDeactivated() const
125 									{ return fPackagesToBeDeactivated; }
126 
127 			status_t			CreateTransaction(
128 									BPackageInstallationLocation location,
129 									BActivationTransaction& _transaction,
130 									BDirectory& _transactionDirectory);
131 			void				CommitTransaction(
132 									const BActivationTransaction& transaction,
133 									const PackageSet& packagesAlreadyAdded,
134 									const PackageSet& packagesAlreadyRemoved,
135 									BDaemonClient::BCommitTransactionResult&
136 										_result);
137 
138 private:
139 			struct NodeMonitorEvent;
140 			struct State;
141 			struct CommitTransactionHandler;
142 
143 			friend struct CommitTransactionHandler;
144 
145 			typedef FSUtils::RelativePath RelativePath;
146 			typedef DoublyLinkedList<NodeMonitorEvent> NodeMonitorEventList;
147 
148 private:
149 			void				_HandleEntryCreatedOrRemoved(
150 									const BMessage* message, bool created);
151 			void				_HandleEntryMoved(const BMessage* message);
152 			void				_QueueNodeMonitorEvent(const BString& name,
153 									bool wasCreated);
154 
155 			void				_PackagesEntryCreated(const char* name);
156 			void				_PackagesEntryRemoved(const char* name);
157 
158 			void				_FillInActivationChangeItem(
159 									PackageFSActivationChangeItem* item,
160 									PackageFSActivationChangeType type,
161 									Package* package, char*& nameBuffer);
162 
163 			void				_AddPackage(Package* package);
164 			void				_RemovePackage(Package* package);
165 
166 			status_t			_ReadPackagesDirectory();
167 			status_t			_GetActivePackages(int fd);
168 
169 			status_t			_AddRepository(BSolver* solver,
170 									BSolverRepository& repository,
171 							 		bool activeOnly, bool installed);
172 
173 			status_t			_OpenPackagesFile(
174 									const RelativePath& subDirectoryPath,
175 									const char* fileName, uint32 openMode,
176 									BFile& _file, BEntry* _entry = NULL);
177 			status_t			_OpenPackagesSubDirectory(
178 									const RelativePath& path, bool create,
179 									BDirectory& _directory);
180 
181 			status_t			_OpenSettingsRootDirectory(
182 									BDirectory& _directory);
183 
184 			status_t			_CreateActivationFileContent(
185 									const PackageSet& toActivate,
186 									const PackageSet& toDeactivate,
187 									BString& _content);
188 			status_t			_WriteActivationFile(
189 									const RelativePath& directoryPath,
190 									const char* fileName,
191 									const PackageSet& toActivate,
192 									const PackageSet& toDeactivate,
193 									BEntry& _entry);
194 
195 			status_t			_WriteTextFile(
196 									const RelativePath& directoryPath,
197 									const char* fileName,
198 									const BString& content, BEntry& _entry);
199 
200 			void				_ChangePackageActivation(
201 									const PackageSet& packagesToActivate,
202 									const PackageSet& packagesToDeactivate);
203 									// throws Exception
204 
205 			status_t			_ExtractPackageContent(Package* package,
206 									const char* contentPath,
207 									BDirectory& targetDirectory,
208 									BDirectory& _extractedFilesDirectory);
209 
210 private:
211 			BString				fPath;
212 			PackageFSMountType	fMountType;
213 			node_ref			fRootDirectoryRef;
214 			node_ref			fPackagesDirectoryRef;
215 			Root*				fRoot;
216 			Listener*			fListener;
217 			State*				fState;
218 			BLocker				fPendingNodeMonitorEventsLock;
219 			NodeMonitorEventList fPendingNodeMonitorEvents;
220 			bigtime_t			fNodeMonitorEventHandleTime;
221 			PackageSet			fPackagesToBeActivated;
222 			PackageSet			fPackagesToBeDeactivated;
223 			BMessage			fLocationInfoReply;
224 									// only accessed in the application thread
225 };
226 
227 
228 class Volume::Listener {
229 public:
230 	virtual						~Listener();
231 
232 	virtual	void				VolumeNodeMonitorEventOccurred(Volume* volume)
233 									= 0;
234 };
235 
236 
237 #endif	// VOLUME_H
238