1/*
2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef PACKAGE_FS_ROOT_H
6#define PACKAGE_FS_ROOT_H
7
8
9#include <Referenceable.h>
10
11#include <util/AutoLock.h>
12#include <util/DoublyLinkedList.h>
13
14#include <lock.h>
15
16#include "DependencyFamily.h"
17#include "ResolvableFamily.h"
18#include "Volume.h"
19
20
21class PackageLinksDirectory;
22
23
24class PackageFSRoot : private BReferenceable,
25	public DoublyLinkedListLinkImpl<PackageFSRoot> {
26public:
27	// constructor and destructor are conceptually private
28								PackageFSRoot(dev_t deviceID, ino_t nodeID);
29	virtual						~PackageFSRoot();
30
31	static	status_t			GlobalInit();
32	static	void				GlobalUninit();
33
34	inline	bool				ReadLock() const;
35	inline	void				ReadUnlock() const;
36	inline	bool				WriteLock();
37	inline	void				WriteUnlock();
38
39			status_t			Init();
40
41	static	status_t			RegisterVolume(Volume* volume);
42			void				UnregisterVolume(Volume* volume);
43
44			status_t			AddPackage(Package* package);
45			void				RemovePackage(Package* package);
46
47			dev_t				DeviceID() const	{ return fDeviceID; }
48			ino_t				NodeID() const		{ return fNodeID; }
49			bool				IsCustom() const	{ return fDeviceID < 0; }
50
51			Volume*				SystemVolume() const;
52			PackageLinksDirectory* GetPackageLinksDirectory() const
53									{ return fPackageLinksDirectory; }
54
55private:
56			typedef DoublyLinkedList<PackageFSRoot> RootList;
57			typedef DoublyLinkedList<Volume> VolumeList;
58
59private:
60			status_t			_AddVolume(Volume* volume);
61			void				_RemoveVolume(Volume* volume);
62
63			status_t			_AddPackage(Package* package);
64			void				_RemovePackage(Package* package);
65
66			void				_ResolveDependencies(
67									ResolvableDependencyList& dependencies);
68			void				_ResolveDependency(Dependency* dependency);
69
70	static	status_t			_GetOrCreateRoot(dev_t deviceID, ino_t nodeID,
71									PackageFSRoot*& _root);
72	static	PackageFSRoot*		_FindRootLocked(dev_t deviceID, ino_t nodeID);
73	static	void				_PutRoot(PackageFSRoot* root);
74
75private:
76	static	mutex				sRootListLock;
77	static	RootList			sRootList;
78
79	mutable	rw_lock				fLock;
80			dev_t				fDeviceID;
81			ino_t				fNodeID;
82			VolumeList			fVolumes;
83			Volume*				fSystemVolume;
84			PackageLinksDirectory* fPackageLinksDirectory;
85			ResolvableFamilyHashTable fResolvables;
86			DependencyFamilyHashTable fDependencies;
87};
88
89
90bool
91PackageFSRoot::ReadLock() const
92{
93	return rw_lock_read_lock(&fLock) == B_OK;
94}
95
96
97void
98PackageFSRoot::ReadUnlock() const
99{
100	rw_lock_read_unlock(&fLock);
101}
102
103
104bool
105PackageFSRoot::WriteLock()
106{
107	return rw_lock_write_lock(&fLock) == B_OK;
108}
109
110
111void
112PackageFSRoot::WriteUnlock()
113{
114	rw_lock_write_unlock(&fLock);
115}
116
117
118typedef AutoLocker<const PackageFSRoot,
119	AutoLockerReadLocking<const PackageFSRoot> > PackageFSRootReadLocker;
120typedef AutoLocker<PackageFSRoot, AutoLockerWriteLocking<PackageFSRoot> >
121	PackageFSRootWriteLocker;
122
123
124#endif	// PACKAGE_FS_ROOT_H
125