Home | History | Annotate | Download | only in flip_server
      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 #ifndef NET_TOOLS_FLIP_SERVER_LOADTIME_MEASUREMENT_H__
      6 #define NET_TOOLS_FLIP_SERVER_LOADTIME_MEASUREMENT_H__
      7 #pragma once
      8 
      9 #include <errno.h>
     10 #include <fcntl.h>
     11 #include <stdio.h>
     12 #include <sys/types.h>
     13 #include <unistd.h>
     14 
     15 #include <map>
     16 #include <string>
     17 #include <vector>
     18 
     19 // Class to handle loadtime measure related urls, which all start with testing
     20 // The in memory server has a singleton object of this class. It includes a
     21 // html file containing javascript to go through a list of urls and upload the
     22 // loadtime. The users can modify urls.txt to define the urls they want to
     23 // measure and start with downloading the html file from browser.
     24 class LoadtimeMeasurement {
     25  public:
     26   LoadtimeMeasurement(const std::string& urls_file,
     27                       const std::string& pageload_html_file)
     28       : num_urls_(0), pageload_html_file_(pageload_html_file) {
     29     std::string urls_string;
     30     read_file_to_string(urls_file.c_str(), &urls_string);
     31     split_string(urls_string, '\n', &urls_);
     32     num_urls_ = urls_.size();
     33   }
     34 
     35   // This is the entry function for all the loadtime measure related urls
     36   // It handles the request to html file, get_total_iteration to get number
     37   // of urls in the urls file, get each url, report the loadtime for
     38   // each url, and the test is completed.
     39   void ProcessRequest(const std::string& uri, std::string& output) {
     40     // remove "/testing/" from uri to get the action
     41     std::string action = uri.substr(9);
     42     if (pageload_html_file_.find(action) != std::string::npos) {
     43       read_file_to_string(pageload_html_file_.c_str(), &output);
     44       return;
     45     }
     46     if (action.find("get_total_iteration") == 0) {
     47       char buffer[16];
     48       snprintf(buffer, 16, "%d", num_urls_);
     49       output.append(buffer, strlen(buffer));
     50       return;
     51     }
     52     if (action.find("geturl") == 0) {
     53       size_t b = action.find_first_of('=');
     54       if (b != std::string::npos) {
     55         int num = atoi(action.substr(b + 1).c_str());
     56         if (num < num_urls_) {
     57           output.append(urls_[num]);
     58         }
     59       }
     60       return;
     61     }
     62     if (action.find("test_complete") == 0) {
     63       for (std::map<std::string, int>::const_iterator it = loadtimes_.begin();
     64            it != loadtimes_.end(); ++it) {
     65         LOG(INFO) << it->first << " " << it->second;
     66       }
     67       loadtimes_.clear();
     68       output.append("OK");
     69       return;
     70     }
     71     if (action.find("record_page_load") == 0) {
     72       std::vector<std::string> query;
     73       split_string(action, '?', &query);
     74       std::vector<std::string> params;
     75       split_string(query[1], '&', &params);
     76       std::vector<std::string> url;
     77       std::vector<std::string> loadtime;
     78       split_string(params[1], '=', &url);
     79       split_string(params[2], '=', &loadtime);
     80       loadtimes_[url[1]] = atoi(loadtime[1].c_str());
     81       output.append("OK");
     82       return;
     83     }
     84   }
     85 
     86  private:
     87   void read_file_to_string(const char* filename, std::string* output) {
     88     output->clear();
     89     int fd = open(filename, 0, "r");
     90     if (fd == -1)
     91       return;
     92     char buffer[4096];
     93     ssize_t read_status = read(fd, buffer, sizeof(buffer));
     94     while (read_status > 0) {
     95       output->append(buffer, static_cast<size_t>(read_status));
     96       do {
     97         read_status = read(fd, buffer, sizeof(buffer));
     98       } while (read_status <= 0 && errno == EINTR);
     99     }
    100     close(fd);
    101   }
    102 
    103   void split_string(std::string& str, char sepa,
    104                     std::vector<std::string>* sub_strs) {
    105     size_t b = 0;
    106     size_t e = str.find_first_of(sepa, b);
    107     while (e != std::string::npos && e > b) {
    108       sub_strs->push_back(str.substr(b, e - b));
    109       b = e + 1;
    110       e = str.find_first_of(sepa, b);
    111     }
    112     if (b < str.size()) {
    113       sub_strs->push_back(str.substr(b));
    114     }
    115   }
    116 
    117   int num_urls_;
    118   std::vector<std::string> urls_;
    119   std::map<std::string, int> loadtimes_;
    120   const std::string pageload_html_file_;
    121 };
    122 
    123 #endif  // NET_TOOLS_FLIP_SERVER_LOADTIME_MEASUREMENT_H__
    124 
    125