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