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