1139823Simp/*
21541Srgrimes * Copyright 2010, Haiku.
31541Srgrimes * Distributed under the terms of the MIT License.
41541Srgrimes *
51541Srgrimes * Authors:
61541Srgrimes *		Clemens Zeidler <haiku@clemens-zeidler.de>
71541Srgrimes */
81541Srgrimes
91541Srgrimes#include "CatchUpManager.h"
101541Srgrimes
111541Srgrimes#include <vector>
121541Srgrimes
131541Srgrimes#include <Debug.h>
141541Srgrimes#include <Query.h>
151541Srgrimes
161541Srgrimes#include "IndexServer.h"
171541Srgrimes
181541Srgrimes
191541Srgrimesconst uint32 kCatchUp = '&CaU';
201541Srgrimesconst uint32 kCatchUpDone = '&CUD';
211541Srgrimes
221541Srgrimesconst bigtime_t kSecond = 1000000;
231541Srgrimes
241541Srgrimes
251541SrgrimesCatchUpAnalyser::CatchUpAnalyser(const BVolume& volume, time_t start,
261541Srgrimes	time_t end, BHandler* manager)
271541Srgrimes	:
281541Srgrimes	AnalyserDispatcher("CatchUpAnalyser"),
291541Srgrimes	fVolume(volume),
301541Srgrimes	fStart(start),
311541Srgrimes	fEnd(end),
3222521Sdyson	fCatchUpManager(manager)
3350477Speter{
341541Srgrimes
351541Srgrimes}
3683651Speter
3783651Speter
3822521Sdysonvoid
39214048SrmacklemCatchUpAnalyser::MessageReceived(BMessage *message)
40214048Srmacklem{
41214048Srmacklem	switch (message->what) {
42214048Srmacklem		case kCatchUp:
43184588Sdfr			_CatchUp();
44184588Sdfr		break;
45184588Sdfr
46184588Sdfr		default:
47184588Sdfr			BLooper::MessageReceived(message);
481541Srgrimes	}
491541Srgrimes}
501541Srgrimes
511541Srgrimes
521541Srgrimesvoid
531541SrgrimesCatchUpAnalyser::StartAnalysing()
54214048Srmacklem{
551541Srgrimes	PostMessage(kCatchUp);
56122698Salfred	Run();
579336Sdfr}
581541Srgrimes
591541Srgrimes
601541Srgrimesvoid
6128270SwollmanCatchUpAnalyser::AnalyseEntry(const entry_ref& ref)
621541Srgrimes{
631541Srgrimes	for (int i = 0; i < fFileAnalyserList.CountItems(); i++) {
641541Srgrimes		FileAnalyser* analyser = fFileAnalyserList.ItemAt(i);
659336Sdfr		const analyser_settings& settings = analyser->CachedSettings();
661541Srgrimes		if (settings.syncPosition / kSecond >= fStart
67147280Sgreen			&& settings.watchingStart / kSecond <= fEnd)
6836176Speter			analyser->AnalyseEntry(ref);
6936176Speter	}
7036176Speter}
7136176Speter
729336Sdfr
7360938Sjakevoid
7419449SdfrCatchUpAnalyser::_CatchUp()
7519449Sdfr{
7619449Sdfr	STRACE("_CatchUp start %i, end %i\n", (int)fStart, (int)fEnd);
7736473Speter	for (int i = 0; i < fFileAnalyserList.CountItems(); i++)
78122953Salfred		STRACE("- Analyser %s\n", fFileAnalyserList.ItemAt(i)->Name().String());
79131691Salfred
80131691Salfred	BQuery query;
81184588Sdfr	query.SetVolume(&fVolume);
82184588Sdfr	query.PushAttr("last_modified");
83184588Sdfr	query.PushInt32(fStart);
84184588Sdfr	query.PushOp(B_GE);
85184588Sdfr	query.PushAttr("last_modified");
86230547Sjhb	query.PushInt32(fEnd);
87202767Srmacklem	query.PushOp(B_LE);
88122698Salfred	query.PushOp(B_AND);
89122698Salfred
90122698Salfred	query.Fetch();
91122698Salfred
92122698Salfred	std::vector<entry_ref> entryList;
93122698Salfred	entry_ref ref;
941541Srgrimes	while (query.GetNextRef(&ref) == B_OK)
951541Srgrimes		entryList.push_back(ref);
96214048Srmacklem
97214048Srmacklem	printf("CatchUpAnalyser:: entryList.size() %i\n", (int)entryList.size());
98214048Srmacklem
99214048Srmacklem	if (entryList.size() == 0)
100214048Srmacklem		return;
101214048Srmacklem
102214048Srmacklem	for (uint32 i = 0; i < entryList.size(); i++) {
103214048Srmacklem		if (Stopped())
104216931Srmacklem			return;
105214048Srmacklem		if (i % 100 == 0)
10655206Speter			printf("Catch up: %i/%i\n", (int)i,(int)entryList.size());
1071541Srgrimes		AnalyseEntry(entryList[i]);
1081541Srgrimes	}
1091541Srgrimes	LastEntry();
1101541Srgrimes
11119449Sdfr	_WriteSyncSatus(fEnd * kSecond);
112131691Salfred	printf("Catched up.\n");
113131691Salfred
11455206Speter	BMessenger managerMessenger(fCatchUpManager);
1151541Srgrimes	BMessage msg(kCatchUpDone);
116131691Salfred	msg.AddPointer("Analyser", this);
117131691Salfred	managerMessenger.SendMessage(&msg);
1182175Spaul}
119131691Salfred
120230547Sjhb
121230547Sjhbvoid
122230547SjhbCatchUpAnalyser::_WriteSyncSatus(bigtime_t syncTime)
123230547Sjhb{
124202767Srmacklem	for (int i = 0; i < fFileAnalyserList.CountItems(); i++) {
125202767Srmacklem		AnalyserSettings* settings = fFileAnalyserList.ItemAt(i)->Settings();
126202767Srmacklem		ASSERT(settings);
127202767Srmacklem		settings->SetSyncPosition(syncTime);
128131691Salfred		settings->WriteSettings();
129131691Salfred	}
130131691Salfred
131}
132
133
134CatchUpManager::CatchUpManager(const BVolume& volume)
135	:
136	fVolume(volume)
137{
138
139}
140
141
142CatchUpManager::~CatchUpManager()
143{
144	Stop();
145
146	for (int i = 0; i < fFileAnalyserQueue.CountItems(); i++)
147		delete fFileAnalyserQueue.ItemAt(i);
148}
149
150
151void
152CatchUpManager::MessageReceived(BMessage *message)
153{
154	CatchUpAnalyser* analyser;
155	switch (message->what) {
156		case kCatchUpDone:
157			message->GetPointer("Analyser", &analyser);
158			fCatchUpAnalyserList.RemoveItem(analyser);
159			analyser->PostMessage(B_QUIT_REQUESTED);
160		break;
161
162		default:
163			BHandler::MessageReceived(message);
164	}
165}
166
167
168bool
169CatchUpManager::AddAnalyser(const FileAnalyser* analyserOrg)
170{
171	IndexServer* server = (IndexServer*)be_app;
172	FileAnalyser* analyser = server->CreateFileAnalyser(analyserOrg->Name(),
173		fVolume);
174	if (!analyser)
175		return false;
176	ASSERT(analyserOrg->Settings());
177	analyser->SetSettings(analyserOrg->Settings());
178
179	bool status = fFileAnalyserQueue.AddItem(analyser);
180	if (!status)
181		delete analyser;
182	return status;
183}
184
185
186void
187CatchUpManager::RemoveAnalyser(const BString& name)
188{
189	for (int i = 0; i < fFileAnalyserQueue.CountItems(); i++) {
190		FileAnalyser* analyser = fFileAnalyserQueue.ItemAt(i);
191		if (analyser->Name() == name) {
192			fFileAnalyserQueue.RemoveItem(analyser);
193			delete analyser;
194		}
195	}
196
197	for (int i = 0; i < fCatchUpAnalyserList.CountItems(); i++)
198		fCatchUpAnalyserList.ItemAt(i)->RemoveAnalyser(name);
199}
200
201
202bool
203CatchUpManager::CatchUp()
204{
205	STRACE("CatchUpManager::CatchUp()\n");
206	bigtime_t startBig = real_time_clock_usecs();
207	bigtime_t endBig = 0;
208	for (int i = 0; i < fFileAnalyserQueue.CountItems(); i++) {
209		FileAnalyser* analyser = fFileAnalyserQueue.ItemAt(i);
210 		analyser->UpdateSettingsCache();
211		const analyser_settings& settings = analyser->CachedSettings();
212		STRACE("%s, %i, %i\n", analyser->Name().String(),
213			  (int)settings.syncPosition, (int)settings.watchingStart);
214		if (settings.syncPosition < startBig)
215			startBig = settings.syncPosition;
216		if (settings.watchingStart > endBig)
217			endBig = settings.watchingStart;
218	}
219
220	CatchUpAnalyser* catchUpAnalyser = new CatchUpAnalyser(fVolume,
221		startBig / kSecond, endBig / kSecond, this);
222	if (!catchUpAnalyser)
223		return false;
224	if (!fCatchUpAnalyserList.AddItem(catchUpAnalyser)) {
225		delete catchUpAnalyser;
226		return false;
227	}
228
229	for (int i = 0; i < fFileAnalyserQueue.CountItems(); i++) {
230		FileAnalyser* analyser = fFileAnalyserQueue.ItemAt(i);
231		// if AddAnalyser fails at least don't leak
232		if (!catchUpAnalyser->AddAnalyser(analyser))
233			delete analyser;
234
235	}
236	fFileAnalyserQueue.MakeEmpty();
237
238	catchUpAnalyser->StartAnalysing();
239	return true;
240}
241
242
243void
244CatchUpManager::Stop()
245{
246	for (int i = 0; i < fCatchUpAnalyserList.CountItems(); i++) {
247		CatchUpAnalyser* catchUpAnalyser = fCatchUpAnalyserList.ItemAt(i);
248		catchUpAnalyser->Stop();
249		catchUpAnalyser->PostMessage(B_QUIT_REQUESTED);
250	}
251	fCatchUpAnalyserList.MakeEmpty();
252}
253