Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Unified Diff: chrome/browser/ui/app_list/search/common/webservice_cache.cc

Issue 49353006: Add caching for apps list search results. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/app_list/search/common/webservice_cache.cc
diff --git a/chrome/browser/ui/app_list/search/common/webservice_cache.cc b/chrome/browser/ui/app_list/search/common/webservice_cache.cc
index 082131268ec5e793a55004902f03cdb5a415a4ae..ff0e15ff5d7a79ce4edbafdb8ee51cdf78326413 100644
--- a/chrome/browser/ui/app_list/search/common/webservice_cache.cc
+++ b/chrome/browser/ui/app_list/search/common/webservice_cache.cc
@@ -4,45 +4,158 @@
#include "chrome/browser/ui/app_list/search/common/webservice_cache.h"
+#include "base/strings/string_number_conversions.h"
#include "base/values.h"
+#include "content/public/browser/browser_context.h"
namespace app_list {
namespace {
-const int kWebserviceCacheMaxSize = 100;
-const int kWebserviceCacheTimeLimitInMinutes = 1;
+const unsigned int kWebserviceCacheMaxSize = 1000;
+const unsigned int kWebserviceCacheTimeLimitInMinutes = 1;
+
+const char kKeyResultTime[] = "time";
+const char kKeyResult[] = "result";
+
+const char kWebstoreQueryPrefix[] = "webstore:";
+const char kPeopleQueryPrefix[] = "people:";
} // namespace
-void WebserviceCache::CacheDeletor::operator()(
- WebserviceCache::Payload& payload) {
- delete payload.second;
+void WebserviceCache::CacheDeletor::operator()(Payload& payload) {
+ delete payload.result;
}
-WebserviceCache::WebserviceCache()
- : cache_(kWebserviceCacheMaxSize) {
+WebserviceCache::WebserviceCache(content::BrowserContext* context)
+ : cache_(Cache::NO_AUTO_EVICT),
+ cache_loaded_(false) {
+ const char kStoreDataFileName[] = "Webservice Search Cache";
+ const base::FilePath data_file =
+ context->GetPath().AppendASCII(kStoreDataFileName);
+ data_store_ = new DictionaryDataStore(data_file);
+ data_store_->Load(base::Bind(&WebserviceCache::OnCacheLoaded, AsWeakPtr()));
}
WebserviceCache::~WebserviceCache() {
}
-const base::DictionaryValue* WebserviceCache::Get(const std::string& query) {
- Cache::iterator iter = cache_.Get(query);
+const CacheResult WebserviceCache::Get(QueryType type,
+ const std::string& query) {
+ std::string typed_query = PrependType(type, query);
+ Cache::iterator iter = cache_.Get(typed_query);
if (iter != cache_.end()) {
- if (base::Time::Now() - iter->second.first <=
+ if (base::Time::Now() - iter->second.time <=
base::TimeDelta::FromMinutes(kWebserviceCacheTimeLimitInMinutes)) {
- return iter->second.second;
+ return std::make_pair(FRESH, iter->second.result);
} else {
- cache_.Erase(iter);
+ return std::make_pair(STALE, iter->second.result);
}
}
- return NULL;
+ return std::make_pair(STALE, static_cast<base::DictionaryValue*>(NULL));
}
-void WebserviceCache::Put(const std::string& query,
+void WebserviceCache::Put(QueryType type,
+ const std::string& query,
scoped_ptr<base::DictionaryValue> result) {
- if (result)
- cache_.Put(query, std::make_pair(base::Time::Now(), result.release()));
+ if (result) {
+ std::string typed_query = PrependType(type, query);
+ Payload payload(base::Time::Now(), result.release());
+
+ cache_.Put(typed_query, payload);
+ // If the cache isn't loaded yet, we're fine with losing queries since
+ // a 1000 entry cache should load really quickly so the chance of a user
+ // already having typed a 3 character search before the cache has loaded is
+ // very unlikely.
+ if (cache_loaded_) {
+ data_store_->cached_dict()->Set(typed_query, DictFromPayload(payload));
+ data_store_->ScheduleWrite();
+ if (cache_.size() > kWebserviceCacheMaxSize)
+ TrimCache();
+ }
+ }
+}
+
+void WebserviceCache::OnCacheLoaded(scoped_ptr<base::DictionaryValue>) {
+ if (!data_store_->cached_dict())
+ return;
+
+ std::vector<std::string> cleanup_keys;
+ for (DictionaryValue::Iterator it(*data_store_->cached_dict());
+ !it.IsAtEnd();
+ it.Advance()) {
+ const base::DictionaryValue* payload_dict;
+ Payload payload;
+ if (!it.value().GetAsDictionary(&payload_dict) ||
+ !payload_dict ||
+ !PayloadFromDict(payload_dict, &payload)) {
+ // In case we don't have a valid payload associated with a given query,
+ // clean up that query from our data store.
+ cleanup_keys.push_back(it.key());
+ continue;
+ }
+ cache_.Put(it.key(), payload);
+ }
+
+ if (!cleanup_keys.empty()) {
+ for (size_t i = 0; i < cleanup_keys.size(); ++i)
+ data_store_->cached_dict()->Remove(cleanup_keys[i], NULL);
+ data_store_->ScheduleWrite();
+ }
+ cache_loaded_ = true;
+}
+
+bool WebserviceCache::PayloadFromDict(const base::DictionaryValue* dict,
+ Payload* payload) {
+ std::string time_string;
+ if (!dict->GetString(kKeyResultTime, &time_string))
+ return false;
+ const base::DictionaryValue* result;
+ if (!dict->GetDictionary(kKeyResult, &result))
+ return false;
+
+ int64 time_val;
+ base::StringToInt64(time_string, &time_val);
+
+ // The result dictionary will be owned by the cache, hence create a copy
+ // instead of returning the original reference. The new dictionary will be
+ // owned by our MRU cache.
+ *payload = Payload(base::Time::FromInternalValue(time_val),
+ result->DeepCopy());
+ return true;
+}
+
+base::DictionaryValue* WebserviceCache::DictFromPayload(
+ const Payload& payload) {
+ base::DictionaryValue* dict = new base::DictionaryValue();
+ dict->SetString(kKeyResultTime, base::Int64ToString(
+ payload.time.ToInternalValue()));
+ // The payload will still keep ownership of it's result dict, hence put a
+ // a copy of the result dictionary here. This dictionary will be owned by
+ // data_store_->cached_dict().
+ dict->Set(kKeyResult, payload.result->DeepCopy());
+
+ return dict;
+}
+
+void WebserviceCache::TrimCache() {
+ for (Cache::size_type i = cache_.size(); i > kWebserviceCacheMaxSize; i--) {
+ Cache::reverse_iterator rbegin = cache_.rbegin();
+ data_store_->cached_dict()->Remove(rbegin->first, NULL);
+ cache_.Erase(rbegin);
+ }
+ data_store_->ScheduleWrite();
+}
+
+std::string WebserviceCache::PrependType(
+ QueryType type, const std::string& query) {
+ switch (type) {
+ case WEBSTORE:
+ return kWebstoreQueryPrefix + query;
+ case PEOPLE:
+ return kPeopleQueryPrefix + query;
+ default:
+ return query;
+ }
}
} // namespace app_list

Powered by Google App Engine
This is Rietveld 408576698