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