Ticket #8912: kyra_resource_parent_cache_v6.diff
File kyra_resource_parent_cache_v6.diff, 8.8 KB (added by , 17 years ago) |
---|
-
resource.h
43 43 44 44 struct ResFileEntry { 45 45 Common::String parent; 46 mutable ResFileEntry *parentEntry; // Cache to avoid lookup by string in the map 47 // No smart invalidation is needed because the map is cleared globally 48 // or expanded but no element is ever removed 46 49 uint32 size; 47 50 48 51 bool preload; … … 129 132 protected: 130 133 void checkFile(const Common::String &file); 131 134 bool isAccessable(const Common::String &file); 135 bool isAccessable(const ResFileEntry *fileEntry); 132 136 133 137 void detectFileTypes(); 138 void detectFileType(const Common::String &filename, ResFileEntry *fileEntry); 134 139 135 140 void initializeLoaders(); 136 141 const ResArchiveLoader *getLoader(ResFileEntry::kType type) const; … … 140 145 LoaderList _loaders; 141 146 ResFileMap _map; 142 147 148 ResFileEntry *getParentEntry(const ResFileEntry *entry) const; 149 ResFileEntry *getParentEntry(const Common::String &filename) const; 150 143 151 typedef Common::List<Common::SharedPtr<CompArchiveLoader> > CompLoaderList; 144 152 typedef CompLoaderList::iterator CompLoaderIterator; 145 153 typedef CompLoaderList::const_iterator CCompLoaderIterator; -
resource.cpp
34 34 35 35 namespace Kyra { 36 36 37 static int sParentCacheHit = 0; 38 static int sParentCacheMiss = 0; 39 37 40 Resource::Resource(KyraEngine_v1 *vm) : _loaders(), _map(), _vm(vm) { 38 41 initializeLoaders(); 39 42 } … … 201 204 // If the old parent is not protected we mark it as not preload anymore, 202 205 // since now no longer all of its embedded files are in the filemap. 203 206 oldParent->_value.preload = false; 204 _map[i->filename]= i->entry;207 iter->_value = i->entry; 205 208 } 206 209 } else { 207 210 // Old parent not found? That's strange... But we just overwrite the old 208 211 // entry. 209 _map[i->filename]= i->entry;212 iter->_value = i->entry; 210 213 } 211 214 } else { 212 215 // The old parent has the same filenames as the new archive, we are sure and overwrite the 213 216 // old file entry, could be afterall that the preload flag of the new archive was 214 217 // just unflagged. 215 _map[i->filename]= i->entry;218 iter->_value = i->entry; 216 219 } 217 220 } 218 221 // 'else' case would mean here overwriting an existing file entry in the map without parent. … … 381 384 Common::SeekableReadStream *parent = getFileStream(iter->_value.parent); 382 385 assert(parent); 383 386 384 ResFile Map::const_iterator parentIter = _map.find(iter->_value.parent);385 const ResArchiveLoader *loader = getLoader(parent Iter->_value.type);387 ResFileEntry* parentEntry = getParentEntry(&iter->_value); 388 const ResArchiveLoader *loader = getLoader(parentEntry->type); 386 389 assert(loader); 387 390 388 391 return loader->loadFileFromArchive(file, parent, iter->_value); … … 395 398 checkFile(file); 396 399 397 400 ResFileMap::const_iterator iter = _map.find(file); 398 while (iter != _map.end()) { 399 if (!iter->_value.parent.empty()) { 400 iter = _map.find(iter->_value.parent); 401 if (iter != _map.end()) { 402 // parent can never be a non archive file 403 if (iter->_value.type == ResFileEntry::kRaw) 404 return false; 405 // not mounted parent means not accessable 406 else if (!iter->_value.mounted) 407 return false; 408 } 409 } else { 410 return true; 401 if (iter == _map.end()) 402 return false; 403 404 return isAccessable(&iter->_value); 405 } 406 407 bool Resource::isAccessable(const ResFileEntry *fileEntry) { 408 assert(fileEntry); 409 410 const ResFileEntry* currentEntry = fileEntry; 411 while (not currentEntry->parent.empty()) { 412 if (currentEntry->parentEntry) { 413 ++sParentCacheHit; 414 currentEntry = currentEntry->parentEntry; 411 415 } 416 else { 417 ++sParentCacheMiss; 418 ResFileMap::iterator it = _map.find(currentEntry->parent); 419 if (it == _map.end()) 420 return false; 421 else 422 currentEntry->parentEntry = &it->_value; 423 } 424 // parent can never be a non archive file 425 if (currentEntry->type == ResFileEntry::kRaw) 426 return false; 427 // not mounted parent means not accessable 428 else if (!currentEntry->mounted) 429 return false; 412 430 } 413 return false; 431 432 return true; 414 433 } 415 434 435 ResFileEntry *Resource::getParentEntry(const ResFileEntry *entry) const { 436 assert(entry); 437 if (entry->parent.empty()) 438 return NULL; 439 else if (entry->parentEntry) { 440 ++sParentCacheHit; 441 //printf ("%d %d %d\n", sParentCacheHit, sParentCacheMiss, sParentCacheHit+sParentCacheMiss); 442 assert(_map.find(entry->parent) != _map.end()); 443 assert(entry->parentEntry == &_map.find(entry->parent)->_value); 444 return entry->parentEntry; 445 } 446 else { 447 ++sParentCacheMiss; 448 ResFileMap::iterator it = _map.find(entry->parent); 449 if (it == _map.end()) 450 return NULL; // If it happens often, the structure maybe deserves a flag to avoid rechecking the map 451 else { 452 entry->parentEntry = &it->_value; 453 return entry->parentEntry; 454 } 455 } 456 } 457 458 ResFileEntry *Resource::getParentEntry(const Common::String &filename) const { 459 ResFileMap::iterator it = _map.find(filename); 460 assert(it != _map.end()); 461 return getParentEntry(&it->_value); 462 } 463 416 464 void Resource::checkFile(const Common::String &file) { 417 465 if (_map.find(file) == _map.end()) { 418 466 CompFileMap::const_iterator iter; 419 467 420 468 if ((iter = _compFiles.find(file)) != _compFiles.end()) { 421 ResFileEntry entry;469 ResFileEntry& entry = _map[file]; 422 470 entry.parent = ""; 471 entry.parentEntry = NULL; 423 472 entry.size = iter->_value.size; 424 473 entry.mounted = false; 425 474 entry.preload = false; 426 475 entry.prot = false; 427 476 entry.type = ResFileEntry::kAutoDetect; 428 477 entry.offset = 0; 429 _map[file] = entry; 430 431 detectFileTypes(); 478 479 detectFileType(file, &entry); 432 480 } else if (Common::File::exists(file)) { 433 481 Common::File temp; 434 482 if (temp.open(file)) { 435 ResFileEntry entry;483 ResFileEntry& entry = _map[file]; 436 484 entry.parent = ""; 485 entry.parentEntry = NULL; 437 486 entry.size = temp.size(); 438 487 entry.mounted = file.compareToIgnoreCase(StaticResource::staticDataFilename()) != 0; 439 488 entry.preload = false; 440 489 entry.prot = false; 441 490 entry.type = ResFileEntry::kAutoDetect; 442 491 entry.offset = 0; 443 _map[file] = entry;444 492 temp.close(); 445 493 446 detectFileType s();494 detectFileType(file, &entry); 447 495 } 448 496 } 449 497 } 450 498 } 451 499 452 void Resource::detectFileTypes() { 453 for (ResFileMap::iterator i = _map.begin(); i != _map.end(); ++i) { 454 if (!isAccessable(i->_key)) 455 continue; 500 void Resource::detectFileType(const Common::String &filename, ResFileEntry *fileEntry) { 501 assert(fileEntry); 502 503 if (!isAccessable(fileEntry)) 504 return; 456 505 457 if (i->_value.type == ResFileEntry::kAutoDetect) {458 459 460 if (!(*l)->checkFilename(i->_key))461 462 463 464 stream = getFileStream(i->_key);506 if (fileEntry->type == ResFileEntry::kAutoDetect) { 507 Common::SeekableReadStream *stream = 0; 508 for (LoaderIterator l = _loaders.begin(); l != _loaders.end(); ++l) { 509 if (!(*l)->checkFilename(filename)) 510 continue; 511 512 if (!stream) 513 stream = getFileStream(filename); 465 514 466 if ((*l)->isLoadable(i->_key, *stream)) { 467 i->_value.type = (*l)->getType(); 468 i->_value.mounted = false; 469 i->_value.preload = false; 470 break; 471 } 515 if ((*l)->isLoadable(filename, *stream)) { 516 fileEntry->type = (*l)->getType(); 517 fileEntry->mounted = false; 518 fileEntry->preload = false; 519 break; 472 520 } 473 delete stream; 474 stream = 0; 521 } 522 delete stream; 523 stream = 0; 475 524 476 if (i->_value.type == ResFileEntry::kAutoDetect) 477 i->_value.type = ResFileEntry::kRaw; 478 } 525 if (fileEntry->type == ResFileEntry::kAutoDetect) 526 fileEntry->type = ResFileEntry::kRaw; 479 527 } 480 528 } 481 529 530 void Resource::detectFileTypes() { 531 for (ResFileMap::iterator i = _map.begin(); i != _map.end(); ++i) 532 detectFileType(i->_key, &i->_value); 533 } 534 482 535 void Resource::tryLoadCompFiles() { 483 536 for (CCompLoaderIterator i = _compLoaders.begin(); i != _compLoaders.end(); ++i) { 484 537 if ((*i)->checkForFiles()) … … 620 673 entry.size = endoffset - startoffset; 621 674 entry.offset = startoffset; 622 675 entry.parent = filename; 676 entry.parentEntry = NULL; 623 677 entry.type = ResFileEntry::kAutoDetect; 624 678 entry.mounted = false; 625 679 entry.prot = false; … … 738 792 for (Common::List<Common::String>::iterator file = filenames.begin(); file != filenames.end(); ++file) { 739 793 ResFileEntry entry; 740 794 entry.parent = filename; 795 entry.parentEntry = NULL; 741 796 entry.type = ResFileEntry::kAutoDetect; 742 797 entry.mounted = false; 743 798 entry.preload = false; … … 807 862 for (uint i = 0; i < entries; ++i) { 808 863 ResFileEntry entry; 809 864 entry.parent = filename; 865 entry.parentEntry = NULL; 810 866 entry.type = ResFileEntry::kAutoDetect; 811 867 entry.mounted = false; 812 868 entry.preload = false;