xref: /haiku/src/servers/index/CatchUpManager.cpp (revision 7a74a5df454197933bc6e80a542102362ee98703)
1 /*
2  * Copyright 2010, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Clemens Zeidler <haiku@clemens-zeidler.de>
7  */
8 
9 #include "CatchUpManager.h"
10 
11 #include <vector>
12 
13 #include <Debug.h>
14 #include <Query.h>
15 
16 #include "IndexServer.h"
17 
18 
19 const uint32 kCatchUp = '&CaU';
20 const uint32 kCatchUpDone = '&CUD';
21 
22 const bigtime_t kSecond = 1000000;
23 
24 
25 CatchUpAnalyser::CatchUpAnalyser(const BVolume& volume, time_t start,
26 	time_t end, BHandler* manager)
27 	:
28 	AnalyserDispatcher("CatchUpAnalyser"),
29 
30 	fVolume(volume),
31 	fStart(start),
32 	fEnd(end),
33 	fCatchUpManager(manager)
34 {
35 
36 }
37 
38 
39 void
40 CatchUpAnalyser::MessageReceived(BMessage *message)
41 {
42 	switch (message->what) {
43 		case kCatchUp:
44 			_CatchUp();
45 		break;
46 
47 		default:
48 			BLooper::MessageReceived(message);
49 	}
50 }
51 
52 
53 void
54 CatchUpAnalyser::StartAnalysing()
55 {
56 	PostMessage(kCatchUp);
57 	Run();
58 }
59 
60 
61 void
62 CatchUpAnalyser::AnalyseEntry(const entry_ref& ref)
63 {
64 	for (int i = 0; i < fFileAnalyserList.CountItems(); i++) {
65 		FileAnalyser* analyser = fFileAnalyserList.ItemAt(i);
66 		const analyser_settings& settings = analyser->CachedSettings();
67 		if (settings.syncPosition / kSecond >= fStart
68 			&& settings.watchingStart / kSecond <= fEnd)
69 			analyser->AnalyseEntry(ref);
70 	}
71 }
72 
73 
74 void
75 CatchUpAnalyser::_CatchUp()
76 {
77 	STRACE("_CatchUp start %i, end %i\n", (int)fStart, (int)fEnd);
78 	for (int i = 0; i < fFileAnalyserList.CountItems(); i++)
79 		STRACE("- Analyser %s\n", fFileAnalyserList.ItemAt(i)->Name().String());
80 
81 	BQuery query;
82 	query.SetVolume(&fVolume);
83 	query.PushAttr("last_modified");
84 	query.PushInt32(fStart);
85 	query.PushOp(B_GE);
86 	query.PushAttr("last_modified");
87 	query.PushInt32(fEnd);
88 	query.PushOp(B_LE);
89 	query.PushOp(B_AND);
90 
91 	query.Fetch();
92 
93 	std::vector<entry_ref> entryList;
94 	entry_ref ref;
95 	while (query.GetNextRef(&ref) == B_OK)
96 		entryList.push_back(ref);
97 
98 	printf("CatchUpAnalyser:: entryList.size() %i\n", (int)entryList.size());
99 
100 	if (entryList.size() == 0)
101 		return;
102 
103 	for (uint32 i = 0; i < entryList.size(); i++) {
104 		if (Stopped())
105 			return;
106 		if (i % 100 == 0)
107 			printf("Catch up: %i/%i\n", (int)i,(int)entryList.size());
108 		AnalyseEntry(entryList[i]);
109 	}
110 	LastEntry();
111 
112 	_WriteSyncSatus(fEnd * kSecond);
113 	printf("Catched up.\n");
114 
115 	BMessenger managerMessenger(fCatchUpManager);
116 	BMessage msg(kCatchUpDone);
117 	msg.AddPointer("Analyser", this);
118 	managerMessenger.SendMessage(&msg);
119 }
120 
121 
122 void
123 CatchUpAnalyser::_WriteSyncSatus(bigtime_t syncTime)
124 {
125 	for (int i = 0; i < fFileAnalyserList.CountItems(); i++) {
126 		AnalyserSettings* settings = fFileAnalyserList.ItemAt(i)->Settings();
127 		ASSERT(settings);
128 		settings->SetSyncPosition(syncTime);
129 		settings->WriteSettings();
130 	}
131 
132 }
133 
134 
135 CatchUpManager::CatchUpManager(const BVolume& volume)
136 	:
137 	fVolume(volume)
138 {
139 
140 }
141 
142 
143 CatchUpManager::~CatchUpManager()
144 {
145 	Stop();
146 
147 	for (int i = 0; i < fFileAnalyserQueue.CountItems(); i++)
148 		delete fFileAnalyserQueue.ItemAt(i);
149 }
150 
151 
152 void
153 CatchUpManager::MessageReceived(BMessage *message)
154 {
155 	CatchUpAnalyser* analyser;
156 	switch (message->what) {
157 		case kCatchUpDone:
158 			message->AddPointer("Analyser", &analyser);
159 			fCatchUpAnalyserList.RemoveItem(analyser);
160 			analyser->PostMessage(B_QUIT_REQUESTED);
161 		break;
162 
163 		default:
164 			BHandler::MessageReceived(message);
165 	}
166 }
167 
168 
169 bool
170 CatchUpManager::AddAnalyser(const FileAnalyser* analyserOrg)
171 {
172 	IndexServer* server = (IndexServer*)be_app;
173 	FileAnalyser* analyser = server->CreateFileAnalyser(analyserOrg->Name(),
174 		fVolume);
175 	if (!analyser)
176 		return false;
177 	ASSERT(analyserOrg->Settings());
178 	analyser->SetSettings(analyserOrg->Settings());
179 
180 	bool status = fFileAnalyserQueue.AddItem(analyser);
181 	if (!status)
182 		delete analyser;
183 	return status;
184 }
185 
186 
187 void
188 CatchUpManager::RemoveAnalyser(const BString& name)
189 {
190 	for (int i = 0; i < fFileAnalyserQueue.CountItems(); i++) {
191 		FileAnalyser* analyser = fFileAnalyserQueue.ItemAt(i);
192 		if (analyser->Name() == name) {
193 			fFileAnalyserQueue.RemoveItem(analyser);
194 			delete analyser;
195 		}
196 	}
197 
198 	for (int i = 0; i < fCatchUpAnalyserList.CountItems(); i++)
199 		fCatchUpAnalyserList.ItemAt(i)->RemoveAnalyser(name);
200 }
201 
202 
203 bool
204 CatchUpManager::CatchUp()
205 {
206 	STRACE("CatchUpManager::CatchUp()\n");
207 	bigtime_t startBig = real_time_clock_usecs();
208 	bigtime_t endBig = 0;
209 	for (int i = 0; i < fFileAnalyserQueue.CountItems(); i++) {
210 		FileAnalyser* analyser = fFileAnalyserQueue.ItemAt(i);
211  		analyser->UpdateSettingsCache();
212 		const analyser_settings& settings = analyser->CachedSettings();
213 		STRACE("%s, %i, %i\n", analyser->Name().String(),
214 			  (int)settings.syncPosition, (int)settings.watchingStart);
215 		if (settings.syncPosition < startBig)
216 			startBig = settings.syncPosition;
217 		if (settings.watchingStart > endBig)
218 			endBig = settings.watchingStart;
219 	}
220 
221 	CatchUpAnalyser* catchUpAnalyser = new CatchUpAnalyser(fVolume,
222 		startBig / kSecond, endBig / kSecond, this);
223 	if (!catchUpAnalyser)
224 		return false;
225 	if (!fCatchUpAnalyserList.AddItem(catchUpAnalyser)) {
226 		delete catchUpAnalyser;
227 		return false;
228 	}
229 
230 	for (int i = 0; i < fFileAnalyserQueue.CountItems(); i++) {
231 		FileAnalyser* analyser = fFileAnalyserQueue.ItemAt(i);
232 		// if AddAnalyser fails at least don't leak
233 		if (!catchUpAnalyser->AddAnalyser(analyser))
234 			delete analyser;
235 
236 	}
237 	fFileAnalyserQueue.MakeEmpty();
238 
239 	catchUpAnalyser->StartAnalysing();
240 	return true;
241 }
242 
243 
244 void
245 CatchUpManager::Stop()
246 {
247 	for (int i = 0; i < fCatchUpAnalyserList.CountItems(); i++) {
248 		CatchUpAnalyser* catchUpAnalyser = fCatchUpAnalyserList.ItemAt(i);
249 		catchUpAnalyser->Stop();
250 		catchUpAnalyser->PostMessage(B_QUIT_REQUESTED);
251 	}
252 	fCatchUpAnalyserList.MakeEmpty();
253 }
254