blob: 0b3972f4181f89fd32c1aca99cc3ba00c6529bce [file] [log] [blame]
/*
* Copyright 2010 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: jmarantz@google.com (Joshua Marantz)
#ifndef PAGESPEED_KERNEL_BASE_STATISTICS_TEMPLATE_H_
#define PAGESPEED_KERNEL_BASE_STATISTICS_TEMPLATE_H_
#include <algorithm>
#include <cstddef>
#include <map>
#include <vector>
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/stl_util.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/writer.h"
namespace net_instaweb {
class MessageHandler;
// This class makes it easier to define new Statistics implementations
// by providing a templatized implementation of variable registration and
// management.
template<class Var, class Hist, class TimedVar> class StatisticsTemplate
: public Statistics {
public:
StatisticsTemplate() {}
virtual ~StatisticsTemplate() {
STLDeleteContainerPointers(variables_.begin(), variables_.end());
STLDeleteContainerPointers(histograms_.begin(), histograms_.end());
STLDeleteContainerPointers(timed_vars_.begin(), timed_vars_.end());
}
// Implementations of Statistics API --- see base class docs for
// description.
virtual Var* AddVariable(const StringPiece& name) {
Var* var = FindVariable(name);
if (var == NULL) {
var = NewVariable(name, variables_.size());
variables_.push_back(var);
variable_names_.push_back(name.as_string());
variable_map_[name.as_string()] = var;
}
return var;
}
virtual Var* AddGlobalVariable(const StringPiece& name) {
Var* var = FindVariable(name);
if (var == NULL) {
var = NewGlobalVariable(name, variables_.size());
variables_.push_back(var);
variable_names_.push_back(name.as_string());
variable_map_[name.as_string()] = var;
}
return var;
}
virtual Var* FindVariable(const StringPiece& name) const {
typename VarMap::const_iterator p = variable_map_.find(name.as_string());
Var* var = NULL;
if (p != variable_map_.end()) {
var = p->second;
}
return var;
}
virtual Hist* AddHistogram(const StringPiece& name) {
Hist* hist = FindHistogram(name);
if (hist == NULL) {
hist = NewHistogram(name);
histograms_.push_back(hist);
histogram_names_.push_back(name.as_string());
histogram_map_[name.as_string()] = hist;
}
return hist;
}
virtual Hist* FindHistogram(const StringPiece& name) const {
typename HistMap::const_iterator p = histogram_map_.find(name.as_string());
Hist* hist = NULL;
if (p != histogram_map_.end()) {
hist = p->second;
}
return hist;
}
virtual TimedVar* AddTimedVariable(const StringPiece& name,
const StringPiece& group) {
TimedVar* timedvar = FindTimedVariable(name);
if (timedvar == NULL) {
timedvar = NewTimedVariable(name, timed_vars_.size());
timed_vars_.push_back(timedvar);
timed_var_map_[name.as_string()] = timedvar;
timed_var_group_map_[group.as_string()].push_back(name.as_string());
}
return timedvar;
}
virtual TimedVar* FindTimedVariable(const StringPiece& name) const {
typename TimedVarMap::const_iterator p =
timed_var_map_.find(name.as_string());
TimedVar* timedvar = NULL;
if (p != timed_var_map_.end()) {
timedvar = p->second;
}
return timedvar;
}
virtual const StringVector& HistogramNames() {
return histogram_names_;
}
virtual const std::map<GoogleString, StringVector>& TimedVariableMap() {
return timed_var_group_map_;
}
virtual void Dump(Writer* writer, MessageHandler* message_handler) {
int longest_string = 0;
for (int i = 0, n = variables_.size(); i < n; ++i) {
const GoogleString& var_name = variable_names_[i];
int length_number = Integer64ToString(variables_[i]->Get()).size();
int length_name = var_name.size();
longest_string = std::max(longest_string, length_name + length_number);
}
GoogleString spaces_buffer = GoogleString(longest_string, ' ');
StringPiece spaces(spaces_buffer);
for (int i = 0, n = variables_.size(); i < n; ++i) {
const GoogleString& var_name = variable_names_[i];
GoogleString var_as_str = Integer64ToString(variables_[i]->Get());
writer->Write(var_name, message_handler);
writer->Write(": ", message_handler);
int num_spaces = longest_string - var_name.size() - var_as_str.size();
writer->Write(spaces.substr(0, num_spaces), message_handler);
writer->Write(var_as_str, message_handler);
writer->Write("\n", message_handler);
}
}
virtual void Clear() {
for (int i = 0, n = variables_.size(); i < n; ++i) {
Variable* var = variables_[i];
var->Clear();
}
for (int i = 0, n = histograms_.size(); i < n; ++i) {
Histogram* hist = histograms_[i];
hist->Clear();
}
for (int i = 0, n = timed_vars_.size(); i < n; ++i) {
TimedVariable* timedvar = timed_vars_[i];
timedvar->Clear();
}
}
protected:
// Interface to subclass.
virtual Var* NewVariable(const StringPiece& name, int index) = 0;
// Default implementation just calls NewVariable
virtual Var* NewGlobalVariable(const StringPiece& name, int index) {
return NewVariable(name, index);
}
virtual Hist* NewHistogram(const StringPiece& name) = 0;
virtual TimedVar* NewTimedVariable(const StringPiece& name, int index) = 0;
size_t variables_size() const { return variables_.size(); }
Var* variables(size_t pos) { return variables_.at(pos); }
size_t histograms_size() const { return histograms_.size(); }
Hist* histograms(size_t pos) { return histograms_.at(pos); }
const GoogleString& histogram_names(size_t pos) const {
return histogram_names_.at(pos);
}
private:
typedef std::vector<Var*> VarVector;
typedef std::map<GoogleString, Var*> VarMap;
typedef std::vector<Hist*> HistVector;
typedef std::map<GoogleString, Hist*> HistMap;
typedef std::vector<TimedVar*> TimedVarVector;
typedef std::map<GoogleString, TimedVar*> TimedVarMap;
VarVector variables_;
VarMap variable_map_;
HistVector histograms_;
HistMap histogram_map_;
TimedVarVector timed_vars_;
TimedVarMap timed_var_map_;
// map between group and names of stats.
std::map<GoogleString, StringVector> timed_var_group_map_;
StringVector variable_names_;
StringVector histogram_names_;
DISALLOW_COPY_AND_ASSIGN(StatisticsTemplate);
};
// A specialization of StatisticsTemplate for implementations that can only
// do scalar statistics variables.
template<class Var>
class ScalarStatisticsTemplate
: public StatisticsTemplate<Var, CountHistogram, FakeTimedVariable> {
public:
ScalarStatisticsTemplate() {}
virtual ~ScalarStatisticsTemplate() {}
protected:
virtual CountHistogram* NewHistogram(const StringPiece& name) {
return new CountHistogram;
}
virtual FakeTimedVariable* NewTimedVariable(const StringPiece& name,
int index) {
return this->NewFakeTimedVariable(name, index);
}
};
} // namespace net_instaweb
#endif // PAGESPEED_KERNEL_BASE_STATISTICS_TEMPLATE_H_