55#include < utility>
66
77#include " envoy/common/exception.h"
8+ #include " envoy/stats/stats.h"
89
910#include " common/common/assert.h"
1011#include " common/common/fmt.h"
1112#include " common/common/logger.h"
13+ #include " common/stats/stats_impl.h"
1214
1315#include " absl/strings/string_view.h"
1416
@@ -57,21 +59,24 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
5759
5860 /* *
5961 * Constructs a map control structure given a set of options, which cannot be changed.
60- * @param options describes the parameters comtrolling set layout.
62+ * @param hash_set_options describes the parameters comtrolling set layout.
6163 * @param init true if the memory should be initialized on construction. If false,
6264 * the data in the table will be sanity checked, and an exception thrown if
6365 * it is incoherent or mismatches the passed-in options.
6466 * @param memory the memory buffer for the set data.
67+ * @param stats_options a reference to the top-level StatsOptions struct containing
68+ * information about max allowable stat name lengths.
6569 *
6670 * Note that no locking of any kind is done by this class; this must be done at the
6771 * call-site to support concurrent access.
6872 */
69- BlockMemoryHashSet (const BlockMemoryHashSetOptions& options, bool init, uint8_t * memory)
70- : cells_(nullptr ), control_(nullptr ), slots_(nullptr ) {
71- mapMemorySegments (options, memory);
73+ BlockMemoryHashSet (const BlockMemoryHashSetOptions& hash_set_options, bool init, uint8_t * memory,
74+ const Stats::StatsOptions& stats_options)
75+ : cells_(nullptr ), control_(nullptr ), slots_(nullptr ), stats_options_(stats_options) {
76+ mapMemorySegments (hash_set_options, memory);
7277 if (init) {
73- initialize (options );
74- } else if (!attach (options )) {
78+ initialize (hash_set_options );
79+ } else if (!attach (hash_set_options )) {
7580 throw EnvoyException (" BlockMemoryHashSet: Incompatible memory block" );
7681 }
7782 }
@@ -82,22 +87,20 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
8287 * backing-store (eg) in memory, which we do after
8388 * constructing the object with the desired sizing.
8489 */
85- static uint64_t numBytes (const BlockMemoryHashSetOptions& options) {
86- uint64_t size =
87- cellOffset (options.capacity ) + sizeof (Control) + options.num_slots * sizeof (uint32_t );
90+ static uint64_t numBytes (const BlockMemoryHashSetOptions& hash_set_options,
91+ const Stats::StatsOptions& stats_options) {
92+ uint64_t size = cellOffset (hash_set_options.capacity , stats_options) + sizeof (Control) +
93+ hash_set_options.num_slots * sizeof (uint32_t );
8894 return align (size);
8995 }
9096
91- uint64_t numBytes () const { return numBytes (control_->options ); }
92-
93- /* *
94- * Returns the options structure that was used to construct the set.
95- */
96- const BlockMemoryHashSetOptions& options () const { return control_->options ; }
97+ uint64_t numBytes (const Stats::StatsOptions& stats_options) const {
98+ return numBytes (control_->hash_set_options , stats_options);
99+ }
97100
98101 /* * Examines the data structures to see if they are sane, assert-failing on any trouble. */
99102 void sanityCheck () {
100- RELEASE_ASSERT (control_->size <= control_->options .capacity , " " );
103+ RELEASE_ASSERT (control_->size <= control_->hash_set_options .capacity , " " );
101104
102105 // As a sanity check, make sure there are control_->size values
103106 // reachable from the slots, each of which has a valid
@@ -107,11 +110,11 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
107110 // slot. Note that the num_values message will be emitted outside
108111 // the loop.
109112 uint32_t num_values = 0 ;
110- for (uint32_t slot = 0 ; slot < control_->options .num_slots ; ++slot) {
113+ for (uint32_t slot = 0 ; slot < control_->hash_set_options .num_slots ; ++slot) {
111114 uint32_t next = 0 ; // initialized to silence compilers.
112115 for (uint32_t cell_index = slots_[slot];
113116 (cell_index != Sentinal) && (num_values <= control_->size ); cell_index = next) {
114- RELEASE_ASSERT (cell_index < control_->options .capacity , " " );
117+ RELEASE_ASSERT (cell_index < control_->hash_set_options .capacity , " " );
115118 Cell& cell = getCell (cell_index);
116119 absl::string_view key = cell.value .key ();
117120 RELEASE_ASSERT (computeSlot (key) == slot, " " );
@@ -122,7 +125,7 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
122125 RELEASE_ASSERT (num_values == control_->size , " " );
123126
124127 uint32_t num_free_entries = 0 ;
125- uint32_t expected_free_entries = control_->options .capacity - control_->size ;
128+ uint32_t expected_free_entries = control_->hash_set_options .capacity - control_->size ;
126129
127130 // Don't infinite-loop with a corruption; break when we see there's a problem.
128131 for (uint32_t cell_index = control_->free_cell_index ;
@@ -152,7 +155,7 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
152155 if (value != nullptr ) {
153156 return ValueCreatedPair (value, false );
154157 }
155- if (control_->size >= control_->options .capacity ) {
158+ if (control_->size >= control_->hash_set_options .capacity ) {
156159 return ValueCreatedPair (nullptr , false );
157160 }
158161 const uint32_t slot = computeSlot (key);
@@ -162,7 +165,7 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
162165 cell.next_cell_index = slots_[slot];
163166 slots_[slot] = cell_index;
164167 value = &cell.value ;
165- value->initialize (key);
168+ value->truncateAndInit (key, stats_options_ );
166169 ++control_->size ;
167170 return ValueCreatedPair (value, true );
168171 }
@@ -215,9 +218,9 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
215218 /* *
216219 * Computes a version signature based on the options and the hash function.
217220 */
218- std::string version () {
219- return fmt::format (" options={} hash={} size={}" , control_->options .toString (),
220- control_->hash_signature , numBytes ());
221+ std::string version (const Stats::StatsOptions& stats_options ) {
222+ return fmt::format (" options={} hash={} size={}" , control_->hash_set_options .toString (),
223+ control_->hash_signature , numBytes (stats_options ));
221224 }
222225
223226private:
@@ -228,20 +231,20 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
228231 * coming in.
229232 * @param memory
230233 */
231- void initialize (const BlockMemoryHashSetOptions& options ) {
234+ void initialize (const BlockMemoryHashSetOptions& hash_set_options ) {
232235 control_->hash_signature = Value::hash (signatureStringToHash ());
233- control_->num_bytes = numBytes (options );
234- control_->options = options ;
236+ control_->num_bytes = numBytes (hash_set_options, stats_options_ );
237+ control_->hash_set_options = hash_set_options ;
235238 control_->size = 0 ;
236239 control_->free_cell_index = 0 ;
237240
238241 // Initialize all the slots;
239- for (uint32_t slot = 0 ; slot < options .num_slots ; ++slot) {
242+ for (uint32_t slot = 0 ; slot < hash_set_options .num_slots ; ++slot) {
240243 slots_[slot] = Sentinal;
241244 }
242245
243246 // Initialize the free-cell list.
244- const uint32_t last_cell = options .capacity - 1 ;
247+ const uint32_t last_cell = hash_set_options .capacity - 1 ;
245248 for (uint32_t cell_index = 0 ; cell_index < last_cell; ++cell_index) {
246249 Cell& cell = getCell (cell_index);
247250 cell.next_cell_index = cell_index + 1 ;
@@ -254,10 +257,10 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
254257 * sanity check to make sure the options copied to the provided memory match, and also
255258 * that the slot, cell, and key-string structures look sane.
256259 */
257- bool attach (const BlockMemoryHashSetOptions& options ) {
258- if (numBytes (options ) != control_->num_bytes ) {
259- ENVOY_LOG (error, " BlockMemoryHashSet unexpected memory size {} != {}" , numBytes (options),
260- control_->num_bytes );
260+ bool attach (const BlockMemoryHashSetOptions& hash_set_options ) {
261+ if (numBytes (hash_set_options, stats_options_ ) != control_->num_bytes ) {
262+ ENVOY_LOG (error, " BlockMemoryHashSet unexpected memory size {} != {}" ,
263+ numBytes (hash_set_options, stats_options_), control_->num_bytes );
261264 return false ;
262265 }
263266 if (Value::hash (signatureStringToHash ()) != control_->hash_signature ) {
@@ -269,7 +272,7 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
269272 }
270273
271274 uint32_t computeSlot (absl::string_view key) {
272- return Value::hash (key) % control_->options .num_slots ;
275+ return Value::hash (key) % control_->hash_set_options .num_slots ;
273276 }
274277
275278 /* *
@@ -290,11 +293,11 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
290293 * Represents control-values for the hash-table.
291294 */
292295 struct Control {
293- BlockMemoryHashSetOptions options ; // Options established at map construction time.
294- uint64_t hash_signature; // Hash of a constant signature string.
295- uint64_t num_bytes; // Bytes allocated on behalf of the map.
296- uint32_t size; // Number of values currently stored.
297- uint32_t free_cell_index; // Offset of first free cell.
296+ BlockMemoryHashSetOptions hash_set_options ; // Options established at map construction time.
297+ uint64_t hash_signature; // Hash of a constant signature string.
298+ uint64_t num_bytes; // Bytes allocated on behalf of the map.
299+ uint32_t size; // Number of values currently stored.
300+ uint32_t free_cell_index; // Offset of first free cell.
298301 };
299302
300303 /* *
@@ -323,10 +326,11 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
323326 * simply an array index because we don't know the size of a key at
324327 * compile-time.
325328 */
326- static uint64_t cellOffset (uint32_t cell_index) {
329+ static uint64_t cellOffset (uint32_t cell_index, const Stats::StatsOptions& stats_options ) {
327330 // sizeof(Cell) includes 'sizeof Value' which may not be accurate. So we need to
328331 // subtract that off, and add the template method's view of the actual value-size.
329- uint64_t cell_size = align (sizeof (Cell) + Value::size () - sizeof (Value));
332+ uint64_t cell_size =
333+ align (sizeof (Cell) + Value::structSizeWithOptions (stats_options) - sizeof (Value));
330334 return cell_index * cell_size;
331335 }
332336
@@ -335,17 +339,17 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
335339 */
336340 Cell& getCell (uint32_t cell_index) {
337341 // Because the key-size is parameteriziable, an array-lookup on sizeof(Cell) does not work.
338- char * ptr = reinterpret_cast <char *>(cells_) + cellOffset (cell_index);
342+ char * ptr = reinterpret_cast <char *>(cells_) + cellOffset (cell_index, stats_options_ );
339343 RELEASE_ASSERT ((reinterpret_cast <uint64_t >(ptr) & (calculateAlignment () - 1 )) == 0 , " " );
340344 return *reinterpret_cast <Cell*>(ptr);
341345 }
342346
343347 /* * Maps out the segments of memory for us to work with. */
344- void mapMemorySegments (const BlockMemoryHashSetOptions& options , uint8_t * memory) {
348+ void mapMemorySegments (const BlockMemoryHashSetOptions& hash_set_options , uint8_t * memory) {
345349 // Note that we are not examining or mutating memory here, just looking at the pointer,
346350 // so we don't need to hold any locks.
347351 cells_ = reinterpret_cast <Cell*>(memory); // First because Value may need to be aligned.
348- memory += cellOffset (options .capacity );
352+ memory += cellOffset (hash_set_options .capacity , stats_options_ );
349353 control_ = reinterpret_cast <Control*>(memory);
350354 memory += sizeof (Control);
351355 slots_ = reinterpret_cast <uint32_t *>(memory);
@@ -356,6 +360,7 @@ template <class Value> class BlockMemoryHashSet : public Logger::Loggable<Logger
356360 Cell* cells_;
357361 Control* control_;
358362 uint32_t * slots_;
363+ const Stats::StatsOptions& stats_options_;
359364};
360365
361366} // namespace Envoy
0 commit comments