OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 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. | |
4 | |
5 #include "net/tools/flip_server/output_ordering.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "net/tools/flip_server/flip_config.h" | |
10 #include "net/tools/flip_server/sm_connection.h" | |
11 | |
12 namespace net { | |
13 | |
14 OutputOrdering::PriorityMapPointer::PriorityMapPointer() | |
15 : ring(NULL), alarm_enabled(false) {} | |
16 | |
17 OutputOrdering::PriorityMapPointer::PriorityMapPointer( | |
18 const PriorityMapPointer& other) = default; | |
19 | |
20 OutputOrdering::PriorityMapPointer::~PriorityMapPointer() {} | |
21 | |
22 // static | |
23 double OutputOrdering::server_think_time_in_s_ = 0.0; | |
24 | |
25 OutputOrdering::OutputOrdering(SMConnectionInterface* connection) | |
26 : first_data_senders_threshold_(kInitialDataSendersThreshold), | |
27 connection_(connection) { | |
28 if (connection) | |
29 epoll_server_ = connection->epoll_server(); | |
30 } | |
31 | |
32 OutputOrdering::~OutputOrdering() { Reset(); } | |
33 | |
34 void OutputOrdering::Reset() { | |
35 while (!stream_ids_.empty()) { | |
36 StreamIdToPriorityMap::iterator sitpmi = stream_ids_.begin(); | |
37 PriorityMapPointer& pmp = sitpmi->second; | |
38 if (pmp.alarm_enabled) { | |
39 epoll_server_->UnregisterAlarm(pmp.alarm_token); | |
40 } | |
41 stream_ids_.erase(sitpmi); | |
42 } | |
43 priority_map_.clear(); | |
44 first_data_senders_.clear(); | |
45 } | |
46 | |
47 bool OutputOrdering::ExistsInPriorityMaps(uint32_t stream_id) const { | |
48 StreamIdToPriorityMap::const_iterator sitpmi = stream_ids_.find(stream_id); | |
49 return sitpmi != stream_ids_.end(); | |
50 } | |
51 | |
52 OutputOrdering::BeginOutputtingAlarm::BeginOutputtingAlarm( | |
53 OutputOrdering* oo, | |
54 OutputOrdering::PriorityMapPointer* pmp, | |
55 const MemCacheIter& mci) | |
56 : output_ordering_(oo), pmp_(pmp), mci_(mci), epoll_server_(NULL) {} | |
57 | |
58 OutputOrdering::BeginOutputtingAlarm::~BeginOutputtingAlarm() { | |
59 if (epoll_server_ && pmp_->alarm_enabled) | |
60 epoll_server_->UnregisterAlarm(pmp_->alarm_token); | |
61 } | |
62 | |
63 int64_t OutputOrdering::BeginOutputtingAlarm::OnAlarm() { | |
64 OnUnregistration(); | |
65 output_ordering_->MoveToActive(pmp_, mci_); | |
66 VLOG(2) << "ON ALARM! Should now start to output..."; | |
67 delete this; | |
68 return 0; | |
69 } | |
70 | |
71 void OutputOrdering::BeginOutputtingAlarm::OnRegistration( | |
72 const EpollServer::AlarmRegToken& tok, | |
73 EpollServer* eps) { | |
74 epoll_server_ = eps; | |
75 pmp_->alarm_token = tok; | |
76 pmp_->alarm_enabled = true; | |
77 } | |
78 | |
79 void OutputOrdering::BeginOutputtingAlarm::OnUnregistration() { | |
80 pmp_->alarm_enabled = false; | |
81 delete this; | |
82 } | |
83 | |
84 void OutputOrdering::BeginOutputtingAlarm::OnShutdown(EpollServer* eps) { | |
85 OnUnregistration(); | |
86 } | |
87 | |
88 void OutputOrdering::MoveToActive(PriorityMapPointer* pmp, MemCacheIter mci) { | |
89 VLOG(2) << "Moving to active!"; | |
90 first_data_senders_.push_back(mci); | |
91 pmp->ring = &first_data_senders_; | |
92 pmp->it = first_data_senders_.end(); | |
93 --pmp->it; | |
94 connection_->ReadyToSend(); | |
95 } | |
96 | |
97 void OutputOrdering::AddToOutputOrder(const MemCacheIter& mci) { | |
98 if (ExistsInPriorityMaps(mci.stream_id)) | |
99 LOG(ERROR) << "OOps, already was inserted here?!"; | |
100 | |
101 double think_time_in_s = server_think_time_in_s_; | |
102 std::string x_server_latency = | |
103 mci.file_data->headers()->GetHeader("X-Server-Latency").as_string(); | |
104 if (!x_server_latency.empty()) { | |
105 char* endp; | |
106 double tmp_think_time_in_s = strtod(x_server_latency.c_str(), &endp); | |
107 if (endp != x_server_latency.c_str() + x_server_latency.size()) { | |
108 LOG(ERROR) << "Unable to understand X-Server-Latency of: " | |
109 << x_server_latency | |
110 << " for resource: " << mci.file_data->filename().c_str(); | |
111 } else { | |
112 think_time_in_s = tmp_think_time_in_s; | |
113 } | |
114 } | |
115 StreamIdToPriorityMap::iterator sitpmi; | |
116 sitpmi = stream_ids_.insert(std::pair<uint32_t, PriorityMapPointer>( | |
117 mci.stream_id, PriorityMapPointer())) | |
118 .first; | |
119 PriorityMapPointer& pmp = sitpmi->second; | |
120 | |
121 BeginOutputtingAlarm* boa = new BeginOutputtingAlarm(this, &pmp, mci); | |
122 VLOG(1) << "Server think time: " << think_time_in_s; | |
123 epoll_server_->RegisterAlarmApproximateDelta(think_time_in_s * 1000000, boa); | |
124 } | |
125 | |
126 void OutputOrdering::SpliceToPriorityRing(PriorityRing::iterator pri) { | |
127 MemCacheIter& mci = *pri; | |
128 PriorityMap::iterator pmi = priority_map_.find(mci.priority); | |
129 if (pmi == priority_map_.end()) { | |
130 pmi = priority_map_.insert(std::pair<uint32_t, PriorityRing>( | |
131 mci.priority, PriorityRing())) | |
132 .first; | |
133 } | |
134 | |
135 pmi->second.splice(pmi->second.end(), first_data_senders_, pri); | |
136 StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(mci.stream_id); | |
137 sitpmi->second.ring = &(pmi->second); | |
138 } | |
139 | |
140 MemCacheIter* OutputOrdering::GetIter() { | |
141 while (!first_data_senders_.empty()) { | |
142 MemCacheIter& mci = first_data_senders_.front(); | |
143 if (mci.bytes_sent >= first_data_senders_threshold_) { | |
144 SpliceToPriorityRing(first_data_senders_.begin()); | |
145 } else { | |
146 first_data_senders_.splice(first_data_senders_.end(), | |
147 first_data_senders_, | |
148 first_data_senders_.begin()); | |
149 mci.max_segment_size = kInitialDataSendersThreshold; | |
150 return &mci; | |
151 } | |
152 } | |
153 while (!priority_map_.empty()) { | |
154 PriorityRing& first_ring = priority_map_.begin()->second; | |
155 if (first_ring.empty()) { | |
156 priority_map_.erase(priority_map_.begin()); | |
157 continue; | |
158 } | |
159 MemCacheIter& mci = first_ring.front(); | |
160 first_ring.splice(first_ring.end(), first_ring, first_ring.begin()); | |
161 mci.max_segment_size = kSpdySegmentSize; | |
162 return &mci; | |
163 } | |
164 return NULL; | |
165 } | |
166 | |
167 void OutputOrdering::RemoveStreamId(uint32_t stream_id) { | |
168 StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(stream_id); | |
169 if (sitpmi == stream_ids_.end()) | |
170 return; | |
171 | |
172 PriorityMapPointer& pmp = sitpmi->second; | |
173 if (pmp.alarm_enabled) | |
174 epoll_server_->UnregisterAlarm(pmp.alarm_token); | |
175 else | |
176 pmp.ring->erase(pmp.it); | |
177 stream_ids_.erase(sitpmi); | |
178 } | |
179 | |
180 } // namespace net | |
OLD | NEW |