| 675 | } |
| 676 | |
| 677 | Result Get(HCache cache, const char* uri, const char* etag, FILE** file, uint32_t* file_size, uint64_t* checksum, |
| 678 | uint32_t* range_start, uint32_t* range_end, uint32_t* document_size) |
| 679 | { |
| 680 | dmMutex::ScopedLock lock(cache->m_Mutex); |
| 681 | |
| 682 | HashState64 hash_state; |
| 683 | dmHashInit64(&hash_state, false); |
| 684 | dmHashUpdateBuffer64(&hash_state, uri, strlen(uri)); |
| 685 | dmHashUpdateBuffer64(&hash_state, etag, strlen(etag)); |
| 686 | uint64_t identifier_hash = dmHashFinal64(&hash_state); |
| 687 | |
| 688 | uint64_t uri_hash = dmHashString64(uri); |
| 689 | Entry* entry = cache->m_CacheTable.Get(uri_hash); |
| 690 | if (entry != 0 && entry->m_Info.m_IdentifierHash == identifier_hash) |
| 691 | { |
| 692 | if (entry->m_WriteLock) |
| 693 | { |
| 694 | dmLogWarning("Cache entry locked."); |
| 695 | return RESULT_LOCKED; |
| 696 | } |
| 697 | |
| 698 | entry->m_Info.m_LastAccessed = dmTime::GetTime(); |
| 699 | |
| 700 | char path[DMPATH_MAX_PATH]; |
| 701 | ContentFilePath(cache, identifier_hash, path, sizeof(path)); |
| 702 | FILE* f = fopen(path, "rb"); |
| 703 | if (f) |
| 704 | { |
| 705 | if (file_size) |
| 706 | { |
| 707 | fseek(f, 0L, SEEK_END); |
| 708 | *file_size = ftell(f); |
| 709 | fseek(f, 0L, SEEK_SET); |
| 710 | } |
| 711 | |
| 712 | *file = f; |
| 713 | entry->m_ReadLockCount++; |
| 714 | *checksum = entry->m_Info.m_Checksum; |
| 715 | |
| 716 | *range_start = entry->m_Info.m_RangeStart; |
| 717 | *range_end = entry->m_Info.m_RangeEnd; |
| 718 | *document_size = entry->m_Info.m_DocumentSize; |
| 719 | |
| 720 | return RESULT_OK; |
| 721 | } |
| 722 | else |
| 723 | { |
| 724 | dmLogError("Unable to open %s", path); |
| 725 | // Remove invalid cache entry |
| 726 | cache->m_CacheTable.Erase(uri_hash); |
| 727 | return RESULT_NO_ENTRY; |
| 728 | } |
| 729 | } |
| 730 | |
| 731 | return RESULT_NO_ENTRY; |
| 732 | } |
| 733 | |
| 734 | Result SetVerified(HCache cache, const char* uri, bool verified) |