1/* 2Open Tracker License 3 4Terms and Conditions 5 6Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8Permission is hereby granted, free of charge, to any person obtaining a copy of 9this software and associated documentation files (the "Software"), to deal in 10the Software without restriction, including without limitation the rights to 11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12of the Software, and to permit persons to whom the Software is furnished to do 13so, subject to the following conditions: 14 15The above copyright notice and this permission notice applies to all licensees 16and shall be included in all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25Except as contained in this notice, the name of Be Incorporated shall not be 26used in advertising or otherwise to promote the sale, use or other dealings in 27this Software without prior written authorization from Be Incorporated. 28 29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30of Be Incorporated in the United States and other countries. Other brand product 31names are registered trademarks or trademarks of their respective holders. 32All rights reserved. 33*/ 34 35// NodePreloader manages caching up icons from apps and prefs folder for 36// fast display 37// 38 39#include <Debug.h> 40#include <Directory.h> 41#include <Entry.h> 42#include <FindDirectory.h> 43#include <Node.h> 44#include <NodeMonitor.h> 45#include <Path.h> 46 47#include "AutoLock.h" 48#include "IconCache.h" 49#include "NodePreloader.h" 50#include "Thread.h" 51#include "Tracker.h" 52 53 54NodePreloader* 55NodePreloader::InstallNodePreloader(const char* name, BLooper* host) 56{ 57 NodePreloader* result = new NodePreloader(name); 58 { 59 AutoLock<BLooper> lock(host); 60 if (!lock) 61 return NULL; 62 host->AddHandler(result); 63 } 64 result->Run(); 65 return result; 66} 67 68 69NodePreloader::NodePreloader(const char* name) 70 : BHandler(name), 71 fModelList(20, true), 72 fQuitRequested(false) 73{ 74} 75 76 77NodePreloader::~NodePreloader() 78{ 79 // block deletion while we are locked 80 fQuitRequested = true; 81 fLock.Lock(); 82} 83 84 85void 86NodePreloader::Run() 87{ 88 fLock.Lock(); 89 Thread::Launch(NewMemberFunctionObject(&NodePreloader::Preload, this)); 90} 91 92 93Model* 94NodePreloader::FindModel(node_ref itemNode) const 95{ 96 for (int32 count = fModelList.CountItems() - 1; count >= 0; count--) { 97 Model* model = fModelList.ItemAt(count); 98 if (*model->NodeRef() == itemNode) 99 return model; 100 } 101 return NULL; 102} 103 104 105void 106NodePreloader::MessageReceived(BMessage* message) 107{ 108 // respond to node monitor notifications 109 110 node_ref itemNode; 111 switch (message->what) { 112 case B_NODE_MONITOR: 113 { 114 switch (message->FindInt32("opcode")) { 115 case B_ENTRY_REMOVED: 116 { 117 AutoLock<Benaphore> locker(fLock); 118 message->FindInt32("device", &itemNode.device); 119 message->FindInt64("node", &itemNode.node); 120 Model* model = FindModel(itemNode); 121 if (!model) 122 break; 123 //PRINT(("preloader removing file %s\n", model->Name())); 124 IconCache::sIconCache->Removing(model); 125 fModelList.RemoveItem(model); 126 break; 127 } 128 129 case B_ATTR_CHANGED: 130 case B_STAT_CHANGED: 131 { 132 AutoLock<Benaphore> locker(fLock); 133 message->FindInt32("device", &itemNode.device); 134 message->FindInt64("node", &itemNode.node); 135 136 const char* attrName; 137 message->FindString("attr", &attrName); 138 Model* model = FindModel(itemNode); 139 if (!model) 140 break; 141 BModelOpener opener(model); 142 IconCache::sIconCache->IconChanged(model->ResolveIfLink()); 143 //PRINT(("preloader updating file %s\n", model->Name())); 144 break; 145 } 146 } 147 break; 148 } 149 150 default: 151 _inherited::MessageReceived(message); 152 break; 153 } 154} 155 156 157void 158NodePreloader::PreloadOne(const char* dirPath) 159{ 160 //PRINT(("preloading directory %s\n", dirPath)); 161 BDirectory dir(dirPath); 162 if (!dir.InitCheck() == B_OK) 163 return; 164 165 node_ref nodeRef; 166 dir.GetNodeRef(&nodeRef); 167 168 // have to node monitor the whole directory 169 TTracker::WatchNode(&nodeRef, B_WATCH_DIRECTORY, this); 170 171 dir.Rewind(); 172 for (;;) { 173 entry_ref ref; 174 if (dir.GetNextRef(&ref) != B_OK) 175 break; 176 177 BEntry entry(&ref); 178 if (!entry.IsFile()) 179 // only interrested in files 180 continue; 181 182 Model* model = new Model(&ref, true); 183 if (model->InitCheck() == B_OK && model->IconFrom() == kUnknownSource) { 184 TTracker::WatchNode(model->NodeRef(), B_WATCH_STAT 185 | B_WATCH_ATTR, this); 186 IconCache::sIconCache->Preload(model, kNormalIcon, B_MINI_ICON, true); 187 fModelList.AddItem(model); 188 model->CloseNode(); 189 } else 190 delete model; 191 } 192} 193 194 195void 196NodePreloader::Preload() 197{ 198 for (int32 count = 100; count >= 0; count--) { 199 // wait for a little bit before going ahead to reduce disk access contention 200 snooze(100000); 201 if (fQuitRequested) { 202 fLock.Unlock(); 203 return; 204 } 205 } 206 207 BMessenger messenger(kTrackerSignature); 208 if (!messenger.IsValid()) { 209 // put out some message here! 210 return; 211 } 212 213 ASSERT(fLock.IsLocked()); 214 BPath path; 215 if (find_directory(B_BEOS_APPS_DIRECTORY, &path) == B_OK) 216 PreloadOne(path.Path()); 217 if (find_directory(B_BEOS_PREFERENCES_DIRECTORY, &path) == B_OK) 218 PreloadOne(path.Path()); 219 220 fLock.Unlock(); 221} 222