blob: 532e421686bd3734d5a0519a0f59880326e914ec [file] [log] [blame]
/*
* Copyright 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Author: morlovich@google.com (Maksim Orlovich)
#include "net/instaweb/rewriter/public/mobilize_cached_finder.h"
#include <map>
#include "base/logging.h"
#include "net/instaweb/rewriter/critical_keys.pb.h"
#include "net/instaweb/rewriter/public/critical_finder_support_util.h"
#include "net/instaweb/rewriter/public/property_cache_util.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "net/instaweb/util/public/property_cache.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
namespace net_instaweb {
const char MobilizeCachedFinder::kMobilizeCachedPropertyName[] =
"mobilize_cached";
const char MobilizeCachedFinder::kMobilizeCachedValidCount[] =
"mobilize_cached_valid_count";
const char MobilizeCachedFinder::kMobilizeCachedExpiredCount[] =
"mobilize_cached_expired_count";
const char MobilizeCachedFinder::kMobilizeCachedNotFoundCount[] =
"mobilize_cached_not_found_count";
const char MobilizeCachedFinder::kMobilizeCachedNoConsensusCount[] =
"mobilize_cached_no_consensus_count";
MobilizeCachedFinder::MobilizeCachedFinder(
const PropertyCache::Cohort* cohort, Statistics* statistics)
: cohort_(cohort) {
mobilize_cached_valid_count_ = statistics->GetTimedVariable(
kMobilizeCachedValidCount);
mobilize_cached_expired_count_ = statistics->GetTimedVariable(
kMobilizeCachedExpiredCount);
mobilize_cached_not_found_count_ = statistics->GetTimedVariable(
kMobilizeCachedNotFoundCount);
mobilize_cached_no_consensus_count_ = statistics->GetTimedVariable(
kMobilizeCachedNoConsensusCount);
}
MobilizeCachedFinder::~MobilizeCachedFinder() {
}
void MobilizeCachedFinder::InitStats(Statistics* statistics) {
statistics->AddTimedVariable(kMobilizeCachedValidCount,
ServerContext::kStatisticsGroup);
statistics->AddTimedVariable(kMobilizeCachedExpiredCount,
ServerContext::kStatisticsGroup);
statistics->AddTimedVariable(kMobilizeCachedNotFoundCount,
ServerContext::kStatisticsGroup);
statistics->AddTimedVariable(kMobilizeCachedNoConsensusCount,
ServerContext::kStatisticsGroup);
}
bool MobilizeCachedFinder::GetMobilizeCachedFromPropertyCache(
RewriteDriver* driver, MobilizeCached* out) {
PropertyCacheDecodeResult result;
// NOTE: if any of these checks fail you probably didn't set up your test
// environment carefully enough. Figuring that out based on test failures
// alone will drive you nuts and take hours out of your life, thus DCHECKs.
DCHECK(driver != NULL);
DCHECK(cohort_ != NULL);
// TODO(morlovich): Uses the wrong page (should be origin_property_page()).
scoped_ptr<CriticalKeys> critical_keys(DecodeFromPropertyCache<CriticalKeys>(
driver, cohort_, kMobilizeCachedPropertyName,
driver->options()->finder_properties_cache_expiration_time_ms(),
&result));
switch (result) {
case kPropertyCacheDecodeNotFound:
mobilize_cached_not_found_count_->IncBy(1);
return false;
case kPropertyCacheDecodeExpired:
mobilize_cached_expired_count_->IncBy(1);
return false;
case kPropertyCacheDecodeParseError:
driver->message_handler()->Message(
kWarning, "Unable to parse Mobilize Cached PropertyValue; "
"url: %s", driver->url());
return false;
case kPropertyCacheDecodeOk:
if (critical_keys.get() == NULL) {
LOG(DFATAL) << "NULL critical_keys with success status of decoding";
return false;
}
break;
}
// Use the critical key framework to aggregate various samples.
StringSet encoded_out;
GetCriticalKeysFromProto(51 /* support_percentage */, *critical_keys,
&encoded_out);
if (encoded_out.size() >= 2) {
LOG(DFATAL)
<< "Two candidates have more than 51% support, that makes no sense!?";
return false;
}
if (encoded_out.size() == 0) {
mobilize_cached_no_consensus_count_->IncBy(1);
return false;
}
// The selected string is the encoded MobilizeCached.
const GoogleString& encoded_result = *encoded_out.begin();
ArrayInputStream input(encoded_result.data(), encoded_result.size());
bool ok = out->ParseFromZeroCopyStream(&input);
if (ok) {
mobilize_cached_valid_count_->IncBy(1);
} else {
driver->message_handler()->Message(
kWarning, "Unable to parse selected MobilizeCached; url: %s",
driver->url());
}
return ok;
}
void MobilizeCachedFinder::UpdateMobilizeCachedInPropertyCache(
const MobilizeCached& new_sample, RewriteDriver* driver) {
// Marshal the new_sample to string.
GoogleString new_sample_encoded;
{
StringOutputStream sstream(&new_sample_encoded);
new_sample.SerializeToZeroCopyStream(&sstream);
}
StringSet new_sample_set;
new_sample_set.insert(new_sample_encoded);
// TODO(morlovich): wrong page (should be origin_property_page()).
WriteCriticalKeysToPropertyCache(
new_sample_set, NULL /* not using nonces */,
100, /* ??? support_interval */
kSkipNonceCheck,
kMobilizeCachedPropertyName,
driver->server_context()->page_property_cache(), cohort_,
driver->property_page(), driver->message_handler(), driver->timer());
}
} // namespace net_instaweb