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 host->AddHandler(result); 63 } 64 result->Run(); 65 return result; 66 } 67 68 69 NodePreloader::NodePreloader(const char* name) 70 : BHandler(name), 71 fModelList(20, true), 72 fQuitRequested(false) 73 { 74 } 75 76 77 NodePreloader::~NodePreloader() 78 { 79 // block deletion while we are locked 80 fQuitRequested = true; 81 fLock.Lock(); 82 } 83 84 85 void 86 NodePreloader::Run() 87 { 88 fLock.Lock(); 89 Thread::Launch(NewMemberFunctionObject(&NodePreloader::Preload, this)); 90 } 91 92 93 Model* 94 NodePreloader::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 105 void 106 NodePreloader::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 157 void 158 NodePreloader::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 195 void 196 NodePreloader::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