| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "net/spdy/hpack_header_table.h" | 5 #include "net/spdy/hpack_header_table.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "net/spdy/hpack_constants.h" | 10 #include "net/spdy/hpack_constants.h" |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 const size_t rhs_index = table_->IndexOf(rhs); | 111 const size_t rhs_index = table_->IndexOf(rhs); |
| 112 DCHECK(lhs == rhs || lhs_index != rhs_index) | 112 DCHECK(lhs == rhs || lhs_index != rhs_index) |
| 113 << "lhs: (" << lhs->name() << ", " << rhs->value() << ") rhs: (" | 113 << "lhs: (" << lhs->name() << ", " << rhs->value() << ") rhs: (" |
| 114 << rhs->name() << ", " << rhs->value() << ")" | 114 << rhs->name() << ", " << rhs->value() << ")" |
| 115 << " lhs index: " << lhs_index << " rhs index: " << rhs_index; | 115 << " lhs index: " << lhs_index << " rhs index: " << rhs_index; |
| 116 return lhs_index < rhs_index; | 116 return lhs_index < rhs_index; |
| 117 } | 117 } |
| 118 | 118 |
| 119 HpackHeaderTable::HpackHeaderTable() | 119 HpackHeaderTable::HpackHeaderTable() |
| 120 : index_(EntryComparator(this)), | 120 : index_(EntryComparator(this)), |
| 121 reference_set_(EntryComparator(this)), | |
| 122 settings_size_bound_(kDefaultHeaderTableSizeSetting), | 121 settings_size_bound_(kDefaultHeaderTableSizeSetting), |
| 123 size_(0), | 122 size_(0), |
| 124 max_size_(kDefaultHeaderTableSizeSetting), | 123 max_size_(kDefaultHeaderTableSizeSetting), |
| 125 total_insertions_(0) { | 124 total_insertions_(0) { |
| 126 for (const StaticEntry* it = kStaticTable; | 125 for (const StaticEntry* it = kStaticTable; |
| 127 it != kStaticTable + arraysize(kStaticTable); ++it) { | 126 it != kStaticTable + arraysize(kStaticTable); ++it) { |
| 128 static_entries_.push_back( | 127 static_entries_.push_back( |
| 129 HpackEntry(StringPiece(it->name, it->name_len), | 128 HpackEntry(StringPiece(it->name, it->name_len), |
| 130 StringPiece(it->value, it->value_len), | 129 StringPiece(it->value, it->value_len), |
| 131 true, // is_static | 130 true, // is_static |
| 132 total_insertions_)); | 131 total_insertions_)); |
| 133 CHECK(index_.insert(&static_entries_.back()).second); | 132 CHECK(index_.insert(&static_entries_.back()).second); |
| 134 | 133 |
| 135 ++total_insertions_; | 134 ++total_insertions_; |
| 136 } | 135 } |
| 137 } | 136 } |
| 138 | 137 |
| 139 HpackHeaderTable::~HpackHeaderTable() {} | 138 HpackHeaderTable::~HpackHeaderTable() {} |
| 140 | 139 |
| 141 HpackEntry* HpackHeaderTable::GetByIndex(size_t index) { | 140 HpackEntry* HpackHeaderTable::GetByIndex(size_t index) { |
| 142 if (index == 0) { | 141 if (index == 0) { |
| 143 return NULL; | 142 return NULL; |
| 144 } | 143 } |
| 145 index -= 1; | 144 index -= 1; |
| 145 if (index < static_entries_.size()) { |
| 146 return &static_entries_[index]; |
| 147 } |
| 148 index -= static_entries_.size(); |
| 146 if (index < dynamic_entries_.size()) { | 149 if (index < dynamic_entries_.size()) { |
| 147 return &dynamic_entries_[index]; | 150 return &dynamic_entries_[index]; |
| 148 } | 151 } |
| 149 index -= dynamic_entries_.size(); | |
| 150 if (index < static_entries_.size()) { | |
| 151 return &static_entries_[index]; | |
| 152 } | |
| 153 return NULL; | 152 return NULL; |
| 154 } | 153 } |
| 155 | 154 |
| 156 HpackEntry* HpackHeaderTable::GetByName(StringPiece name) { | 155 HpackEntry* HpackHeaderTable::GetByName(StringPiece name) { |
| 157 HpackEntry query(name, ""); | 156 HpackEntry query(name, ""); |
| 158 OrderedEntrySet::const_iterator it = index_.lower_bound(&query); | 157 OrderedEntrySet::const_iterator it = index_.lower_bound(&query); |
| 159 if (it != index_.end() && (*it)->name() == name) { | 158 if (it != index_.end() && (*it)->name() == name) { |
| 160 return *it; | 159 return *it; |
| 161 } | 160 } |
| 162 return NULL; | 161 return NULL; |
| 163 } | 162 } |
| 164 | 163 |
| 165 HpackEntry* HpackHeaderTable::GetByNameAndValue(StringPiece name, | 164 HpackEntry* HpackHeaderTable::GetByNameAndValue(StringPiece name, |
| 166 StringPiece value) { | 165 StringPiece value) { |
| 167 HpackEntry query(name, value); | 166 HpackEntry query(name, value); |
| 168 OrderedEntrySet::const_iterator it = index_.lower_bound(&query); | 167 OrderedEntrySet::const_iterator it = index_.lower_bound(&query); |
| 169 if (it != index_.end() && (*it)->name() == name && (*it)->value() == value) { | 168 if (it != index_.end() && (*it)->name() == name && (*it)->value() == value) { |
| 170 return *it; | 169 return *it; |
| 171 } | 170 } |
| 172 return NULL; | 171 return NULL; |
| 173 } | 172 } |
| 174 | 173 |
| 175 size_t HpackHeaderTable::IndexOf(const HpackEntry* entry) const { | 174 size_t HpackHeaderTable::IndexOf(const HpackEntry* entry) const { |
| 176 if (entry->IsLookup()) { | 175 if (entry->IsLookup()) { |
| 177 return 0; | 176 return 0; |
| 178 } else if (entry->IsStatic()) { | 177 } else if (entry->IsStatic()) { |
| 179 return 1 + entry->InsertionIndex() + dynamic_entries_.size(); | 178 return 1 + entry->InsertionIndex(); |
| 180 } else { | 179 } else { |
| 181 return total_insertions_ - entry->InsertionIndex(); | 180 return total_insertions_ - entry->InsertionIndex() + static_entries_.size(); |
| 182 } | 181 } |
| 183 } | 182 } |
| 184 | 183 |
| 185 void HpackHeaderTable::SetMaxSize(size_t max_size) { | 184 void HpackHeaderTable::SetMaxSize(size_t max_size) { |
| 186 CHECK_LE(max_size, settings_size_bound_); | 185 CHECK_LE(max_size, settings_size_bound_); |
| 187 | 186 |
| 188 max_size_ = max_size; | 187 max_size_ = max_size; |
| 189 if (size_ > max_size_) { | 188 if (size_ > max_size_) { |
| 190 Evict(EvictionCountToReclaim(size_ - max_size_)); | 189 Evict(EvictionCountToReclaim(size_ - max_size_)); |
| 191 CHECK_LE(size_, max_size_); | 190 CHECK_LE(size_, max_size_); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 return count; | 228 return count; |
| 230 } | 229 } |
| 231 | 230 |
| 232 void HpackHeaderTable::Evict(size_t count) { | 231 void HpackHeaderTable::Evict(size_t count) { |
| 233 for (size_t i = 0; i != count; ++i) { | 232 for (size_t i = 0; i != count; ++i) { |
| 234 CHECK(!dynamic_entries_.empty()); | 233 CHECK(!dynamic_entries_.empty()); |
| 235 HpackEntry* entry = &dynamic_entries_.back(); | 234 HpackEntry* entry = &dynamic_entries_.back(); |
| 236 | 235 |
| 237 size_ -= entry->Size(); | 236 size_ -= entry->Size(); |
| 238 CHECK_EQ(1u, index_.erase(entry)); | 237 CHECK_EQ(1u, index_.erase(entry)); |
| 239 reference_set_.erase(entry); | |
| 240 dynamic_entries_.pop_back(); | 238 dynamic_entries_.pop_back(); |
| 241 } | 239 } |
| 242 } | 240 } |
| 243 | 241 |
| 244 HpackEntry* HpackHeaderTable::TryAddEntry(StringPiece name, StringPiece value) { | 242 HpackEntry* HpackHeaderTable::TryAddEntry(StringPiece name, StringPiece value) { |
| 245 Evict(EvictionCountForEntry(name, value)); | 243 Evict(EvictionCountForEntry(name, value)); |
| 246 | 244 |
| 247 size_t entry_size = HpackEntry::Size(name, value); | 245 size_t entry_size = HpackEntry::Size(name, value); |
| 248 if (entry_size > (max_size_ - size_)) { | 246 if (entry_size > (max_size_ - size_)) { |
| 249 // Entire table has been emptied, but there's still insufficient room. | 247 // Entire table has been emptied, but there's still insufficient room. |
| 250 DCHECK(dynamic_entries_.empty()); | 248 DCHECK(dynamic_entries_.empty()); |
| 251 DCHECK_EQ(0u, size_); | 249 DCHECK_EQ(0u, size_); |
| 252 return NULL; | 250 return NULL; |
| 253 } | 251 } |
| 254 dynamic_entries_.push_front(HpackEntry(name, | 252 dynamic_entries_.push_front(HpackEntry(name, |
| 255 value, | 253 value, |
| 256 false, // is_static | 254 false, // is_static |
| 257 total_insertions_)); | 255 total_insertions_)); |
| 258 CHECK(index_.insert(&dynamic_entries_.front()).second); | 256 CHECK(index_.insert(&dynamic_entries_.front()).second); |
| 259 | 257 |
| 260 size_ += entry_size; | 258 size_ += entry_size; |
| 261 ++total_insertions_; | 259 ++total_insertions_; |
| 262 | 260 |
| 263 return &dynamic_entries_.front(); | 261 return &dynamic_entries_.front(); |
| 264 } | 262 } |
| 265 | 263 |
| 266 void HpackHeaderTable::ClearReferenceSet() { | |
| 267 for (OrderedEntrySet::iterator it = reference_set_.begin(); | |
| 268 it != reference_set_.end(); ++it) { | |
| 269 (*it)->set_state(0); | |
| 270 } | |
| 271 reference_set_.clear(); | |
| 272 } | |
| 273 | |
| 274 bool HpackHeaderTable::Toggle(HpackEntry* entry) { | |
| 275 CHECK(!entry->IsStatic()); | |
| 276 CHECK_EQ(0u, entry->state()); | |
| 277 | |
| 278 std::pair<OrderedEntrySet::iterator, bool> insert_result = | |
| 279 reference_set_.insert(entry); | |
| 280 if (insert_result.second) { | |
| 281 return true; | |
| 282 } else { | |
| 283 reference_set_.erase(insert_result.first); | |
| 284 return false; | |
| 285 } | |
| 286 } | |
| 287 | |
| 288 void HpackHeaderTable::DebugLogTableState() const { | 264 void HpackHeaderTable::DebugLogTableState() const { |
| 289 DVLOG(2) << "Reference Set:"; | |
| 290 for (OrderedEntrySet::const_iterator it = reference_set_.begin(); | |
| 291 it != reference_set_.end(); ++it) { | |
| 292 DVLOG(2) << " " << (*it)->GetDebugString(); | |
| 293 } | |
| 294 DVLOG(2) << "Dynamic table:"; | 265 DVLOG(2) << "Dynamic table:"; |
| 295 for (EntryTable::const_iterator it = dynamic_entries_.begin(); | 266 for (EntryTable::const_iterator it = dynamic_entries_.begin(); |
| 296 it != dynamic_entries_.end(); ++it) { | 267 it != dynamic_entries_.end(); ++it) { |
| 297 DVLOG(2) << " " << it->GetDebugString(); | 268 DVLOG(2) << " " << it->GetDebugString(); |
| 298 } | 269 } |
| 299 DVLOG(2) << "Full Index:"; | 270 DVLOG(2) << "Full Index:"; |
| 300 for (OrderedEntrySet::const_iterator it = index_.begin(); | 271 for (OrderedEntrySet::const_iterator it = index_.begin(); |
| 301 it != index_.end(); ++it) { | 272 it != index_.end(); ++it) { |
| 302 DVLOG(2) << " " << (*it)->GetDebugString(); | 273 DVLOG(2) << " " << (*it)->GetDebugString(); |
| 303 } | 274 } |
| 304 } | 275 } |
| 305 | 276 |
| 306 } // namespace net | 277 } // namespace net |
| OLD | NEW |