blob: 25a4e51858c5d54532db2dda195d6e4d70a19f4e [file] [log] [blame]
// Copyright 2010 Google Inc. All Rights Reserved.
//
// 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.
#ifndef NET_INSTAWEB_APACHE_APR_STATISTICS_H_
#define NET_INSTAWEB_APACHE_APR_STATISTICS_H_
#include <string>
#include "net/instaweb/util/public/statistics_template.h"
#include "net/instaweb/util/public/string_util.h"
#include "apr_shm.h"
#include "apr.h"
#include "apr_errno.h"
struct apr_pool_t;
struct apr_global_mutex_t;
namespace net_instaweb {
class Writer;
class MessageHandler;
// An implementation of Statistics using the APR's Shared Memory module,
// apr_shm. These statistics will be shared amongst all processes and threads
// spawned by Apache. Note that we will be obtaining a global mutex for every
// read and write to these variables. Since this may be expensive, it is
// recommended that each thread keep a local cache and infrequently write
// through to this Statistics object. TODO(abliss): actually do this.
//
// Because we must allocate shared memory segments before the module forks off
// its children, all AddVariable calls must be in the post_config hook. Once
// all variables are added, you must call InitVariables.
//
// If a variable fails to initialize (due to either its mutex or its shared
// memory segment not working), it will not increment in that process (and a
// warning message will be logged). Other variables will work normally. If the
// variable fails to initialize in the process that happens to serve the
// mod_pagespeed_statistics page, then the variable will show up with value -1.
//
// Implementation details heavily cribbed from mod_shm_counter by Aaron Bannert.
class AprVariable : public Variable {
public:
explicit AprVariable(const StringPiece& name);
int64 Get64() const;
virtual int Get() const;
virtual void Set(int newValue);
virtual void Add(int delta);
private:
friend class AprStatistics;
// Logs an error message and returns false if the result is not SUCCESS.
bool CheckResult(const apr_status_t result, const StringPiece& verb,
const StringPiece& filename = kEmptyString) const;
// Initialize this variable's mutex
bool InitMutex(apr_pool_t* pool, bool parent);
// Initialize this variable's shared memory segment.
bool InitShm(apr_pool_t* pool, bool parent);
const std::string& name() const { return name_; }
// The global (cross-thread, cross-process) mutex protecting value_.
// This is NULL if the variable has not yet been properly initialized.
apr_global_mutex_t* mutex_;
// The name of this variable.
const std::string name_;
// Pointer to the shared-memory segment containing our current value.
apr_shm_t* shm_;
// Offset within the shared-memory segment for our current value.
int64* value_ptr_;
};
class AprStatistics : public StatisticsTemplate<AprVariable> {
public:
AprStatistics();
virtual AprVariable* NewVariable(const StringPiece& name, int index);
// Allocate shared memory segments and mutices for all variables. This must
// be called with parent=true from the post_config hook, and with parent=false
// from the child_init hook. After this is called, you must no longer call
// AddVariable.
void InitVariables(apr_pool_t *pool, bool parent);
// Dump the statistics to the given writer.
void Dump(Writer* writer, MessageHandler* message_handler);
// Set all statistics to 0.
void Clear();
bool frozen() const { return frozen_; }
private:
bool frozen_;
};
} // namespace net_instaweb
#endif // NET_INSTAWEB_APACHE_APR_STATISTICS_H_