license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 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. |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 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" |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 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::wstring& 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. |
| 57 | static StatsTable* current() { return global_table_; } |
| 58 | |
| 59 | // Set the global table for use in this process. |
| 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::wstring& name); |
| 78 | |
| 79 | // Returns the space occupied by a thread in the table. Generally used |
| 80 | // if a thread terminates but the process continues. This function |
| 81 | // does not zero out the thread's counters. |
| 82 | void UnregisterThread(); |
| 83 | |
| 84 | // Returns the number of threads currently registered. This is really not |
| 85 | // useful except for diagnostics and debugging. |
| 86 | int CountThreadsRegistered() const; |
| 87 | |
| 88 | // Find a counter in the StatsTable. |
| 89 | // |
| 90 | // Returns an id for the counter which can be used to call GetLocation(). |
| 91 | // If the counter does not exist, attempts to create a row for the new |
| 92 | // counter. If there is no space in the table for the new counter, |
| 93 | // returns 0. |
| 94 | int FindCounter(const std::wstring& name); |
| 95 | |
| 96 | // TODO(mbelshe): implement RemoveCounter. |
| 97 | |
| 98 | // Gets the location of a particular value in the table based on |
| 99 | // the counter id and slot id. |
| 100 | int* GetLocation(int counter_id, int slot_id) const; |
| 101 | |
| 102 | // Gets the counter name at a particular row. If the row is empty, |
| 103 | // returns NULL. |
| 104 | const wchar_t* GetRowName(int index) const; |
| 105 | |
| 106 | // Gets the sum of the values for a particular row. |
| 107 | int GetRowValue(int index) const; |
| 108 | |
| 109 | // Gets the sum of the values for a particular row for a given pid. |
| 110 | int GetRowValue(int index, int pid) const; |
| 111 | |
| 112 | // Gets the sum of the values for a particular counter. If the counter |
| 113 | // does not exist, creates the counter. |
| 114 | int GetCounterValue(const std::wstring& name); |
| 115 | |
| 116 | // Gets the sum of the values for a particular counter for a given pid. |
| 117 | // If the counter does not exist, creates the counter. |
| 118 | int GetCounterValue(const std::wstring& name, int pid); |
| 119 | |
| 120 | // The maxinum number of counters/rows in the table. |
| 121 | int GetMaxCounters() const; |
| 122 | |
| 123 | // The maxinum number of threads/columns in the table. |
| 124 | int GetMaxThreads() const; |
| 125 | |
| 126 | // The maximum length (in characters) of a Thread's name including |
| 127 | // null terminator, as stored in the shared memory. |
| 128 | static const int kMaxThreadNameLength = 32; |
| 129 | |
| 130 | // The maximum length (in characters) of a Counter's name including |
| 131 | // null terminator, as stored in the shared memory. |
| 132 | static const int kMaxCounterNameLength = 32; |
| 133 | |
| 134 | // Convenience function to lookup a counter location for a |
| 135 | // counter by name for the calling thread. Will register |
| 136 | // the thread if it is not already registered. |
| 137 | static int* FindLocation(const wchar_t *name); |
| 138 | |
| 139 | private: |
| 140 | // Locates a free slot in the table. Returns a number > 0 on success, |
| 141 | // or 0 on failure. The caller must hold the shared_memory lock when |
| 142 | // calling this function. |
| 143 | int FindEmptyThread() const; |
| 144 | |
| 145 | // Locates a counter in the table or finds an empty row. Returns a |
| 146 | // number > 0 on success, or 0 on failure. The caller must hold the |
| 147 | // shared_memory_lock when calling this function. |
| 148 | int FindCounterOrEmptyRow(const std::wstring& name) const; |
| 149 | |
| 150 | // Internal function to add a counter to the StatsTable. Assumes that |
| 151 | // the counter does not already exist in the table. |
| 152 | // |
| 153 | // name is a unique identifier for this counter, and will be truncated |
| 154 | // to kMaxCounterNameLength-1 characters. |
| 155 | // |
| 156 | // On success, returns the counter_id for the newly added counter. |
| 157 | // On failure, returns 0. |
| 158 | int AddCounter(const std::wstring& name); |
| 159 | |
| 160 | // Get the TLS data for the calling thread. Returns NULL if none is |
| 161 | // initialized. |
| 162 | StatsTableTLSData* GetTLSData() const; |
| 163 | |
| 164 | typedef base::hash_map<std::wstring, int> CountersMap; |
| 165 | |
| 166 | bool opened_; |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 167 | StatsTablePrivate* impl_; |
| 168 | // The counters_lock_ protects the counters_ hash table. |
| 169 | Lock counters_lock_; |
| 170 | // The counters_ hash map is an in-memory hash of the counters. |
| 171 | // It is used for quick lookup of counters, but is cannot be used |
| 172 | // as a substitute for what is in the shared memory. Even though |
| 173 | // we don't have a counter in our hash table, another process may |
| 174 | // have created it. |
| 175 | CountersMap counters_; |
| 176 | TLSSlot tls_index_; |
| 177 | |
| 178 | static StatsTable* global_table_; |
| 179 | DISALLOW_EVIL_CONSTRUCTORS(StatsTable); |
| 180 | }; |
| 181 | |
| 182 | #endif // BASE_STATS_TABLE_H__ |