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
CatchUpAnalyser(const BVolume & volume,time_t start,time_t end,BHandler * manager)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
MessageReceived(BMessage * message)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
StartAnalysing()53 CatchUpAnalyser::StartAnalysing()
54 {
55 PostMessage(kCatchUp);
56 Run();
57 }
58
59
60 void
AnalyseEntry(const entry_ref & ref)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
_CatchUp()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
_WriteSyncSatus(bigtime_t syncTime)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
CatchUpManager(const BVolume & volume)134 CatchUpManager::CatchUpManager(const BVolume& volume)
135 :
136 fVolume(volume)
137 {
138
139 }
140
141
~CatchUpManager()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
MessageReceived(BMessage * message)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
AddAnalyser(const FileAnalyser * analyserOrg)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
RemoveAnalyser(const BString & name)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
CatchUp()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
Stop()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