Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: net/spdy/spdy_header_block.h

Issue 2611173004: Modify SpdyHeaderBlock's internals to consolidate header values only on first access. (Closed)
Patch Set: Nit. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef NET_SPDY_SPDY_HEADER_BLOCK_H_ 5 #ifndef NET_SPDY_SPDY_HEADER_BLOCK_H_
6 #define NET_SPDY_SPDY_HEADER_BLOCK_H_ 6 #define NET_SPDY_SPDY_HEADER_BLOCK_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <list> 10 #include <list>
11 #include <map> 11 #include <map>
12 #include <memory> 12 #include <memory>
13 #include <string> 13 #include <string>
14 #include <vector>
14 15
15 #include "base/macros.h" 16 #include "base/macros.h"
16 #include "base/strings/string_piece.h" 17 #include "base/strings/string_piece.h"
17 #include "net/base/linked_hash_map.h" 18 #include "net/base/linked_hash_map.h"
18 #include "net/base/net_export.h" 19 #include "net/base/net_export.h"
19 #include "net/log/net_log.h" 20 #include "net/log/net_log.h"
20 21
21 namespace base { 22 namespace base {
22 class Value; 23 class Value;
23 } 24 }
24 25
25 namespace net { 26 namespace net {
26 27
27 class NetLogCaptureMode; 28 class NetLogCaptureMode;
28 29
29 namespace test { 30 namespace test {
31 class SpdyHeaderBlockPeer;
30 class ValueProxyPeer; 32 class ValueProxyPeer;
31 } 33 }
32 34
33 // This class provides a key-value map that can be used to store SPDY header 35 // This class provides a key-value map that can be used to store SPDY header
34 // names and values. This data structure preserves insertion order. 36 // names and values. This data structure preserves insertion order.
35 // 37 //
36 // Under the hood, this data structure uses large, contiguous blocks of memory 38 // Under the hood, this data structure uses large, contiguous blocks of memory
37 // to store names and values. Lookups may be performed with StringPiece keys, 39 // to store names and values. Lookups may be performed with StringPiece keys,
38 // and values are returned as StringPieces (via ValueProxy, below). 40 // and values are returned as StringPieces (via ValueProxy, below).
39 // Value StringPieces are valid as long as the SpdyHeaderBlock exists; allocated 41 // Value StringPieces are valid as long as the SpdyHeaderBlock exists; allocated
40 // memory is never freed until SpdyHeaderBlock's destruction. 42 // memory is never freed until SpdyHeaderBlock's destruction.
41 // 43 //
42 // This implementation does not make much of an effort to minimize wasted space. 44 // This implementation does not make much of an effort to minimize wasted space.
43 // It's expected that keys are rarely deleted from a SpdyHeaderBlock. 45 // It's expected that keys are rarely deleted from a SpdyHeaderBlock.
44 class NET_EXPORT SpdyHeaderBlock { 46 class NET_EXPORT SpdyHeaderBlock {
45 private: 47 private:
46 using MapType = linked_hash_map<base::StringPiece,
47 base::StringPiece,
48 base::StringPieceHash>;
49 class Storage; 48 class Storage;
50 49
50 // Stores a list of value fragments that can be joined later with a
51 // key-dependent separator.
52 class NET_EXPORT HeaderValue {
53 public:
54 HeaderValue(Storage* storage,
55 base::StringPiece key,
56 base::StringPiece initial_value);
57
58 // Moves are allowed.
59 HeaderValue(HeaderValue&& other);
60 HeaderValue& operator=(HeaderValue&& other);
61
62 // Copies are not.
63 HeaderValue(const HeaderValue& other) = delete;
64 HeaderValue& operator=(const HeaderValue& other) = delete;
65
66 ~HeaderValue();
67
68 // Consumes at most |fragment.size()| bytes of memory.
69 void Append(base::StringPiece fragment);
70
71 base::StringPiece value() const { return as_pair().second; }
72 const std::pair<base::StringPiece, base::StringPiece>& as_pair() const;
73
74 private:
75 // May allocate a large contiguous region of memory to hold the concatenated
76 // fragments and separators.
77 base::StringPiece ConsolidatedValue() const;
78
79 mutable Storage* storage_;
80 mutable std::vector<base::StringPiece> fragments_;
81 // The first element is the key; the second is the consolidated value.
82 mutable std::pair<base::StringPiece, base::StringPiece> pair_;
83 };
84
85 typedef linked_hash_map<base::StringPiece, HeaderValue, base::StringPieceHash>
86 MapType;
87
51 public: 88 public:
52 using iterator = MapType::iterator; 89 typedef std::pair<base::StringPiece, base::StringPiece> value_type;
53 using const_iterator = MapType::const_iterator; 90
54 using value_type = MapType::value_type; 91 // Provides iteration over a sequence of std::pair<StringPiece, StringPiece>,
55 using reverse_iterator = MapType::reverse_iterator; 92 // even though the underlying MapType::value_type is different. Dereferencing
93 // the iterator will result in memory allocation for multi-value headers.
94 class NET_EXPORT iterator {
95 public:
96 // The following type definitions fulfill the requirements for iterator
97 // implementations.
98 typedef std::pair<base::StringPiece, base::StringPiece> value_type;
99 typedef value_type& reference;
100 typedef value_type* pointer;
101 typedef std::forward_iterator_tag iterator_category;
102 typedef MapType::iterator::difference_type difference_type;
103
104 // In practice, this iterator only offers access to const value_type.
105 typedef const value_type& const_reference;
106 typedef const value_type* const_pointer;
107
108 explicit iterator(MapType::const_iterator it);
109 iterator(const iterator& other);
110 ~iterator();
111
112 // This will result in memory allocation if the value consists of multiple
113 // fragments.
114 const_reference operator*() const { return it_->second.as_pair(); }
115
116 const_pointer operator->() const { return &(this->operator*()); }
117 bool operator==(const iterator& it) const { return it_ == it.it_; }
118 bool operator!=(const iterator& it) const { return !(*this == it); }
119
120 iterator& operator++() {
121 it_++;
122 return *this;
123 }
124
125 iterator operator++(int) {
126 auto ret = *this;
127 this->operator++();
128 return ret;
129 }
130
131 private:
132 MapType::const_iterator it_;
133 };
134 typedef iterator const_iterator;
56 135
57 class ValueProxy; 136 class ValueProxy;
58 137
59 SpdyHeaderBlock(); 138 SpdyHeaderBlock();
60 SpdyHeaderBlock(const SpdyHeaderBlock& other) = delete; 139 SpdyHeaderBlock(const SpdyHeaderBlock& other) = delete;
61 SpdyHeaderBlock(SpdyHeaderBlock&& other); 140 SpdyHeaderBlock(SpdyHeaderBlock&& other);
62 ~SpdyHeaderBlock(); 141 ~SpdyHeaderBlock();
63 142
64 SpdyHeaderBlock& operator=(const SpdyHeaderBlock& other) = delete; 143 SpdyHeaderBlock& operator=(const SpdyHeaderBlock& other) = delete;
65 SpdyHeaderBlock& operator=(SpdyHeaderBlock&& other); 144 SpdyHeaderBlock& operator=(SpdyHeaderBlock&& other);
66 SpdyHeaderBlock Clone() const; 145 SpdyHeaderBlock Clone() const;
67 146
68 bool operator==(const SpdyHeaderBlock& other) const; 147 bool operator==(const SpdyHeaderBlock& other) const;
69 bool operator!=(const SpdyHeaderBlock& other) const; 148 bool operator!=(const SpdyHeaderBlock& other) const;
70 149
71 // Provides a human readable multi-line representation of the stored header 150 // Provides a human readable multi-line representation of the stored header
72 // keys and values. 151 // keys and values.
73 std::string DebugString() const; 152 std::string DebugString() const;
74 153
75 // These methods delegate to our MapType member. 154 iterator begin() { return iterator(block_.begin()); }
76 iterator begin() { return block_.begin(); } 155 iterator end() { return iterator(block_.end()); }
77 iterator end() { return block_.end(); } 156 const_iterator begin() const { return const_iterator(block_.begin()); }
78 const_iterator begin() const { return block_.begin(); } 157 const_iterator end() const { return const_iterator(block_.end()); }
79 const_iterator end() const { return block_.end(); }
80 bool empty() const { return block_.empty(); } 158 bool empty() const { return block_.empty(); }
81 size_t size() const { return block_.size(); } 159 size_t size() const { return block_.size(); }
82 iterator find(base::StringPiece key) { return block_.find(key); } 160 iterator find(base::StringPiece key) { return iterator(block_.find(key)); }
83 const_iterator find(base::StringPiece key) const { return block_.find(key); } 161 const_iterator find(base::StringPiece key) const {
84 reverse_iterator rbegin() { return block_.rbegin(); } 162 return const_iterator(block_.find(key));
163 }
85 void erase(base::StringPiece key) { block_.erase(key); } 164 void erase(base::StringPiece key) { block_.erase(key); }
86 165
87 // Clears both our MapType member and the memory used to hold headers. 166 // Clears both our MapType member and the memory used to hold headers.
88 void clear(); 167 void clear();
89 168
90 // The next few methods copy data into our backing storage. 169 // The next few methods copy data into our backing storage.
91 170
92 // If key already exists in the block, replaces the value of that key. Else 171 // If key already exists in the block, replaces the value of that key. Else
93 // adds a new header to the end of the block. 172 // adds a new header to the end of the block.
94 void insert(const MapType::value_type& value); 173 void insert(const value_type& value);
95 174
96 // If a header with the key is already present, then append the value to the 175 // If a header with the key is already present, then append the value to the
97 // existing header value, NUL ("\0") separated unless the key is cookie, in 176 // existing header value, NUL ("\0") separated unless the key is cookie, in
98 // which case the separator is "; ". 177 // which case the separator is "; ".
99 // If there is no such key, a new header with the key and value is added. 178 // If there is no such key, a new header with the key and value is added.
100 void AppendValueOrAddHeader(const base::StringPiece key, 179 void AppendValueOrAddHeader(const base::StringPiece key,
101 const base::StringPiece value); 180 const base::StringPiece value);
102 181
103 // Allows either lookup or mutation of the value associated with a key. 182 // Allows either lookup or mutation of the value associated with a key.
104 ValueProxy operator[](const base::StringPiece key); 183 ValueProxy operator[](const base::StringPiece key);
(...skipping 28 matching lines...) Expand all
133 const base::StringPiece key); 212 const base::StringPiece key);
134 213
135 SpdyHeaderBlock::MapType* block_; 214 SpdyHeaderBlock::MapType* block_;
136 SpdyHeaderBlock::Storage* storage_; 215 SpdyHeaderBlock::Storage* storage_;
137 SpdyHeaderBlock::MapType::iterator lookup_result_; 216 SpdyHeaderBlock::MapType::iterator lookup_result_;
138 base::StringPiece key_; 217 base::StringPiece key_;
139 bool valid_; 218 bool valid_;
140 }; 219 };
141 220
142 private: 221 private:
222 friend class test::SpdyHeaderBlockPeer;
223
143 void AppendHeader(const base::StringPiece key, const base::StringPiece value); 224 void AppendHeader(const base::StringPiece key, const base::StringPiece value);
144 Storage* GetStorage(); 225 Storage* GetStorage();
226 size_t bytes_allocated() const;
145 227
146 // StringPieces held by |block_| point to memory owned by |*storage_|. 228 // StringPieces held by |block_| point to memory owned by |*storage_|.
147 // |storage_| might be nullptr as long as |block_| is empty. 229 // |storage_| might be nullptr as long as |block_| is empty.
148 MapType block_; 230 MapType block_;
149 std::unique_ptr<Storage> storage_; 231 std::unique_ptr<Storage> storage_;
150 }; 232 };
151 233
234 // Writes |fragments| to |dst|, joined by |separator|. |dst| must be large
235 // enough to hold the result. Returns the number of bytes written.
236 NET_EXPORT size_t Join(char* dst,
237 const std::vector<base::StringPiece>& fragments,
238 base::StringPiece separator);
239
152 // Converts a SpdyHeaderBlock into NetLog event parameters. 240 // Converts a SpdyHeaderBlock into NetLog event parameters.
153 NET_EXPORT std::unique_ptr<base::Value> SpdyHeaderBlockNetLogCallback( 241 NET_EXPORT std::unique_ptr<base::Value> SpdyHeaderBlockNetLogCallback(
154 const SpdyHeaderBlock* headers, 242 const SpdyHeaderBlock* headers,
155 NetLogCaptureMode capture_mode); 243 NetLogCaptureMode capture_mode);
156 244
157 // Converts NetLog event parameters into a SPDY header block and writes them 245 // Converts NetLog event parameters into a SPDY header block and writes them
158 // to |headers|. |event_param| must have been created by 246 // to |headers|. |event_param| must have been created by
159 // SpdyHeaderBlockNetLogCallback. On failure, returns false and clears 247 // SpdyHeaderBlockNetLogCallback. On failure, returns false and clears
160 // |headers|. 248 // |headers|.
161 NET_EXPORT bool SpdyHeaderBlockFromNetLogParam( 249 NET_EXPORT bool SpdyHeaderBlockFromNetLogParam(
162 const base::Value* event_param, 250 const base::Value* event_param,
163 SpdyHeaderBlock* headers); 251 SpdyHeaderBlock* headers);
164 252
165 } // namespace net 253 } // namespace net
166 254
167 #endif // NET_SPDY_SPDY_HEADER_BLOCK_H_ 255 #endif // NET_SPDY_SPDY_HEADER_BLOCK_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698