Windows should animate when they are about to get docked at screen edges.
[chromium-blink-merge.git] / net / tools / flip_server / output_ordering.cc
blob22fd08ac1c19a494a707959d9a0770982e876b1a
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.
5 #include "net/tools/flip_server/output_ordering.h"
7 #include "net/tools/flip_server/flip_config.h"
8 #include "net/tools/flip_server/sm_connection.h"
11 namespace net {
13 OutputOrdering::PriorityMapPointer::PriorityMapPointer()
14 : ring(NULL),
15 alarm_enabled(false) {
18 // static
19 double OutputOrdering::server_think_time_in_s_ = 0.0;
21 OutputOrdering::OutputOrdering(SMConnectionInterface* connection)
22 : first_data_senders_threshold_(kInitialDataSendersThreshold),
23 connection_(connection) {
24 if (connection)
25 epoll_server_ = connection->epoll_server();
28 OutputOrdering::~OutputOrdering() {}
30 void OutputOrdering::Reset() {
31 while (!stream_ids_.empty()) {
32 StreamIdToPriorityMap::iterator sitpmi = stream_ids_.begin();
33 PriorityMapPointer& pmp = sitpmi->second;
34 if (pmp.alarm_enabled) {
35 epoll_server_->UnregisterAlarm(pmp.alarm_token);
37 stream_ids_.erase(sitpmi);
39 priority_map_.clear();
40 first_data_senders_.clear();
43 bool OutputOrdering::ExistsInPriorityMaps(uint32 stream_id) {
44 StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(stream_id);
45 return sitpmi != stream_ids_.end();
48 OutputOrdering::BeginOutputtingAlarm::BeginOutputtingAlarm(
49 OutputOrdering* oo,
50 OutputOrdering::PriorityMapPointer* pmp,
51 const MemCacheIter& mci)
52 : output_ordering_(oo),
53 pmp_(pmp),
54 mci_(mci),
55 epoll_server_(NULL) {
58 OutputOrdering::BeginOutputtingAlarm::~BeginOutputtingAlarm() {
59 if (epoll_server_ && pmp_->alarm_enabled)
60 epoll_server_->UnregisterAlarm(pmp_->alarm_token);
63 int64 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;
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;
79 void OutputOrdering::BeginOutputtingAlarm::OnUnregistration() {
80 pmp_->alarm_enabled = false;
83 void OutputOrdering::BeginOutputtingAlarm::OnShutdown(EpollServer* eps) {
84 OnUnregistration();
87 void OutputOrdering::MoveToActive(PriorityMapPointer* pmp, MemCacheIter mci) {
88 VLOG(2) << "Moving to active!";
89 first_data_senders_.push_back(mci);
90 pmp->ring = &first_data_senders_;
91 pmp->it = first_data_senders_.end();
92 --pmp->it;
93 connection_->ReadyToSend();
96 void OutputOrdering::AddToOutputOrder(const MemCacheIter& mci) {
97 if (ExistsInPriorityMaps(mci.stream_id))
98 LOG(ERROR) << "OOps, already was inserted here?!";
100 double think_time_in_s = server_think_time_in_s_;
101 std::string x_server_latency =
102 mci.file_data->headers()->GetHeader("X-Server-Latency").as_string();
103 if (!x_server_latency.empty()) {
104 char* endp;
105 double tmp_think_time_in_s = strtod(x_server_latency.c_str(), &endp);
106 if (endp != x_server_latency.c_str() + x_server_latency.size()) {
107 LOG(ERROR) << "Unable to understand X-Server-Latency of: "
108 << x_server_latency << " for resource: "
109 << mci.file_data->filename().c_str();
110 } else {
111 think_time_in_s = tmp_think_time_in_s;
114 StreamIdToPriorityMap::iterator sitpmi;
115 sitpmi = stream_ids_.insert(
116 std::pair<uint32, PriorityMapPointer>(mci.stream_id,
117 PriorityMapPointer())).first;
118 PriorityMapPointer& pmp = sitpmi->second;
120 BeginOutputtingAlarm* boa = new BeginOutputtingAlarm(this, &pmp, mci);
121 VLOG(1) << "Server think time: " << think_time_in_s;
122 epoll_server_->RegisterAlarmApproximateDelta(
123 think_time_in_s * 1000000, boa);
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(
131 std::pair<uint32, PriorityRing>(mci.priority, PriorityRing())).first;
134 pmi->second.splice(pmi->second.end(),
135 first_data_senders_,
136 pri);
137 StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(mci.stream_id);
138 sitpmi->second.ring = &(pmi->second);
141 MemCacheIter* OutputOrdering::GetIter() {
142 while (!first_data_senders_.empty()) {
143 MemCacheIter& mci = first_data_senders_.front();
144 if (mci.bytes_sent >= first_data_senders_threshold_) {
145 SpliceToPriorityRing(first_data_senders_.begin());
146 } else {
147 first_data_senders_.splice(first_data_senders_.end(),
148 first_data_senders_,
149 first_data_senders_.begin());
150 mci.max_segment_size = kInitialDataSendersThreshold;
151 return &mci;
154 while (!priority_map_.empty()) {
155 PriorityRing& first_ring = priority_map_.begin()->second;
156 if (first_ring.empty()) {
157 priority_map_.erase(priority_map_.begin());
158 continue;
160 MemCacheIter& mci = first_ring.front();
161 first_ring.splice(first_ring.end(),
162 first_ring,
163 first_ring.begin());
164 mci.max_segment_size = kSpdySegmentSize;
165 return &mci;
167 return NULL;
170 void OutputOrdering::RemoveStreamId(uint32 stream_id) {
171 StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(stream_id);
172 if (sitpmi == stream_ids_.end())
173 return;
175 PriorityMapPointer& pmp = sitpmi->second;
176 if (pmp.alarm_enabled)
177 epoll_server_->UnregisterAlarm(pmp.alarm_token);
178 else
179 pmp.ring->erase(pmp.it);
180 stream_ids_.erase(sitpmi);
183 } // namespace net