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