server.cpp
Go to the documentation of this file.
00001 #include <cstdio>
00002 #include <fstream>
00003 #include <boost/date_time/posix_time/posix_time.hpp>
00004 #include <boost/algorithm/string.hpp>
00005 
00006 #include <fcgiapp.h>
00007 
00008 #include <megatree/metadata.h>
00009 #include <megatree/tree_common.h>
00010 #include <megatree/node_file.h>
00011 #include <megatree/storage.h>
00012 #include <megatree/storage_factory.h>
00013 
00014 typedef std::map<std::string, boost::shared_ptr<megatree::Storage> > StorageMap;
00015 StorageMap g_storage_map;
00016 
00017 
00018 void emitPong(FCGX_Stream *out)
00019 {
00020   FCGX_FPrintF(out, 
00021                "Content-Type: text/html\r\n"
00022                "\r\n"
00023                "files pong");
00024 }
00025 
00026 void emitTrees(FCGX_Stream *out, const std::vector<std::string>& trees)
00027 {
00028   std::string tree_string;
00029   for (unsigned i=0; i<trees.size(); i++){
00030     tree_string += trees[i];
00031     if (i < trees.size()-1)
00032       tree_string += ",";
00033   }
00034   FCGX_FPrintF(out, 
00035                "Content-Type: text/html\r\n"
00036                "\r\n"
00037                "%s", tree_string.c_str());
00038 }
00039 
00040 
00041 #define NL "<br />\n"
00042 //#define DUMP_VAR(x) FCGX_FPrintF(out, "%s: %s" NL, #x, FCGX_GetParam(#x, envp) ? FCGX_GetParam(#x, envp) : "<null>")
00043 #define DUMP_VAR(x) FCGX_FPrintF(out, "<tr><td>%s</td><td>%s</td></tr>\n",   \
00044                                  #x, FCGX_GetParam(#x, envp) ? FCGX_GetParam(#x, envp) : "<null>")
00045 void emitDump(FCGX_Stream *out, char **envp)
00046 {
00047   FCGX_FPrintF(out, "Content-Type: text/html\r\n");
00048   FCGX_FPrintF(out, "\r\n");
00049   FCGX_FPrintF(out, "<html>\n");
00050   FCGX_FPrintF(out, "<head><title>Dump</title></head>");
00051   FCGX_FPrintF(out, "<body>");
00052   FCGX_FPrintF(out, "<h1>Dump</h1>\n");
00053   
00054   FCGX_FPrintF(out, "<table>\n");
00055   FCGX_FPrintF(out, "<tr><td>Compiled</td><td>%s  %s</td></tr>\n", __DATE__, __TIME__);
00056   FCGX_FPrintF(out, "<tr><td>Pid</td><td>%d</td></tr>\n", getpid());
00057 
00058   FCGX_FPrintF(out, "<tr><td></td><td></td></tr>\n");
00059   FCGX_FPrintF(out, "<tr><td><b>Env</b></td><td></td></tr>\n");
00060   DUMP_VAR(DOCUMENT_ROOT);
00061   DUMP_VAR(CONTENT_LENGTH);
00062   DUMP_VAR(HTTP_REFERER);
00063   DUMP_VAR(HTTP_USER_AGENT);
00064   DUMP_VAR(PATH_INFO);
00065   DUMP_VAR(PATH_TRANSLATED);
00066   DUMP_VAR(QUERY_STRING);
00067   DUMP_VAR(REMOTE_ADDR);
00068   DUMP_VAR(REMOTE_HOST);
00069   DUMP_VAR(REQUEST_METHOD);
00070   DUMP_VAR(SCRIPT_NAME);
00071   DUMP_VAR(SERVER_NAME);
00072   DUMP_VAR(HTTP_COOKIE);
00073   DUMP_VAR(HTTP_HOST);
00074   
00075   FCGX_FPrintF(out, "</table>\n");
00076   FCGX_FPrintF(out, "</body></html>\n");
00077 }
00078 
00079 void emitBox(FCGX_Stream *out)
00080 {
00081   FCGX_FPrintF(out, "Content-Type: application/octet-stream\r\n");
00082   FCGX_FPrintF(out, "\r\n");
00083 
00084   // Cube, from [64,92], with min corner in red, others in white
00085   uint8_t coords[] = {
00086     0, // Children
00087     64, 64, 64,     255, 0, 0,
00088     192, 64, 64,    255, 255, 255,
00089     64, 192, 64,   255, 255, 255,
00090     192, 192, 64,   255, 255, 255,
00091     64, 64, 192,   255, 255, 255,
00092     192, 64, 192,   255, 255, 255,
00093     64, 192, 192,   255, 255, 255,
00094     192, 192, 192,  255, 255, 255
00095   };
00096 
00097   FCGX_PutStr((char*)coords, 1 + 8 * 6 * sizeof(uint8_t), out);
00098 }
00099 
00100 
00101 void sendResult(boost::shared_ptr<FCGX_Request> req, const std::string &filename, const megatree::ByteVec& file_data)
00102 {
00103   if (file_data.empty()) {
00104     FCGX_FPrintF(req->out, "Status: 404 Not Found\r\n");
00105     FCGX_FPrintF(req->out, "Content-Type: text/html\r\n");
00106     FCGX_FPrintF(req->out, "\r\n");
00107     FCGX_FPrintF(req->out, "File not found: %s<br />\n", filename.c_str());
00108   }
00109   else{
00110     FCGX_FPrintF(req->out, "Content-Type: application/octet-stream\r\n");
00111     //FCGX_FPrintF(req->out, "X-Server-Id: " << num << "\r\n", num);
00112     FCGX_FPrintF(req->out, "\r\n");
00113     FCGX_PutStr((char*)&file_data[0], file_data.size(), req->out);
00114   }
00115   
00116   FCGX_Finish_r(req.get());
00117 }
00118 
00119 void emitFile(boost::shared_ptr<FCGX_Request> req, const std::string& tree, const std::string &filename)
00120 {
00121   StorageMap::iterator it = g_storage_map.find(tree);
00122   if (it == g_storage_map.end())
00123     fprintf(stderr, "Server does not support tree %s\n", tree.c_str());
00124   else
00125     it->second->getAsync(filename, boost::bind(&sendResult, req, filename, _1));
00126 }
00127 
00128 
00129 
00130 std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
00131   std::stringstream ss(s);
00132   std::string item;
00133   while(std::getline(ss, item, delim)) {
00134     elems.push_back(item);
00135   }
00136   return elems;
00137 }
00138 
00139 
00140 std::vector<std::string> split(const std::string &s, char delim) {
00141   std::vector<std::string> elems;
00142   return split(s, delim, elems);
00143 }
00144 
00145 
00146 std::map<std::string, std::string> getParams(char* query_string)
00147 {
00148   std::map<std::string, std::string> params;
00149   std::vector<std::string> params_vec = split(std::string(query_string), '&');
00150   for (unsigned i=0; i<params_vec.size(); i++){
00151     std::vector<std::string> param_vec = split(params_vec[i], '=');    
00152     if (param_vec.size() == 2)
00153       params[param_vec[0]] = param_vec[1].c_str();
00154   }
00155   return params;
00156 }
00157 
00158 
00159 
00160 int main(int argc, char** argv)
00161 {
00162   using namespace boost::algorithm;
00163   
00164   int ret = FCGX_Init();
00165   if (ret != 0) {
00166     fprintf(stderr, "Unable to initialize fcgi\n");
00167     return 1;
00168   }
00169 
00170   std::vector<std::string> trees;
00171   //trees.push_back("chappes");
00172   //trees.push_back("bourges");
00173   //trees.push_back("tahoe_all");
00174   //trees.push_back("tahoe_roads");
00175   //trees.push_back("kendall_all");
00176   //trees.push_back("car");
00177 
00178   if (argc > 1)
00179   {
00180     std::string arg = argv[1];
00181     boost::replace_all(arg, "/", "$2f");
00182     trees.push_back(arg);
00183   }
00184 
00185   for (unsigned i=0; i<trees.size(); i++)
00186   {
00187     std::string tree_path = trees[i];
00188     boost::replace_all(tree_path, "$2f", "/");
00189     printf("Path %s\n", tree_path.c_str());
00190     g_storage_map[trees[i]] = megatree::openStorage(tree_path, megatree::VIZ_FORMAT);
00191   }
00192 
00193 
00194   while (true)
00195   {
00196     boost::shared_ptr<FCGX_Request> req(new FCGX_Request);
00197     ret = FCGX_InitRequest(req.get(), 0, 0);
00198     assert(ret == 0);
00199     ret = FCGX_Accept_r(req.get());
00200     assert(ret == 0);
00201 
00202     char* path_string = FCGX_GetParam("PATH_INFO", req->envp);
00203     if(path_string == NULL)
00204     {
00205       fprintf(stderr, "The path string is null!!!!\n");
00206     }
00207 
00208     
00209     std::string request_path(path_string ? path_string : "");
00210     if (request_path == "/ping") {
00211       emitPong(req->out);
00212       FCGX_Finish_r(req.get());
00213     }
00214     else if (request_path == "/box") {
00215       emitBox(req->out);
00216       FCGX_Finish_r(req.get());
00217     }
00218     else if (request_path == "/serve_new_tree") {
00219       char* query_string = FCGX_GetParam("QUERY_STRING", req->envp);
00220       std::map<std::string, std::string> params = getParams(query_string);      
00221       if (params.find("new_tree_name") != params.end()){
00222         std::string new_tree_name = params["new_tree_name"];
00223         std::vector<std::string> name_split = split(new_tree_name, '_');        
00224         if (name_split[0] == "proc" && name_split[1] == "tahoe"){
00225           trees.push_back(new_tree_name);
00226           g_storage_map[new_tree_name] = megatree::openStorage("hbase://wgsc3/" + new_tree_name, megatree::VIZ_FORMAT);
00227           printf("Now also serving tree %s\n", new_tree_name.c_str());
00228           FCGX_FPrintF(req->out, 
00229                        "Content-Type: text/html\r\n"
00230                        "\r\n"
00231                        "%s", new_tree_name.c_str());
00232         }
00233         else
00234           printf("Wrong tree name for serving new tree: %s\n", query_string);
00235       }
00236       else
00237         printf("Wrong parameters for serving new tree: %s\n", query_string);
00238       FCGX_Finish_r(req.get());
00239     }
00240     else if (request_path == "/supported_trees") {
00241       emitTrees(req->out, trees);
00242       FCGX_Finish_r(req.get());
00243     }
00244     else if (starts_with(request_path, "/")) {
00245       int slash = request_path.substr(1).find('/');
00246       std::string tree = request_path.substr(1, slash);
00247       std::string filename = request_path.substr(slash+2);
00248       printf("Received request for tree %s and file %s\n", tree.c_str(), filename.c_str());
00249       emitFile(req, tree, filename);
00250     }
00251     else {
00252       emitDump(req->out, req->envp);
00253       FCGX_Finish_r(req.get());
00254     }
00255   }
00256   
00257   return 0;
00258 }


megatree_server
Author(s): Wim Meeussen
autogenerated on Mon Dec 2 2013 13:01:37