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