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