HaikuDepot: Implemented simple icon-cache.

* In a first round, icons are trying to be loaded
   from the icon cache.
 * In a second round, the cached icons are updated from the
   server, unless the icons files have been modified within
   the last hour. The web-app does support headers for checking
   if the resource has been modified since a certain date, however,
   with hvif being so small and the time it takes to connect to the
   server per individual icon being so relatively long, it doesn't
   seem worth it just yet to optimize for not actually getting the
   icon data in response.
This commit is contained in:
Stephan Aßmus 2014-04-05 23:24:52 +02:00
parent f5ce3e39da
commit 726db742bd
2 changed files with 52 additions and 6 deletions

View File

@ -6,11 +6,18 @@
#include "Model.h" #include "Model.h"
#include <ctime>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <time.h>
#include <Autolock.h> #include <Autolock.h>
#include <Catalog.h> #include <Catalog.h>
#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <File.h>
#include <Path.h>
#include "WebAppInterface.h" #include "WebAppInterface.h"
@ -564,13 +571,14 @@ int32
Model::_PopulateAllPackagesEntry(void* cookie) Model::_PopulateAllPackagesEntry(void* cookie)
{ {
Model* model = static_cast<Model*>(cookie); Model* model = static_cast<Model*>(cookie);
model->_PopulateAllPackagesThread(); model->_PopulateAllPackagesThread(true);
model->_PopulateAllPackagesThread(false);
return 0; return 0;
} }
void void
Model::_PopulateAllPackagesThread() Model::_PopulateAllPackagesThread(bool fromCacheOnly)
{ {
int32 depotIndex = 0; int32 depotIndex = 0;
int32 packageIndex = 0; int32 packageIndex = 0;
@ -601,7 +609,7 @@ Model::_PopulateAllPackagesThread()
if (package.Get() == NULL) if (package.Get() == NULL)
continue; continue;
_PopulatePackageIcon(package); _PopulatePackageIcon(package, fromCacheOnly);
// TODO: Average user rating. It needs to be shown in the // TODO: Average user rating. It needs to be shown in the
// list view, so without the user clicking the package. // list view, so without the user clicking the package.
} }
@ -609,8 +617,41 @@ Model::_PopulateAllPackagesThread()
void void
Model::_PopulatePackageIcon(const PackageInfoRef& package) Model::_PopulatePackageIcon(const PackageInfoRef& package, bool fromCacheOnly)
{ {
// See if there is a cached icon file
BFile iconFile;
BPath iconCachePath;
bool fileExists = false;
BString iconName(package->Title());
iconName << ".hvif";
time_t modifiedTime;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &iconCachePath) == B_OK
&& iconCachePath.Append("HaikuDepot/IconCache") == B_OK
&& create_directory(iconCachePath.Path(), 0777) == B_OK
&& iconCachePath.Append(iconName) == B_OK) {
// Try opening the file in read-only mode, which will fail if its
// not a file or does not exist.
fileExists = iconFile.SetTo(iconCachePath.Path(), B_READ_ONLY) == B_OK;
if (fileExists)
iconFile.GetModificationTime(&modifiedTime);
}
if (fileExists) {
time_t now;
time(&now);
if (fromCacheOnly || now - modifiedTime < 60 * 60) {
// Cache file is recent enough, just use it and return.
BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(iconFile), true);
package->SetIcon(bitmapRef);
return;
}
}
if (fromCacheOnly)
return;
// Retrieve icon from web-app
WebAppInterface interface; WebAppInterface interface;
BMallocIO buffer; BMallocIO buffer;
@ -618,5 +659,9 @@ Model::_PopulatePackageIcon(const PackageInfoRef& package)
if (status == B_OK) { if (status == B_OK) {
BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(buffer), true); BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(buffer), true);
package->SetIcon(bitmapRef); package->SetIcon(bitmapRef);
if (iconFile.SetTo(iconCachePath.Path(),
B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) == B_OK) {
iconFile.Write(buffer.Buffer(), buffer.BufferLength());
}
} }
} }

View File

@ -91,10 +91,11 @@ public:
private: private:
static int32 _PopulateAllPackagesEntry(void* cookie); static int32 _PopulateAllPackagesEntry(void* cookie);
void _PopulateAllPackagesThread(); void _PopulateAllPackagesThread(bool fromCacheOnly);
void _PopulatePackageIcon( void _PopulatePackageIcon(
const PackageInfoRef& package); const PackageInfoRef& package,
bool fromCacheOnly);
private: private:
BLocker fLock; BLocker fLock;