15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2009 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/output_ordering.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <utility>
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/flip_config.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/sm_connection.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OutputOrdering::PriorityMapPointer::PriorityMapPointer()
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : ring(NULL), alarm_enabled(false) {}
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)OutputOrdering::PriorityMapPointer::~PriorityMapPointer() {}
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double OutputOrdering::server_think_time_in_s_ = 0.0;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OutputOrdering::OutputOrdering(SMConnectionInterface* connection)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : first_data_senders_threshold_(kInitialDataSendersThreshold),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_(connection) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (connection)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    epoll_server_ = connection->epoll_server();
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)OutputOrdering::~OutputOrdering() { Reset(); }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OutputOrdering::Reset() {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!stream_ids_.empty()) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StreamIdToPriorityMap::iterator sitpmi = stream_ids_.begin();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PriorityMapPointer& pmp = sitpmi->second;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pmp.alarm_enabled) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      epoll_server_->UnregisterAlarm(pmp.alarm_token);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_ids_.erase(sitpmi);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  priority_map_.clear();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first_data_senders_.clear();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool OutputOrdering::ExistsInPriorityMaps(uint32 stream_id) const {
453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StreamIdToPriorityMap::const_iterator sitpmi = stream_ids_.find(stream_id);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sitpmi != stream_ids_.end();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OutputOrdering::BeginOutputtingAlarm::BeginOutputtingAlarm(
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OutputOrdering* oo,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OutputOrdering::PriorityMapPointer* pmp,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const MemCacheIter& mci)
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : output_ordering_(oo), pmp_(pmp), mci_(mci), epoll_server_(NULL) {}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OutputOrdering::BeginOutputtingAlarm::~BeginOutputtingAlarm() {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (epoll_server_ && pmp_->alarm_enabled)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    epoll_server_->UnregisterAlarm(pmp_->alarm_token);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 OutputOrdering::BeginOutputtingAlarm::OnAlarm() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnUnregistration();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_ordering_->MoveToActive(pmp_, mci_);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << "ON ALARM! Should now start to output...";
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OutputOrdering::BeginOutputtingAlarm::OnRegistration(
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EpollServer::AlarmRegToken& tok,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EpollServer* eps) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  epoll_server_ = eps;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pmp_->alarm_token = tok;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pmp_->alarm_enabled = true;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OutputOrdering::BeginOutputtingAlarm::OnUnregistration() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pmp_->alarm_enabled = false;
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  delete this;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OutputOrdering::BeginOutputtingAlarm::OnShutdown(EpollServer* eps) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnUnregistration();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OutputOrdering::MoveToActive(PriorityMapPointer* pmp, MemCacheIter mci) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << "Moving to active!";
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  first_data_senders_.push_back(mci);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pmp->ring = &first_data_senders_;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pmp->it = first_data_senders_.end();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --pmp->it;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->ReadyToSend();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OutputOrdering::AddToOutputOrder(const MemCacheIter& mci) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ExistsInPriorityMaps(mci.stream_id))
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "OOps, already was inserted here?!";
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double think_time_in_s = server_think_time_in_s_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string x_server_latency =
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      mci.file_data->headers()->GetHeader("X-Server-Latency").as_string();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!x_server_latency.empty()) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* endp;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double tmp_think_time_in_s = strtod(x_server_latency.c_str(), &endp);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (endp != x_server_latency.c_str() + x_server_latency.size()) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Unable to understand X-Server-Latency of: "
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 << x_server_latency
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 << " for resource: " << mci.file_data->filename().c_str();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      think_time_in_s = tmp_think_time_in_s;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamIdToPriorityMap::iterator sitpmi;
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  sitpmi = stream_ids_.insert(std::pair<uint32, PriorityMapPointer>(
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  mci.stream_id, PriorityMapPointer())).first;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PriorityMapPointer& pmp = sitpmi->second;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BeginOutputtingAlarm* boa = new BeginOutputtingAlarm(this, &pmp, mci);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Server think time: " << think_time_in_s;
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  epoll_server_->RegisterAlarmApproximateDelta(think_time_in_s * 1000000, boa);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OutputOrdering::SpliceToPriorityRing(PriorityRing::iterator pri) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemCacheIter& mci = *pri;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PriorityMap::iterator pmi = priority_map_.find(mci.priority);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pmi == priority_map_.end()) {
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    pmi = priority_map_.insert(std::pair<uint32, PriorityRing>(
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   mci.priority, PriorityRing())).first;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  pmi->second.splice(pmi->second.end(), first_data_senders_, pri);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(mci.stream_id);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sitpmi->second.ring = &(pmi->second);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MemCacheIter* OutputOrdering::GetIter() {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!first_data_senders_.empty()) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MemCacheIter& mci = first_data_senders_.front();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mci.bytes_sent >= first_data_senders_threshold_) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SpliceToPriorityRing(first_data_senders_.begin());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      first_data_senders_.splice(first_data_senders_.end(),
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 first_data_senders_,
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 first_data_senders_.begin());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mci.max_segment_size = kInitialDataSendersThreshold;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &mci;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!priority_map_.empty()) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PriorityRing& first_ring = priority_map_.begin()->second;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (first_ring.empty()) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      priority_map_.erase(priority_map_.begin());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MemCacheIter& mci = first_ring.front();
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    first_ring.splice(first_ring.end(), first_ring, first_ring.begin());
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mci.max_segment_size = kSpdySegmentSize;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &mci;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OutputOrdering::RemoveStreamId(uint32 stream_id) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(stream_id);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sitpmi == stream_ids_.end())
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PriorityMapPointer& pmp = sitpmi->second;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pmp.alarm_enabled)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    epoll_server_->UnregisterAlarm(pmp.alarm_token);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pmp.ring->erase(pmp.it);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stream_ids_.erase(sitpmi);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
176