• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // A StatsTable is a table of statistics.  It can be used across multiple
6 // processes and threads, maintaining cheap statistics counters without
7 // locking.
8 //
9 // The goal is to make it very cheap and easy for developers to add
10 // counters to code, without having to build one-off utilities or mechanisms
11 // to track the counters, and also to allow a single "view" to display
12 // the contents of all counters.
13 //
14 // To achieve this, StatsTable creates a shared memory segment to store
15 // the data for the counters.  Upon creation, it has a specific size
16 // which governs the maximum number of counters and concurrent
17 // threads/processes which can use it.
18 //
19 
20 #ifndef BASE_STATS_TABLE_H__
21 #define BASE_STATS_TABLE_H__
22 
23 #include <string>
24 #include "base/basictypes.h"
25 #include "base/hash_tables.h"
26 #include "base/lock.h"
27 #include "base/thread_local_storage.h"
28 
29 class StatsTablePrivate;
30 
31 namespace {
32 struct StatsTableTLSData;
33 }
34 
35 class StatsTable {
36  public:
37   // Create a new StatsTable.
38   // If a StatsTable already exists with the specified name, this StatsTable
39   // will use the same shared memory segment as the original.  Otherwise,
40   // a new StatsTable is created and all counters are zeroed.
41   //
42   // name is the name of the StatsTable to use.
43   //
44   // max_threads is the maximum number of threads the table will support.
45   // If the StatsTable already exists, this number is ignored.
46   //
47   // max_counters is the maximum number of counters the table will support.
48   // If the StatsTable already exists, this number is ignored.
49   StatsTable(const std::string& name, int max_threads, int max_counters);
50 
51   // Destroys the StatsTable.  When the last StatsTable is destroyed
52   // (across all processes), the StatsTable is removed from disk.
53   ~StatsTable();
54 
55   // For convenience, we create a static table.  This is generally
56   // used automatically by the counters.
current()57   static StatsTable* current() { return global_table_; }
58 
59   // Set the global table for use in this process.
set_current(StatsTable * value)60   static void set_current(StatsTable* value) { global_table_ = value; }
61 
62   // Get the slot id for the calling thread. Returns 0 if no
63   // slot is assigned.
64   int GetSlot() const;
65 
66   // All threads that contribute data to the table must register with the
67   // table first.  This function will set thread local storage for the
68   // thread containing the location in the table where this thread will
69   // write its counter data.
70   //
71   // name is just a debugging tag to label the thread, and it does not
72   // need to be unique.  It will be truncated to kMaxThreadNameLength-1
73   // characters.
74   //
75   // On success, returns the slot id for this thread.  On failure,
76   // returns 0.
77   int RegisterThread(const std::string& name);
78 
79   // Returns the number of threads currently registered.  This is really not
80   // useful except for diagnostics and debugging.
81   int CountThreadsRegistered() const;
82 
83   // Find a counter in the StatsTable.
84   //
85   // Returns an id for the counter which can be used to call GetLocation().
86   // If the counter does not exist, attempts to create a row for the new
87   // counter.  If there is no space in the table for the new counter,
88   // returns 0.
89   int FindCounter(const std::string& name);
90 
91   // TODO(mbelshe): implement RemoveCounter.
92 
93   // Gets the location of a particular value in the table based on
94   // the counter id and slot id.
95   int* GetLocation(int counter_id, int slot_id) const;
96 
97   // Gets the counter name at a particular row.  If the row is empty,
98   // returns NULL.
99   const char* GetRowName(int index) const;
100 
101   // Gets the sum of the values for a particular row.
102   int GetRowValue(int index) const;
103 
104   // Gets the sum of the values for a particular row for a given pid.
105   int GetRowValue(int index, int pid) const;
106 
107   // Gets the sum of the values for a particular counter.  If the counter
108   // does not exist, creates the counter.
109   int GetCounterValue(const std::string& name);
110 
111   // Gets the sum of the values for a particular counter for a given pid.
112   // If the counter does not exist, creates the counter.
113   int GetCounterValue(const std::string& name, int pid);
114 
115   // The maxinum number of counters/rows in the table.
116   int GetMaxCounters() const;
117 
118   // The maxinum number of threads/columns in the table.
119   int GetMaxThreads() const;
120 
121   // The maximum length (in characters) of a Thread's name including
122   // null terminator, as stored in the shared memory.
123   static const int kMaxThreadNameLength = 32;
124 
125   // The maximum length (in characters) of a Counter's name including
126   // null terminator, as stored in the shared memory.
127   static const int kMaxCounterNameLength = 32;
128 
129   // Convenience function to lookup a counter location for a
130   // counter by name for the calling thread.  Will register
131   // the thread if it is not already registered.
132   static int* FindLocation(const char *name);
133 
134  private:
135   // Returns the space occupied by a thread in the table.  Generally used
136   // if a thread terminates but the process continues.  This function
137   // does not zero out the thread's counters.
138   // Cannot be used inside a posix tls destructor.
139   void UnregisterThread();
140 
141   // This variant expects the tls data to be passed in, so it is safe to
142   // call from inside a posix tls destructor (see doc for pthread_key_create).
143   void UnregisterThread(StatsTableTLSData* tls_data);
144 
145   // The SlotReturnFunction is called at thread exit for each thread
146   // which used the StatsTable.
147   static void SlotReturnFunction(void* data);
148 
149   // Locates a free slot in the table.  Returns a number > 0 on success,
150   // or 0 on failure.  The caller must hold the shared_memory lock when
151   // calling this function.
152   int FindEmptyThread() const;
153 
154   // Locates a counter in the table or finds an empty row.  Returns a
155   // number > 0 on success, or 0 on failure.  The caller must hold the
156   // shared_memory_lock when calling this function.
157   int FindCounterOrEmptyRow(const std::string& name) const;
158 
159   // Internal function to add a counter to the StatsTable.  Assumes that
160   // the counter does not already exist in the table.
161   //
162   // name is a unique identifier for this counter, and will be truncated
163   // to kMaxCounterNameLength-1 characters.
164   //
165   // On success, returns the counter_id for the newly added counter.
166   // On failure, returns 0.
167   int AddCounter(const std::string& name);
168 
169   // Get the TLS data for the calling thread.  Returns NULL if none is
170   // initialized.
171   StatsTableTLSData* GetTLSData() const;
172 
173   typedef base::hash_map<std::string, int> CountersMap;
174 
175   StatsTablePrivate* impl_;
176   // The counters_lock_ protects the counters_ hash table.
177   Lock counters_lock_;
178   // The counters_ hash map is an in-memory hash of the counters.
179   // It is used for quick lookup of counters, but is cannot be used
180   // as a substitute for what is in the shared memory.  Even though
181   // we don't have a counter in our hash table, another process may
182   // have created it.
183   CountersMap counters_;
184   TLSSlot tls_index_;
185 
186   static StatsTable* global_table_;
187 
188   DISALLOW_EVIL_CONSTRUCTORS(StatsTable);
189 };
190 
191 #endif  // BASE_STATS_TABLE_H__
192