xref: /haiku/src/servers/index/CatchUpManager.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
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 	fVolume(volume),
30 	fStart(start),
31 	fEnd(end),
32 	fCatchUpManager(manager)
33 {
34 
35 }
36 
37 
38 void
39 CatchUpAnalyser::MessageReceived(BMessage *message)
40 {
41 	switch (message->what) {
42 		case kCatchUp:
43 			_CatchUp();
44 		break;
45 
46 		default:
47 			BLooper::MessageReceived(message);
48 	}
49 }
50 
51 
52 void
53 CatchUpAnalyser::StartAnalysing()
54 {
55 	PostMessage(kCatchUp);
56 	Run();
57 }
58 
59 
60 void
61 CatchUpAnalyser::AnalyseEntry(const entry_ref& ref)
62 {
63 	for (int i = 0; i < fFileAnalyserList.CountItems(); i++) {
64 		FileAnalyser* analyser = fFileAnalyserList.ItemAt(i);
65 		const analyser_settings& settings = analyser->CachedSettings();
66 		if (settings.syncPosition / kSecond >= fStart
67 			&& settings.watchingStart / kSecond <= fEnd)
68 			analyser->AnalyseEntry(ref);
69 	}
70 }
71 
72 
73 void
74 CatchUpAnalyser::_CatchUp()
75 {
76 	STRACE("_CatchUp start %i, end %i\n", (int)fStart, (int)fEnd);
77 	for (int i = 0; i < fFileAnalyserList.CountItems(); i++)
78 		STRACE("- Analyser %s\n", fFileAnalyserList.ItemAt(i)->Name().String());
79 
80 	BQuery query;
81 	query.SetVolume(&fVolume);
82 	query.PushAttr("last_modified");
83 	query.PushInt32(fStart);
84 	query.PushOp(B_GE);
85 	query.PushAttr("last_modified");
86 	query.PushInt32(fEnd);
87 	query.PushOp(B_LE);
88 	query.PushOp(B_AND);
89 
90 	query.Fetch();
91 
92 	std::vector<entry_ref> entryList;
93 	entry_ref ref;
94 	while (query.GetNextRef(&ref) == B_OK)
95 		entryList.push_back(ref);
96 
97 	printf("CatchUpAnalyser:: entryList.size() %i\n", (int)entryList.size());
98 
99 	if (entryList.size() == 0)
100 		return;
101 
102 	for (uint32 i = 0; i < entryList.size(); i++) {
103 		if (Stopped())
104 			return;
105 		if (i % 100 == 0)
106 			printf("Catch up: %i/%i\n", (int)i,(int)entryList.size());
107 		AnalyseEntry(entryList[i]);
108 	}
109 	LastEntry();
110 
111 	_WriteSyncSatus(fEnd * kSecond);
112 	printf("Catched up.\n");
113 
114 	BMessenger managerMessenger(fCatchUpManager);
115 	BMessage msg(kCatchUpDone);
116 	msg.AddPointer("Analyser", this);
117 	managerMessenger.SendMessage(&msg);
118 }
119 
120 
121 void
122 CatchUpAnalyser::_WriteSyncSatus(bigtime_t syncTime)
123 {
124 	for (int i = 0; i < fFileAnalyserList.CountItems(); i++) {
125 		AnalyserSettings* settings = fFileAnalyserList.ItemAt(i)->Settings();
126 		ASSERT(settings);
127 		settings->SetSyncPosition(syncTime);
128 		settings->WriteSettings();
129 	}
130 
131 }
132 
133 
134 CatchUpManager::CatchUpManager(const BVolume& volume)
135 	:
136 	fVolume(volume)
137 {
138 
139 }
140 
141 
142 CatchUpManager::~CatchUpManager()
143 {
144 	Stop();
145 
146 	for (int i = 0; i < fFileAnalyserQueue.CountItems(); i++)
147 		delete fFileAnalyserQueue.ItemAt(i);
148 }
149 
150 
151 void
152 CatchUpManager::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 
168 bool
169 CatchUpManager::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 
186 void
187 CatchUpManager::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 
202 bool
203 CatchUpManager::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 
243 void
244 CatchUpManager::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