1// StatisticsManager.cpp
2
3#include "StatisticsManager.h"
4
5#include <AutoLocker.h>
6#include <HashMap.h>
7#include <Message.h>
8
9#include "DebugSupport.h"
10#include "SecurityContext.h"
11
12typedef HashMap<HashString, int32>	UserCountMap;
13
14// ShareStatistics
15class StatisticsManager::ShareStatistics {
16public:
17	ShareStatistics(const char* share)
18		: fShare(share),
19		  fUsers()
20	{
21	}
22
23	~ShareStatistics()
24	{
25	}
26
27	status_t Init()
28	{
29		return fUsers.InitCheck();
30	}
31
32	const char* GetShare() const
33	{
34		return fShare.GetString();
35	}
36
37	void AddUser(const char* user)
38	{
39		int32 count = 0;
40		if (fUsers.ContainsKey(user))
41			count = fUsers.Get(user);
42		count++;
43		fUsers.Put(user, count);
44	}
45
46	void RemoveUser(const char* user)
47	{
48		if (!fUsers.ContainsKey(user))
49			return;
50
51		int32 count = fUsers.Get(user);
52		count--;
53		if (count > 0)
54			fUsers.Put(user, count);
55		else
56			fUsers.Remove(user);
57	}
58
59	status_t GetStatistics(BMessage* statistics)
60	{
61		// add "mounted by"
62		for (UserCountMap::Iterator it = fUsers.GetIterator(); it.HasNext();) {
63			HashString user(it.Next().key);
64			status_t error = statistics->AddString("mounted by",
65				user.GetString());
66			if (error != B_OK)
67				return error;
68		}
69		return B_OK;
70	}
71
72private:
73	HashString		fShare;
74	UserCountMap	fUsers;
75};
76
77// ShareStatisticsMap
78struct StatisticsManager::ShareStatisticsMap
79	: HashMap<HashString, StatisticsManager::ShareStatistics*> {
80};
81
82
83// constructor
84StatisticsManager::StatisticsManager()
85	: fLock("statistics manager"),
86	  fShareStatistics(NULL)
87{
88}
89
90// destructor
91StatisticsManager::~StatisticsManager()
92{
93	// delete the share statistics
94	for (ShareStatisticsMap::Iterator it = fShareStatistics->GetIterator();
95		 it.HasNext();) {
96		ShareStatistics* statistics = it.Next().value;
97		delete statistics;
98	}
99
100	delete fShareStatistics;
101}
102
103// Init
104status_t
105StatisticsManager::Init()
106{
107	// check lock
108	if (fLock.Sem() < 0)
109		return fLock.Sem();
110
111	// create share info map
112	fShareStatistics = new(std::nothrow) ShareStatisticsMap;
113	if (!fShareStatistics)
114		return B_NO_MEMORY;
115	status_t error = fShareStatistics->InitCheck();
116	if (error != B_OK)
117		return error;
118
119	return B_OK;
120}
121
122// CreateDefault
123status_t
124StatisticsManager::CreateDefault()
125{
126	if (fManager)
127		return B_OK;
128
129	fManager = new(std::nothrow) StatisticsManager;
130	if (!fManager)
131		return B_NO_MEMORY;
132	status_t error = fManager->Init();
133	if (error != B_OK) {
134		DeleteDefault();
135		return error;
136	}
137
138	return B_OK;
139}
140
141// DeleteDefault
142void
143StatisticsManager::DeleteDefault()
144{
145	if (fManager) {
146		delete fManager;
147		fManager = NULL;
148	}
149}
150
151// GetDefault
152StatisticsManager*
153StatisticsManager::GetDefault()
154{
155	return fManager;
156}
157
158// UserRemoved
159void
160StatisticsManager::UserRemoved(User* user)
161{
162	// the shares the user mounted should already have been unmounted
163}
164
165// ShareRemoved
166void
167StatisticsManager::ShareRemoved(Share* share)
168{
169	if (!share)
170		return;
171
172	AutoLocker<Locker> locker(fLock);
173
174	ShareStatistics* statistics = fShareStatistics->Remove(share->GetName());
175	delete statistics;
176}
177
178// ShareMounted
179void
180StatisticsManager::ShareMounted(Share* share, User* user)
181{
182	if (!share || !user)
183		return;
184
185	AutoLocker<Locker> locker(fLock);
186
187	// get the statistics
188	ShareStatistics* statistics = fShareStatistics->Get(share->GetName());
189	if (!statistics) {
190		// no statistics for this share yet: create
191		statistics = new(std::nothrow) ShareStatistics(share->GetName());
192		if (!statistics)
193			return;
194
195		// add to the map
196		if (fShareStatistics->Put(share->GetName(), statistics) != B_OK) {
197			delete statistics;
198			return;
199		}
200	}
201
202	// add the user
203	statistics->AddUser(user->GetName());
204}
205
206// ShareUnmounted
207void
208StatisticsManager::ShareUnmounted(Share* share, User* user)
209{
210	if (!share || !user)
211		return;
212
213	AutoLocker<Locker> locker(fLock);
214
215	// get the statistics
216	ShareStatistics* statistics = fShareStatistics->Get(share->GetName());
217	if (!statistics)
218		return;
219
220	// remove the user
221	statistics->RemoveUser(user->GetName());
222}
223
224// GetUserStatistics
225status_t
226StatisticsManager::GetUserStatistics(User* user, BMessage* statistics)
227{
228	if (!user)
229		return B_BAD_VALUE;
230
231	return GetUserStatistics(user->GetName(), statistics);
232}
233
234// GetUserStatistics
235status_t
236StatisticsManager::GetUserStatistics(const char* user, BMessage* _statistics)
237{
238	if (!user || !_statistics)
239		return B_BAD_VALUE;
240
241	// nothing for now
242
243	return B_OK;
244}
245
246// GetShareStatistics
247status_t
248StatisticsManager::GetShareStatistics(Share* share, BMessage* statistics)
249{
250	if (!share)
251		return B_BAD_VALUE;
252
253	return GetShareStatistics(share->GetName(), statistics);
254}
255
256// GetShareStatistics
257status_t
258StatisticsManager::GetShareStatistics(const char* share, BMessage* _statistics)
259{
260	if (!share || !_statistics)
261		return B_BAD_VALUE;
262
263	AutoLocker<Locker> locker(fLock);
264
265	// get the statistics
266	ShareStatistics* statistics = fShareStatistics->Get(share);
267	if (!statistics)
268		return B_OK;
269
270	// get the users
271	return statistics->GetStatistics(_statistics);
272}
273
274
275// fManager
276StatisticsManager*	StatisticsManager::fManager = NULL;
277