aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.txt16
-rw-r--r--linden/indra/llmessage/llassetstorage.cpp41
-rw-r--r--linden/indra/newview/lltexturecache.cpp68
-rw-r--r--linden/indra/newview/lltexturecache.h5
4 files changed, 104 insertions, 26 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 2cc6cca..5564136 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -3,3 +3,19 @@
3 * linden/indra/newview/llviewerjointattachment.h (LLViewerJoint): 3 * linden/indra/newview/llviewerjointattachment.h (LLViewerJoint):
4 VWR-2685: Possible crash in bounding box (getBoundingBoxAgent()) 4 VWR-2685: Possible crash in bounding box (getBoundingBoxAgent())
5 from hud attachments. 5 from hud attachments.
6
72008-09-16 Jacek Antonelli <jacek.antonelli@gmail.com>
8
9 * linden/indra/newview/lltexturecache.cpp (purgeTextureFilesTimeSliced):
10 Skip "N files scheduled for deletion" message when nothing scheduled.
11
122008-09-16 Nicholaz Beresford <nicholaz@blueflash.cc>
13
14 * linden/indra/newview/lltexturecache.cpp:
15 VWR-3878: Purging cache textures causes viewer to pause for many
16 seconds, with heavy disk activity.
17 * linden/indra/newview/lltexturecache.h:
18 Ditto.
19
20 * linden/indra/llmessage/llassetstorage.cpp:
21 VWR-3877: A nasty possible memory overwrite and two minor leaks.
diff --git a/linden/indra/llmessage/llassetstorage.cpp b/linden/indra/llmessage/llassetstorage.cpp
index a6077e5..83026ba 100644
--- a/linden/indra/llmessage/llassetstorage.cpp
+++ b/linden/indra/llmessage/llassetstorage.cpp
@@ -515,16 +515,19 @@ void LLAssetStorage::downloadCompleteCallback(
515 S32 result, 515 S32 result,
516 const LLUUID& file_id, 516 const LLUUID& file_id,
517 LLAssetType::EType file_type, 517 LLAssetType::EType file_type,
518 void* user_data, LLExtStat ext_status) 518 void* callback_parm_req, LLExtStat ext_status)
519{ 519{
520 lldebugs << "LLAssetStorage::downloadCompleteCallback() for " << file_id 520 lldebugs << "LLAssetStorage::downloadCompleteCallback() for " << file_id
521 << "," << LLAssetType::lookup(file_type) << llendl; 521 << "," << LLAssetType::lookup(file_type) << llendl;
522 LLAssetRequest* req = (LLAssetRequest*)user_data; 522
523 // be careful! req may be a ptr to memory already freed (a timeout does this)
524 LLAssetRequest* req = (LLAssetRequest*)callback_parm_req;
523 if(!req) 525 if(!req)
524 { 526 {
525 llwarns << "LLAssetStorage::downloadCompleteCallback called without" 527 llwarns << "LLAssetStorage::downloadCompleteCallback called without"
526 "a valid request." << llendl; 528 "a valid request." << llendl;
527 return; 529 // we can live with a null pointer, we're not allowed to deref the ptr anyway (see above)
530 // return;
528 } 531 }
529 if (!gAssetStorage) 532 if (!gAssetStorage)
530 { 533 {
@@ -532,12 +535,10 @@ void LLAssetStorage::downloadCompleteCallback(
532 return; 535 return;
533 } 536 }
534 537
535 req->setUUID(file_id);
536 req->setType(file_type);
537 if (LL_ERR_NOERR == result) 538 if (LL_ERR_NOERR == result)
538 { 539 {
539 // we might have gotten a zero-size file 540 // we might have gotten a zero-size file
540 LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType()); 541 LLVFile vfile(gAssetStorage->mVFS, file_id, file_type);
541 if (vfile.getSize() <= 0) 542 if (vfile.getSize() <= 0)
542 { 543 {
543 llwarns << "downloadCompleteCallback has non-existent or zero-size asset " << req->getUUID() << llendl; 544 llwarns << "downloadCompleteCallback has non-existent or zero-size asset " << req->getUUID() << llendl;
@@ -556,7 +557,7 @@ void LLAssetStorage::downloadCompleteCallback(
556 { 557 {
557 request_list_t::iterator curiter = iter++; 558 request_list_t::iterator curiter = iter++;
558 LLAssetRequest* tmp = *curiter; 559 LLAssetRequest* tmp = *curiter;
559 if ((tmp->getUUID() == req->getUUID()) && (tmp->getType()== req->getType())) 560 if ((tmp->getUUID() == file_id) && (tmp->getType() == file_type))
560 { 561 {
561 requests.push_front(tmp); 562 requests.push_front(tmp);
562 iter = gAssetStorage->mPendingDownloads.erase(curiter); 563 iter = gAssetStorage->mPendingDownloads.erase(curiter);
@@ -569,7 +570,7 @@ void LLAssetStorage::downloadCompleteCallback(
569 LLAssetRequest* tmp = *curiter; 570 LLAssetRequest* tmp = *curiter;
570 if (tmp->mDownCallback) 571 if (tmp->mDownCallback)
571 { 572 {
572 tmp->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), tmp->mUserData, result, ext_status); 573 tmp->mDownCallback(gAssetStorage->mVFS, tmp->getUUID(), tmp->getType(), tmp->mUserData, result, ext_status);
573 } 574 }
574 delete tmp; 575 delete tmp;
575 } 576 }
@@ -665,10 +666,10 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback(
665 S32 result, 666 S32 result,
666 const LLUUID& file_id, 667 const LLUUID& file_id,
667 LLAssetType::EType file_type, 668 LLAssetType::EType file_type,
668 void* user_data, 669 void* callback_parm_req,
669 LLExtStat ext_status) 670 LLExtStat ext_status)
670{ 671{
671 LLEstateAssetRequest *req = (LLEstateAssetRequest*)user_data; 672 LLEstateAssetRequest *req = (LLEstateAssetRequest*)callback_parm_req;
672 if(!req) 673 if(!req)
673 { 674 {
674 llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called" 675 llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
@@ -682,12 +683,10 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback(
682 return; 683 return;
683 } 684 }
684 685
685 req->setUUID(file_id);
686 req->setType(file_type);
687 if (LL_ERR_NOERR == result) 686 if (LL_ERR_NOERR == result)
688 { 687 {
689 // we might have gotten a zero-size file 688 // we might have gotten a zero-size file
690 LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getAType()); 689 LLVFile vfile(gAssetStorage->mVFS, file_id, file_type);
691 if (vfile.getSize() <= 0) 690 if (vfile.getSize() <= 0)
692 { 691 {
693 llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl; 692 llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl;
@@ -697,7 +696,9 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback(
697 } 696 }
698 } 697 }
699 698
700 req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getAType(), req->mUserData, result, ext_status); 699 req->mDownCallback(gAssetStorage->mVFS, file_id, file_type, req->mUserData, result, ext_status);
700
701 delete req;
701} 702}
702 703
703void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id, 704void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
@@ -802,10 +803,10 @@ void LLAssetStorage::downloadInvItemCompleteCallback(
802 S32 result, 803 S32 result,
803 const LLUUID& file_id, 804 const LLUUID& file_id,
804 LLAssetType::EType file_type, 805 LLAssetType::EType file_type,
805 void* user_data, 806 void* callback_parm_req,
806 LLExtStat ext_status) 807 LLExtStat ext_status)
807{ 808{
808 LLInvItemRequest *req = (LLInvItemRequest*)user_data; 809 LLInvItemRequest *req = (LLInvItemRequest*)callback_parm_req;
809 if(!req) 810 if(!req)
810 { 811 {
811 llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called" 812 llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
@@ -818,12 +819,10 @@ void LLAssetStorage::downloadInvItemCompleteCallback(
818 return; 819 return;
819 } 820 }
820 821
821 req->setUUID(file_id);
822 req->setType(file_type);
823 if (LL_ERR_NOERR == result) 822 if (LL_ERR_NOERR == result)
824 { 823 {
825 // we might have gotten a zero-size file 824 // we might have gotten a zero-size file
826 LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType()); 825 LLVFile vfile(gAssetStorage->mVFS, file_id, file_type);
827 if (vfile.getSize() <= 0) 826 if (vfile.getSize() <= 0)
828 { 827 {
829 llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl; 828 llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl;
@@ -833,7 +832,9 @@ void LLAssetStorage::downloadInvItemCompleteCallback(
833 } 832 }
834 } 833 }
835 834
836 req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), req->mUserData, result, ext_status); 835 req->mDownCallback(gAssetStorage->mVFS, file_id, file_type, req->mUserData, result, ext_status);
836
837 delete req;
837} 838}
838 839
839///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 840/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/linden/indra/newview/lltexturecache.cpp b/linden/indra/newview/lltexturecache.cpp
index 22cb6c1..ac956e2 100644
--- a/linden/indra/newview/lltexturecache.cpp
+++ b/linden/indra/newview/lltexturecache.cpp
@@ -881,6 +881,8 @@ LLTextureCache::LLTextureCache(bool threaded)
881 881
882LLTextureCache::~LLTextureCache() 882LLTextureCache::~LLTextureCache()
883{ 883{
884 purgeTextureFilesTimeSliced(TRUE); // force-flush all pending file deletes
885
884 apr_pool_destroy(mFileAPRPool); 886 apr_pool_destroy(mFileAPRPool);
885} 887}
886 888
@@ -1187,7 +1189,7 @@ void LLTextureCache::purgeTextures(bool validate)
1187 return; 1189 return;
1188 } 1190 }
1189 1191
1190 LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Reading Entries..." << LL_ENDL; 1192 LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Reading " << num_entries << " Entries from " << mTexturesDirEntriesFileName << LL_ENDL;
1191 1193
1192 std::map<LLUUID, S32> entry_idx_map; 1194 std::map<LLUUID, S32> entry_idx_map;
1193 S64 total_size = 0; 1195 S64 total_size = 0;
@@ -1216,7 +1218,7 @@ void LLTextureCache::purgeTextures(bool validate)
1216 LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Validating: " << validate_idx << LL_ENDL; 1218 LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Validating: " << validate_idx << LL_ENDL;
1217 } 1219 }
1218 1220
1219 S64 min_cache_size = (sCacheMaxTexturesSize * 9) / 10; 1221 S64 min_cache_size = sCacheMaxTexturesSize / 100 * 95;
1220 S32 purge_count = 0; 1222 S32 purge_count = 0;
1221 S32 next_idx = 0; 1223 S32 next_idx = 0;
1222 for (S32 idx=0; idx<num_entries; idx++) 1224 for (S32 idx=0; idx<num_entries; idx++)
@@ -1250,8 +1252,8 @@ void LLTextureCache::purgeTextures(bool validate)
1250 if (purge_entry) 1252 if (purge_entry)
1251 { 1253 {
1252 purge_count++; 1254 purge_count++;
1253 LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; 1255 LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL;
1254 ll_apr_file_remove(filename, NULL); 1256 mFilesToDelete.push_back(filename);
1255 total_size -= entries[idx].mSize; 1257 total_size -= entries[idx].mSize;
1256 entries[idx].mSize = 0; 1258 entries[idx].mSize = 0;
1257 } 1259 }
@@ -1266,7 +1268,11 @@ void LLTextureCache::purgeTextures(bool validate)
1266 } 1268 }
1267 num_entries = next_idx; 1269 num_entries = next_idx;
1268 1270
1269 LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Writing Entries: " << num_entries << LL_ENDL; 1271 mTimeLastFileDelete.reset();
1272
1273 LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Writing Entries: "
1274 << num_entries << " (" << num_entries*sizeof(Entry)/1024 << "KB)"
1275 << LL_ENDL;
1270 1276
1271 ll_apr_file_remove(mTexturesDirEntriesFileName, NULL); 1277 ll_apr_file_remove(mTexturesDirEntriesFileName, NULL);
1272 ll_apr_file_write_ex(mTexturesDirEntriesFileName, NULL, 1278 ll_apr_file_write_ex(mTexturesDirEntriesFileName, NULL,
@@ -1289,10 +1295,56 @@ void LLTextureCache::purgeTextures(bool validate)
1289 LL_INFOS("TextureCache") << "TEXTURE CACHE:" 1295 LL_INFOS("TextureCache") << "TEXTURE CACHE:"
1290 << " PURGED: " << purge_count 1296 << " PURGED: " << purge_count
1291 << " ENTRIES: " << num_entries 1297 << " ENTRIES: " << num_entries
1292 << " CACHE SIZE: " << total_size / 1024*1024 << " MB" 1298 << " CACHE SIZE: " << total_size/1024/1024 << " MB"
1293 << llendl; 1299 << llendl;
1294} 1300}
1295 1301
1302
1303void LLTextureCache::purgeTextureFilesTimeSliced(BOOL force_all)
1304{
1305 LLMutexLock lock(&mHeaderMutex);
1306
1307 F32 delay_between_passes = 1.0f; // seconds
1308 F32 max_time_per_pass = 0.1f; // seconds
1309
1310 if (!force_all && mTimeLastFileDelete.getElapsedTimeF32() <= delay_between_passes)
1311 {
1312 return;
1313 }
1314
1315 LLTimer timer;
1316 S32 howmany = 0;
1317
1318 if (mFilesToDelete.size() > 0)
1319 {
1320 llinfos << "TEXTURE CACHE: " << mFilesToDelete.size() << " files scheduled for deletion" << llendl;
1321 }
1322
1323 for (LLTextureCache::filename_list_t::iterator iter = mFilesToDelete.begin(); iter!=mFilesToDelete.end(); )
1324 {
1325 LLTextureCache::filename_list_t::iterator iter2 = iter++;
1326 ll_apr_file_remove(*iter2, NULL);
1327 mFilesToDelete.erase(iter2);
1328 howmany++;
1329
1330 if (!force_all && timer.getElapsedTimeF32() > max_time_per_pass)
1331 {
1332 break;
1333 }
1334 }
1335
1336 if (!mFilesToDelete.empty())
1337 {
1338 llinfos << "TEXTURE CACHE: "<< howmany << " files deleted ("
1339 << mFilesToDelete.size() << " files left for next pass)"
1340 << llendl;
1341 }
1342
1343 mTimeLastFileDelete.reset();
1344}
1345
1346
1347
1296////////////////////////////////////////////////////////////////////////////// 1348//////////////////////////////////////////////////////////////////////////////
1297 1349
1298// call lockWorkers() first! 1350// call lockWorkers() first!
@@ -1462,6 +1514,10 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
1462 purgeTextures(false); 1514 purgeTextures(false);
1463 mDoPurge = FALSE; 1515 mDoPurge = FALSE;
1464 } 1516 }
1517
1518 purgeTextureFilesTimeSliced(); // purge textures from cache in a non-hiccup-way
1519
1520
1465 if (datasize >= TEXTURE_CACHE_ENTRY_SIZE) 1521 if (datasize >= TEXTURE_CACHE_ENTRY_SIZE)
1466 { 1522 {
1467 LLMutexLock lock(&mWorkersMutex); 1523 LLMutexLock lock(&mWorkersMutex);
diff --git a/linden/indra/newview/lltexturecache.h b/linden/indra/newview/lltexturecache.h
index f083dd0..e15a88b 100644
--- a/linden/indra/newview/lltexturecache.h
+++ b/linden/indra/newview/lltexturecache.h
@@ -119,6 +119,7 @@ private:
119 void readHeaderCache(apr_pool_t* poolp = NULL); 119 void readHeaderCache(apr_pool_t* poolp = NULL);
120 void purgeAllTextures(bool purge_directories); 120 void purgeAllTextures(bool purge_directories);
121 void purgeTextures(bool validate); 121 void purgeTextures(bool validate);
122 void purgeTextureFilesTimeSliced(BOOL force_all = FALSE);
122 S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL); 123 S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL);
123 bool removeHeaderCacheEntry(const LLUUID& id); 124 bool removeHeaderCacheEntry(const LLUUID& id);
124 void lockHeaders() { mHeaderMutex.lock(); } 125 void lockHeaders() { mHeaderMutex.lock(); }
@@ -140,6 +141,10 @@ private:
140 141
141 typedef std::vector<std::pair<LLPointer<Responder>, bool> > responder_list_t; 142 typedef std::vector<std::pair<LLPointer<Responder>, bool> > responder_list_t;
142 responder_list_t mCompletedList; 143 responder_list_t mCompletedList;
144
145 typedef std::list<std::string> filename_list_t;
146 filename_list_t mFilesToDelete;
147 LLTimer mTimeLastFileDelete;
143 148
144 BOOL mReadOnly; 149 BOOL mReadOnly;
145 150