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 19const uint32 kCatchUp = '&CaU'; 20const uint32 kCatchUpDone = '&CUD'; 21 22const bigtime_t kSecond = 1000000; 23 24 25CatchUpAnalyser::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 38void 39CatchUpAnalyser::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 52void 53CatchUpAnalyser::StartAnalysing() 54{ 55 PostMessage(kCatchUp); 56 Run(); 57} 58 59 60void 61CatchUpAnalyser::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 73void 74CatchUpAnalyser::_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 121void 122CatchUpAnalyser::_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 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