<commit_before>/// \file player.cpp
/// Holds all code for the MistPlayer application used for VoD streams.

#include <iostream>//for std::cerr
#include <stdio.h> //for fileno
#include <stdlib.h> //for atoi
#include <sys/time.h>
#include <mist/dtsc.h>
#include <mist/json.h>
#include <mist/config.h>
#include <mist/socket.h>
#include <mist/timing.h>
#include <mist/procs.h>

//under cygwin, recv blocks for ~15ms if no data is available.
//This is a hack to keep performance decent with that bug present.
#ifdef __CYGWIN__
#define CYG_DEFI int cyg_count;
#define CYG_INCR cyg_count++;
#define CYG_LOOP (cyg_count % 20 == 0) &&
#else
#define CYG_DEFI
#define CYG_INCR
#define CYG_LOOP
#endif

///Converts a stats line to up, down, host, connector and conntime values.
class Stats{
  public:
    unsigned int up;///<The amount of bytes sent upstream.
    unsigned int down;///<The amount of bytes received downstream.
    std::string host;///<The connected host.
    std::string connector;///<The connector the user is connected with.
    unsigned int conntime;///<The amount of time the user is connected.
    ///\brief Default stats constructor.
    ///
    ///Should not be used.
    Stats(){
      up = 0;
      down = 0;
      conntime = 0;
    }
    ;
    ///\brief Stats constructor reading a string.
    ///
    ///Reads a stats string and parses it to the internal representation.
    ///\param s The string of stats.
    Stats(std::string s){
      size_t f = s.find(' ');
      if (f != std::string::npos){
        host = s.substr(0, f);
        s.erase(0, f + 1);
      }
      f = s.find(' ');
      if (f != std::string::npos){
        connector = s.substr(0, f);
        s.erase(0, f + 1);
      }
      f = s.find(' ');
      if (f != std::string::npos){
        conntime = atoi(s.substr(0, f).c_str());
        s.erase(0, f + 1);
      }
      f = s.find(' ');
      if (f != std::string::npos){
        up = atoi(s.substr(0, f).c_str());
        s.erase(0, f + 1);
        down = atoi(s.c_str());
      }
    }
};

int main(int argc, char** argv){
  Util::Config conf(argv[0], PACKAGE_VERSION);
  conf.addOption("filename", JSON::fromString("{\"arg_num\":1, \"help\":\"Name of the file to write to stdout.\"}"));
  conf.parseArgs(argc, argv);
  conf.activate();
  int playing = 0;

  Socket::Connection in_out = Socket::Connection(fileno(stdout), fileno(stdin));

  DTSC::File source = DTSC::File(conf.getString("filename"));
  JSON::Value meta = source.getMeta();

  //send the header
  std::string meta_str = meta.toNetPacked();
  in_out.Send(meta_str);

  if ( !(meta.isMember("keytime") && meta.isMember("keybpos") && meta.isMember("keynum") && meta.isMember("keylen") && meta.isMember("frags"))
      && meta.isMember("video")){
    //file needs to be DTSCFix'ed! Run MistDTSCFix executable on it first
    std::cerr << "Calculating / writing / updating VoD metadata..." << std::endl;
    Util::Procs::Start("Fixer", Util::getMyPath() + "MistDTSCFix " + conf.getString("filename"));
    while (Util::Procs::isActive("Fixer")){
      Util::sleep(5000);
    }
    std::cerr << "Done! Aborting this request to make sure all goes well." << std::endl;
    return 1;
  }

  JSON::Value pausemark;
  pausemark["datatype"] = "pause_marker";
  pausemark["time"] = (long long int)0;

  Socket::Connection StatsSocket = Socket::Connection("/tmp/mist/statistics", true);
  int lasttime = Util::epoch(); //time last packet was sent

  if (meta["video"]["keyms"].asInt() < 11){
    meta["video"]["keyms"] = (long long int)1000;
  }
  JSON::Value last_pack;

  bool meta_sent = false;
  int playUntil = -1;
  long long now, lastTime = 0; //for timing of sending packets
  long long bench = 0; //for benchmarking
  std::set<int> newSelect;
  Stats sts;
  CYG_DEFI

  while (in_out.connected() && (Util::epoch() - lasttime < 60) && conf.is_active){
    CYG_INCR
    if (CYG_LOOP in_out.spool()){
      while (in_out.Received().size()){
        //delete anything that doesn't end with a newline
        if ( *(in_out.Received().get().rbegin()) != '\n'){
          in_out.Received().get().clear();
          continue;
        }
        in_out.Received().get().resize(in_out.Received().get().size() - 1);
        if ( !in_out.Received().get().empty()){
          switch (in_out.Received().get()[0]){
            case 'P': { //Push
#if DEBUG >= 4
              std::cerr << "Received push - ignoring (" << in_out.Received().get() << ")" << std::endl;
#endif
              in_out.close(); //pushing to VoD makes no sense
              break;
            }
            case 'S': { //Stats
              if ( !StatsSocket.connected()){
                StatsSocket = Socket::Connection("/tmp/mist/statistics", true);
              }
              if (StatsSocket.connected()){
                sts = Stats(in_out.Received().get().substr(2));
                JSON::Value json_sts;
                json_sts["vod"]["down"] = (long long int)sts.down;
                json_sts["vod"]["up"] = (long long int)sts.up;
                json_sts["vod"]["time"] = (long long int)sts.conntime;
                json_sts["vod"]["host"] = sts.host;
                json_sts["vod"]["connector"] = sts.connector;
                json_sts["vod"]["filename"] = conf.getString("filename");
                json_sts["vod"]["now"] = Util::epoch();
                json_sts["vod"]["start"] = Util::epoch() - sts.conntime;
                if ( !meta_sent){
                  json_sts["vod"]["meta"] = meta;
                  for (JSON::ObjIter oIt = json_sts["vod"]["meta"]["tracks"].ObjBegin(); oIt != json_sts["vod"]["meta"]["tracks"].ObjEnd(); oIt++){
                    oIt->second.removeMember("init");
                    oIt->second.removeMember("keys");
                    oIt->second.removeMember("frags");
                  }
                  meta_sent = true;
                }
                StatsSocket.Send(json_sts.toString().c_str());
                StatsSocket.Send("\n\n");
                StatsSocket.flush();
              }
              break;
            }
            case 's': { //second-seek
              int ms = JSON::Value(in_out.Received().get().substr(2)).asInt();
              bool ret = source.seek_time(ms);
              lasttime = 0;
              break;
            }
            case 'p': { //play
              playing = -1;
              lasttime = 0;
              in_out.setBlocking(false);
              if (in_out.Received().get().size() >= 2){
                playUntil = atoi(in_out.Received().get().substr(2).c_str());
                bench = Util::getMS();
              }else{
                playUntil = 0;
              }
              break;
            }
            case 'o': { //once-play
              if (playing <= 0){
                playing = 1;
              }
              ++playing;
              in_out.setBlocking(false);
              bench = Util::getMS();
              break;
            }
            case 'q': { //quit-playing
              playing = 0;
              in_out.setBlocking(true);
              break;
            }
            case 't': {
              newSelect.clear();
              std::string tmp = in_out.Received().get().substr(2);
              while (tmp != ""){
                newSelect.insert(atoi(tmp.substr(0,tmp.find(' ')).c_str()));
                if (tmp.find(' ') != std::string::npos){
                  tmp.erase(0,tmp.find(' ')+1);
                }else{
                  tmp = "";
                }
              }
              source.selectTracks(newSelect);
              break;
            }
#if DEBUG >= 4
            default: {
              std::cerr << "MistPlayer received an unknown command: " << in_out.Received().get() << std::endl;
              break;
            }
#endif
          }
          in_out.Received().get().clear();
        }
      }
    }
    if (playing != 0){
      now = Util::getMS();
      source.seekNext();
      if ( !source.getJSON()){
        playing = 0;
      }
      if (source.atKeyframe()){
        if (playing > 0){
          --playing;
        }
      }
      if (lastTime == 0){
        lastTime = now - source.getJSON()["time"].asInt();
      }
      if (playing == -1 && playUntil == 0 && source.getJSON()["time"].asInt() > now - lastTime + 2500){
        std::cerr << (source.getJSON()["time"].asInt() - (now - lastTime)) << " sleepytimes" << std::endl;
        Util::sleep(source.getJSON()["time"].asInt() - (now - lastTime));
      }
      if ( playUntil && playUntil < source.getJSON()["time"].asInt()){
        playing = 0;
      }
      if (playing == 0){
#if DEBUG >= 4
        std::cerr << "Completed VoD request in MistPlayer (" << (Util::getMS() - bench) << "ms)" << std::endl;
#endif
        pausemark["time"] = source.getJSON()["time"];
        pausemark.netPrepare();
        in_out.SendNow(pausemark.toNetPacked());
        in_out.setBlocking(true);
      }else{
        lasttime = Util::epoch();
        //insert proper header for this type of data
        in_out.Send("DTP2");
        //insert the packet length
        unsigned int size = htonl( source.getPacket().size());
        in_out.Send((char*) &size, 4);
        in_out.SendNow(source.getPacket());
      }
    }else{
      Util::sleep(10);
    }
  }
  StatsSocket.close();
  in_out.close();
#if DEBUG >= 5
  if (Util::epoch() - lasttime < 60){
    std::cerr << "MistPlayer exited (disconnect)." << std::endl;
  }else{
    std::cerr << "MistPlayer exited (command timeout)." << std::endl;
  }
#endif
  return 0;
}
<commit_msg>Player optimisation<commit_after>/// \file player.cpp
/// Holds all code for the MistPlayer application used for VoD streams.

#include <iostream>//for std::cerr
#include <stdio.h> //for fileno
#include <stdlib.h> //for atoi
#include <sys/time.h>
#include <mist/dtsc.h>
#include <mist/json.h>
#include <mist/config.h>
#include <mist/socket.h>
#include <mist/timing.h>
#include <mist/procs.h>

//under cygwin, recv blocks for ~15ms if no data is available.
//This is a hack to keep performance decent with that bug present.
#ifdef __CYGWIN__
#define CYG_DEFI int cyg_count;
#define CYG_INCR cyg_count++;
#define CYG_LOOP (cyg_count % 20 == 0) &&
#else
#define CYG_DEFI
#define CYG_INCR
#define CYG_LOOP
#endif

///Converts a stats line to up, down, host, connector and conntime values.
class Stats{
  public:
    unsigned int up;///<The amount of bytes sent upstream.
    unsigned int down;///<The amount of bytes received downstream.
    std::string host;///<The connected host.
    std::string connector;///<The connector the user is connected with.
    unsigned int conntime;///<The amount of time the user is connected.
    ///\brief Default stats constructor.
    ///
    ///Should not be used.
    Stats(){
      up = 0;
      down = 0;
      conntime = 0;
    }
    ;
    ///\brief Stats constructor reading a string.
    ///
    ///Reads a stats string and parses it to the internal representation.
    ///\param s The string of stats.
    Stats(std::string s){
      size_t f = s.find(' ');
      if (f != std::string::npos){
        host = s.substr(0, f);
        s.erase(0, f + 1);
      }
      f = s.find(' ');
      if (f != std::string::npos){
        connector = s.substr(0, f);
        s.erase(0, f + 1);
      }
      f = s.find(' ');
      if (f != std::string::npos){
        conntime = atoi(s.substr(0, f).c_str());
        s.erase(0, f + 1);
      }
      f = s.find(' ');
      if (f != std::string::npos){
        up = atoi(s.substr(0, f).c_str());
        s.erase(0, f + 1);
        down = atoi(s.c_str());
      }
    }
};

int main(int argc, char** argv){
  Util::Config conf(argv[0], PACKAGE_VERSION);
  conf.addOption("filename", JSON::fromString("{\"arg_num\":1, \"help\":\"Name of the file to write to stdout.\"}"));
  conf.parseArgs(argc, argv);
  conf.activate();
  int playing = 0;

  Socket::Connection in_out = Socket::Connection(fileno(stdout), fileno(stdin));

  DTSC::File source = DTSC::File(conf.getString("filename"));
  JSON::Value meta = source.getMeta();

  //send the header
  std::string meta_str = meta.toNetPacked();
  in_out.Send(meta_str);

  if ( !(meta.isMember("keytime") && meta.isMember("keybpos") && meta.isMember("keynum") && meta.isMember("keylen") && meta.isMember("frags"))
      && meta.isMember("video")){
    //file needs to be DTSCFix'ed! Run MistDTSCFix executable on it first
    std::cerr << "Calculating / writing / updating VoD metadata..." << std::endl;
    Util::Procs::Start("Fixer", Util::getMyPath() + "MistDTSCFix " + conf.getString("filename"));
    while (Util::Procs::isActive("Fixer")){
      Util::sleep(5000);
    }
    std::cerr << "Done! Aborting this request to make sure all goes well." << std::endl;
    return 1;
  }

  JSON::Value pausemark;
  pausemark["datatype"] = "pause_marker";
  pausemark["time"] = (long long int)0;

  Socket::Connection StatsSocket = Socket::Connection("/tmp/mist/statistics", true);
  int lasttime = Util::epoch(); //time last packet was sent

  if (meta["video"]["keyms"].asInt() < 11){
    meta["video"]["keyms"] = (long long int)1000;
  }
  JSON::Value last_pack;

  bool meta_sent = false;
  int playUntil = -1;
  long long now, lastTime = 0; //for timing of sending packets
  long long bench = 0; //for benchmarking
  std::set<int> newSelect;
  Stats sts;
  CYG_DEFI

  while (in_out.connected() && (Util::epoch() - lasttime < 60) && conf.is_active){
    CYG_INCR
    if (CYG_LOOP in_out.spool()){
      while (in_out.Received().size()){
        //delete anything that doesn't end with a newline
        if ( *(in_out.Received().get().rbegin()) != '\n'){
          in_out.Received().get().clear();
          continue;
        }
        in_out.Received().get().resize(in_out.Received().get().size() - 1);
        if ( !in_out.Received().get().empty()){
          switch (in_out.Received().get()[0]){
            case 'P': { //Push
#if DEBUG >= 4
              std::cerr << "Received push - ignoring (" << in_out.Received().get() << ")" << std::endl;
#endif
              in_out.close(); //pushing to VoD makes no sense
              break;
            }
            case 'S': { //Stats
              if ( !StatsSocket.connected()){
                StatsSocket = Socket::Connection("/tmp/mist/statistics", true);
              }
              if (StatsSocket.connected()){
                sts = Stats(in_out.Received().get().substr(2));
                JSON::Value json_sts;
                json_sts["vod"]["down"] = (long long int)sts.down;
                json_sts["vod"]["up"] = (long long int)sts.up;
                json_sts["vod"]["time"] = (long long int)sts.conntime;
                json_sts["vod"]["host"] = sts.host;
                json_sts["vod"]["connector"] = sts.connector;
                json_sts["vod"]["filename"] = conf.getString("filename");
                json_sts["vod"]["now"] = Util::epoch();
                json_sts["vod"]["start"] = Util::epoch() - sts.conntime;
                if ( !meta_sent){
                  json_sts["vod"]["meta"] = meta;
                  for (JSON::ObjIter oIt = json_sts["vod"]["meta"]["tracks"].ObjBegin(); oIt != json_sts["vod"]["meta"]["tracks"].ObjEnd(); oIt++){
                    oIt->second.removeMember("init");
                    oIt->second.removeMember("keys");
                    oIt->second.removeMember("frags");
                  }
                  meta_sent = true;
                }
                StatsSocket.Send(json_sts.toString().c_str());
                StatsSocket.Send("\n\n");
                StatsSocket.flush();
              }
              break;
            }
            case 's': { //second-seek
              int ms = JSON::Value(in_out.Received().get().substr(2)).asInt();
              bool ret = source.seek_time(ms);
              lasttime = 0;
              lastTime = 0;
              break;
            }
            case 'p': { //play
              playing = -1;
              lasttime = 0;
              in_out.setBlocking(false);
              if (in_out.Received().get().size() >= 2){
                playUntil = atoi(in_out.Received().get().substr(2).c_str());
                bench = Util::getMS();
              }else{
                playUntil = 0;
              }
              break;
            }
            case 'o': { //once-play
              if (playing <= 0){
                playing = 1;
              }
              ++playing;
              in_out.setBlocking(false);
              bench = Util::getMS();
              break;
            }
            case 'q': { //quit-playing
              playing = 0;
              in_out.setBlocking(true);
              break;
            }
            case 't': {
              newSelect.clear();
              std::string tmp = in_out.Received().get().substr(2);
              while (tmp != ""){
                newSelect.insert(atoi(tmp.substr(0,tmp.find(' ')).c_str()));
                if (tmp.find(' ') != std::string::npos){
                  tmp.erase(0,tmp.find(' ')+1);
                }else{
                  tmp = "";
                }
              }
              source.selectTracks(newSelect);
              break;
            }
#if DEBUG >= 4
            default: {
              std::cerr << "MistPlayer received an unknown command: " << in_out.Received().get() << std::endl;
              break;
            }
#endif
          }
          in_out.Received().get().clear();
        }
      }
    }
    if (playing != 0){
      now = Util::getMS();
      source.seekNext();
      if ( !source.getJSON()){
        playing = 0;
      }
      if (source.atKeyframe()){
        if (playing > 0){
          --playing;
        }
      }
      if (lastTime == 0){
        lastTime = now - source.getJSON()["time"].asInt();
      }
      if (playing == -1 && playUntil == 0 && source.getJSON()["time"].asInt() > now - lastTime + 1000){
        //std::cerr << (source.getJSON()["time"].asInt() - (now - lastTime)) << " ms sleep" << std::endl;
        Util::sleep(source.getJSON()["time"].asInt() - (now - lastTime));
      }
      if ( playUntil && playUntil < source.getJSON()["time"].asInt()){
        playing = 0;
      }
      if (playing == 0){
#if DEBUG >= 4
        std::cerr << "Completed VoD request in MistPlayer (" << (Util::getMS() - bench) << "ms)" << std::endl;
#endif
        pausemark["time"] = source.getJSON()["time"];
        pausemark.netPrepare();
        in_out.SendNow(pausemark.toNetPacked());
        in_out.setBlocking(true);
      }else{
        lasttime = Util::epoch();
        //insert proper header for this type of data
        in_out.Send("DTP2");
        //insert the packet length
        unsigned int size = htonl( source.getPacket().size());
        in_out.Send((char*) &size, 4);
        in_out.SendNow(source.getPacket());
      }
    }else{
      Util::sleep(10);
    }
  }
  StatsSocket.close();
  in_out.close();
#if DEBUG >= 5
  if (Util::epoch() - lasttime < 60){
    std::cerr << "MistPlayer exited (disconnect)." << std::endl;
  }else{
    std::cerr << "MistPlayer exited (command timeout)." << std::endl;
  }
#endif
  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/shell/shell_render_process_observer.h"

#include "base/command_line.h"
#include "content/public/common/content_client.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/test/layouttest_support.h"
#include "content/shell/shell_content_renderer_client.h"
#include "content/shell/shell_messages.h"
#include "content/shell/shell_switches.h"
#include "content/shell/webkit_test_runner.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Tools/DumpRenderTree/chromium/TestRunner/public/WebTestInterfaces.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/support/gc_extension.h"

using WebKit::WebFrame;
using WebKit::WebRuntimeFeatures;
using WebTestRunner::WebTestDelegate;
using WebTestRunner::WebTestInterfaces;

namespace content {

namespace {
ShellRenderProcessObserver* g_instance = NULL;
}

// static
ShellRenderProcessObserver* ShellRenderProcessObserver::GetInstance() {
  return g_instance;
}

ShellRenderProcessObserver::ShellRenderProcessObserver()
    : main_test_runner_(NULL),
      test_delegate_(NULL) {
  CHECK(!g_instance);
  g_instance = this;
  RenderThread::Get()->AddObserver(this);
  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
    return;
  WebRuntimeFeatures::enableInputTypeDateTime(true);
  WebRuntimeFeatures::enableInputTypeDateTimeLocal(true);
  WebRuntimeFeatures::enableInputTypeMonth(true);
  WebRuntimeFeatures::enableInputTypeTime(true);
  WebRuntimeFeatures::enableInputTypeWeek(true);
  WebRuntimeFeatures::enableCanvasPath(true);
  DisableAppCacheLogging();
  EnableDevToolsFrontendTesting();
  EnableShortCircuitSizeUpdates();
  DoNotSendFocusEvents();
}

ShellRenderProcessObserver::~ShellRenderProcessObserver() {
  CHECK(g_instance == this);
  g_instance = NULL;
}

void ShellRenderProcessObserver::SetTestDelegate(WebTestDelegate* delegate) {
  test_interfaces_->setDelegate(delegate);
  test_delegate_ = delegate;
}

void ShellRenderProcessObserver::SetMainWindow(RenderView* view) {
  WebKitTestRunner* test_runner = WebKitTestRunner::Get(view);
  test_interfaces_->setWebView(view->GetWebView(), test_runner->proxy());
  main_test_runner_ = test_runner;
}

void ShellRenderProcessObserver::WebKitInitialized() {
  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
    return;

  // We always expose GC to layout tests.
  webkit_glue::SetJavaScriptFlags(" --expose-gc");
  RenderThread::Get()->RegisterExtension(extensions_v8::GCExtension::Get());

  test_interfaces_.reset(new WebTestInterfaces);
  test_interfaces_->resetAll();
}

bool ShellRenderProcessObserver::OnControlMessageReceived(
    const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(ShellRenderProcessObserver, message)
    IPC_MESSAGE_HANDLER(ShellViewMsg_ResetAll, OnResetAll)
    IPC_MESSAGE_HANDLER(ShellViewMsg_SetWebKitSourceDir, OnSetWebKitSourceDir)
    IPC_MESSAGE_HANDLER(ShellViewMsg_LoadHyphenDictionary,
                        OnLoadHyphenDictionary)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  return handled;
}

void ShellRenderProcessObserver::OnResetAll() {
  test_interfaces_->resetAll();
  if (main_test_runner_)
    main_test_runner_->Reset();
}

void ShellRenderProcessObserver::OnSetWebKitSourceDir(
    const base::FilePath& webkit_source_dir) {
  webkit_source_dir_ = webkit_source_dir;
}

void ShellRenderProcessObserver::OnLoadHyphenDictionary(
    const IPC::PlatformFileForTransit& dict_file) {
  ShellContentRendererClient* renderer_client =
      static_cast<content::ShellContentRendererClient*>(
          content::GetContentClient()->renderer());
  renderer_client->LoadHyphenDictionary(
      IPC::PlatformFileForTransitToPlatformFile(dict_file));
}

}  // namespace content
<commit_msg>[content shell] WebRuntimeFeatures are managed by TestRunner<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/shell/shell_render_process_observer.h"

#include "base/command_line.h"
#include "content/public/common/content_client.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/test/layouttest_support.h"
#include "content/shell/shell_content_renderer_client.h"
#include "content/shell/shell_messages.h"
#include "content/shell/shell_switches.h"
#include "content/shell/webkit_test_runner.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Tools/DumpRenderTree/chromium/TestRunner/public/WebTestInterfaces.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/support/gc_extension.h"

using WebKit::WebFrame;
using WebTestRunner::WebTestDelegate;
using WebTestRunner::WebTestInterfaces;

namespace content {

namespace {
ShellRenderProcessObserver* g_instance = NULL;
}

// static
ShellRenderProcessObserver* ShellRenderProcessObserver::GetInstance() {
  return g_instance;
}

ShellRenderProcessObserver::ShellRenderProcessObserver()
    : main_test_runner_(NULL),
      test_delegate_(NULL) {
  CHECK(!g_instance);
  g_instance = this;
  RenderThread::Get()->AddObserver(this);
  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
    return;
  DisableAppCacheLogging();
  EnableDevToolsFrontendTesting();
  EnableShortCircuitSizeUpdates();
  DoNotSendFocusEvents();
}

ShellRenderProcessObserver::~ShellRenderProcessObserver() {
  CHECK(g_instance == this);
  g_instance = NULL;
}

void ShellRenderProcessObserver::SetTestDelegate(WebTestDelegate* delegate) {
  test_interfaces_->setDelegate(delegate);
  test_delegate_ = delegate;
}

void ShellRenderProcessObserver::SetMainWindow(RenderView* view) {
  WebKitTestRunner* test_runner = WebKitTestRunner::Get(view);
  test_interfaces_->setWebView(view->GetWebView(), test_runner->proxy());
  main_test_runner_ = test_runner;
}

void ShellRenderProcessObserver::WebKitInitialized() {
  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
    return;

  // We always expose GC to layout tests.
  webkit_glue::SetJavaScriptFlags(" --expose-gc");
  RenderThread::Get()->RegisterExtension(extensions_v8::GCExtension::Get());

  test_interfaces_.reset(new WebTestInterfaces);
  test_interfaces_->resetAll();
}

bool ShellRenderProcessObserver::OnControlMessageReceived(
    const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(ShellRenderProcessObserver, message)
    IPC_MESSAGE_HANDLER(ShellViewMsg_ResetAll, OnResetAll)
    IPC_MESSAGE_HANDLER(ShellViewMsg_SetWebKitSourceDir, OnSetWebKitSourceDir)
    IPC_MESSAGE_HANDLER(ShellViewMsg_LoadHyphenDictionary,
                        OnLoadHyphenDictionary)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  return handled;
}

void ShellRenderProcessObserver::OnResetAll() {
  test_interfaces_->resetAll();
  if (main_test_runner_)
    main_test_runner_->Reset();
}

void ShellRenderProcessObserver::OnSetWebKitSourceDir(
    const base::FilePath& webkit_source_dir) {
  webkit_source_dir_ = webkit_source_dir;
}

void ShellRenderProcessObserver::OnLoadHyphenDictionary(
    const IPC::PlatformFileForTransit& dict_file) {
  ShellContentRendererClient* renderer_client =
      static_cast<content::ShellContentRendererClient*>(
          content::GetContentClient()->renderer());
  renderer_client->LoadHyphenDictionary(
      IPC::PlatformFileForTransitToPlatformFile(dict_file));
}

}  // namespace content
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* no header other than FlagInfo.h should be included here */

#ifdef _MSC_VER
#pragma warning( 4:4786)
#endif

/* interface header */
#include "FlagInfo.h"

/* system headers */
#include <iostream>

// implementation-specific bzflag headers
#include "BZDBCache.h"

/* private */

/* protected */

/* public */

// flags list
FlagInfo              *FlagInfo::flagList      = NULL;
std::vector<FlagType*> FlagInfo::allowedFlags;
int                    FlagInfo::numExtraFlags = 0;
int                    FlagInfo::numFlags      = 0;
int                    FlagInfo::numFlagsInAir;

FlagInfo::FlagInfo()
{
  // prep flag
  flag.type               = Flags::Null;
  flag.status             = FlagNoExist;
  flag.endurance          = FlagNormal;
  flag.owner              = NoPlayer;
  flag.position[0]        = 0.0f;
  flag.position[1]        = 0.0f;
  flag.position[2]        = 0.0f;
  flag.launchPosition[0]  = 0.0f;
  flag.launchPosition[1]  = 0.0f;
  flag.launchPosition[2]  = 0.0f;
  flag.landingPosition[0] = 0.0f;
  flag.landingPosition[1] = 0.0f;
  flag.landingPosition[2] = 0.0f;
  flag.flightTime         = 0.0f;
  flag.flightEnd          = 0.0f;
  flag.initialVelocity    = 0.0f;
  player                  = -1;
  grabs                   = 0;
}

void FlagInfo::setSize(int _numFlags)
{
  // sanity check
  if (_numFlags > 1000000) {
    std::cerr << "WARNING: FlagInfo::setSize was given an insane flag count of " << _numFlags << std::endl;
    std::cerr << "clamping to 1000000 flags just for kicks" << std::endl;
    _numFlags = 100000;
  }

  numFlags = _numFlags;
  delete[] flagList;
  flagList = NULL;
  if (numFlags)
    flagList = new FlagInfo[numFlags];
  for (int i = 0; i < numFlags; i++)
    flagList[i].flagIndex = i;
}

void FlagInfo::setAllowed(std::vector<FlagType*> allowed)
{
  allowedFlags = allowed;
}

void FlagInfo::setExtra(int extra)
{
  numExtraFlags = extra;
}

int FlagInfo::lookupFirstTeamFlag(int teamindex)
{
  for (int i = 0; i < numFlags; i++) {
    if (flagList[i].flag.type->flagTeam == teamindex)
      return i;
  }
  return -1;
}

void FlagInfo::setRequiredFlag(FlagType *desc)
{
  required = true;
  flag.type = desc;
}

void FlagInfo::addFlag()
{
  const float flagAltitude = BZDB.eval(StateDatabase::BZDB_FLAGALTITUDE);
  const float gravity      = BZDBCache::gravity;
  const float maxGrabs     = BZDB.eval(StateDatabase::BZDB_MAXFLAGGRABS);

  // flag in now entering game
  numFlagsInAir++;
  flag.status          = FlagComing;

  // compute drop time
  const float flightTime = 2.0f * sqrtf(-2.0f * flagAltitude / gravity);
  flag.flightTime        = 0.0f;
  flag.flightEnd         = flightTime;
  flag.initialVelocity   = -0.5f * gravity * flightTime;
  dropDone               = TimeKeeper::getCurrent();
  dropDone              += flightTime;

  if (flag.type == Flags::Null)
    // pick a random flag
    flag.type = allowedFlags[(int)(allowedFlags.size() * (float)bzfrand())];

  // decide how sticky the flag will be
  if (flag.type->flagQuality == FlagBad)
    flag.endurance = FlagSticky;
  else
    flag.endurance = FlagUnstable;

  // how times will it stick around
  if ((flag.endurance == FlagSticky) || (flag.type == Flags::Thief))
    grabs = 1;
  else
    grabs = int(floor(maxGrabs * (float)bzfrand())) + 1;
}

void *FlagInfo::pack(void *buf)
{
  buf = nboPackUShort(buf, flagIndex);
  buf = FlagInfo::flagList[flagIndex].flag.pack(buf);
  return buf;
}

void *FlagInfo::fakePack(void *buf)
{
  buf = nboPackUShort(buf, flagIndex);
  buf = FlagInfo::flagList[flagIndex].flag.fakePack(buf);
  return buf;
}

void FlagInfo::dropFlag(float pos[3], float landingPos[3], bool vanish)
{
  numFlagsInAir++;
  flag.status             = vanish ? FlagGoing : FlagInAir;

  flag.landingPosition[0] = landingPos[0];
  flag.landingPosition[1] = landingPos[1];
  flag.landingPosition[2] = landingPos[2];

  flag.position[0]       = landingPos[0];
  flag.position[1]       = landingPos[1];
  flag.position[2]       = landingPos[2];
  flag.launchPosition[0] = pos[0];
  flag.launchPosition[1] = pos[1];
  flag.launchPosition[2] = pos[2] + BZDBCache::tankHeight;

  // compute flight info -- flight time depends depends on start and end
  // altitudes and desired height above start altitude
  const float gravity        = BZDBCache::gravity;
  const float flagAltitude   = BZDB.eval(StateDatabase::BZDB_FLAGALTITUDE);
  const float thrownAltitude = (flag.type == Flags::Shield) ?
    BZDB.eval(StateDatabase::BZDB_SHIELDFLIGHT) * flagAltitude : flagAltitude;
  const float maxAltitude    = pos[2] + thrownAltitude;
  const float upTime         = sqrtf(-2.0f * thrownAltitude / gravity);
  const float downTime       = sqrtf(-2.0f * (maxAltitude - pos[2]) / gravity);
  const float flightTime     = upTime + downTime;

  dropDone             = TimeKeeper::getCurrent();
  dropDone            += flightTime;
  flag.flightTime      = 0.0f;
  flag.flightEnd       = flightTime;
  flag.initialVelocity = -gravity * upTime;
}

void FlagInfo::resetFlag(float position[3], bool teamIsEmpty)
{
  // reset a flag's info
  player      = -1;
  // if it's a random flag, reset flag id
  if (flagIndex >= numFlags - numExtraFlags)
    flag.type = Flags::Null;

  flag.position[0] = position[0];
  flag.position[1] = position[1];
  flag.position[2] = position[2];

  // required flags mustn't just disappear
  if (required) {
    if (flag.type->flagTeam == ::NoTeam)
      // flag in now entering game
      addFlag();
    else if (teamIsEmpty)
      flag.status = FlagNoExist;
    else
      flag.status = FlagOnGround;
  } else {
    flag.status = FlagNoExist;
  }
}

void FlagInfo::grab(int playerIndex)
{
  flag.status = FlagOnTank;
  flag.owner  = playerIndex;
  player      = playerIndex;
  numShots    = 0;
}

int FlagInfo::teamIndex()
{
  return flag.type->flagTeam;
}

int FlagInfo::getIndex()
{
  return flagIndex;
}

float FlagInfo::getNextDrop(TimeKeeper &tm)
{
  // find timeout when next flag would hit ground
  float waitTime = 3.0f;
  if (numFlagsInAir > 0) {
    for (int i = 0; i < numFlags; i++) {
      FlagInfo &flag = flagList[i];
      if (flag.flag.status != FlagNoExist &&
	  flag.flag.status != FlagOnTank &&
	  flag.flag.status != FlagOnGround &&
	  flag.dropDone - tm < waitTime)
	waitTime = flag.dropDone - tm;
    }
  }
  return waitTime;
}

bool FlagInfo::landing(const TimeKeeper &tm)
{
  if (numFlagsInAir <= 0)
    return false;

  bool land = false;
  if (flag.status == FlagInAir || flag.status == FlagComing) {
    if (dropDone - tm <= 0.0f) {
      flag.status = FlagOnGround;
      numFlagsInAir--;
      land        = true;
    }
  } else if (flag.status == FlagGoing) {
    if (dropDone - tm <= 0.0f) {
      flag.status = FlagNoExist;
      numFlagsInAir--;
      land        = true;
    }
  }
  return land;
}

void FlagInfo::setNoFlagInAir()
{
  numFlagsInAir = 0;
}

void FlagInfo::getTextualInfo(char *message)
{
  sprintf(message, "%d p:%d r:%d g:%d i:%s s:%d p:%3.1fx%3.1fx%3.1f",
	  flagIndex, player, required, grabs, flag.type->flagAbbv, flag.status,
	  flag.position[0], flag.position[1], flag.position[2]);
}

bool FlagInfo::exist()
{
  return flag.status != FlagNoExist;
}

FlagInfo *FlagInfo::get(int index)
{
  if (index < 0)
    return NULL;
  if (index >= numFlags)
    return NULL;
  return &flagList[index];
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>fix team flag color<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* no header other than FlagInfo.h should be included here */

#ifdef _MSC_VER
#pragma warning( 4:4786)
#endif

/* interface header */
#include "FlagInfo.h"

/* system headers */
#include <iostream>

// implementation-specific bzflag headers
#include "BZDBCache.h"

/* private */

/* protected */

/* public */

// flags list
FlagInfo              *FlagInfo::flagList      = NULL;
std::vector<FlagType*> FlagInfo::allowedFlags;
int                    FlagInfo::numExtraFlags = 0;
int                    FlagInfo::numFlags      = 0;
int                    FlagInfo::numFlagsInAir;

FlagInfo::FlagInfo()
{
  // prep flag
  flag.type               = Flags::Null;
  flag.status             = FlagNoExist;
  flag.endurance          = FlagNormal;
  flag.owner              = NoPlayer;
  flag.position[0]        = 0.0f;
  flag.position[1]        = 0.0f;
  flag.position[2]        = 0.0f;
  flag.launchPosition[0]  = 0.0f;
  flag.launchPosition[1]  = 0.0f;
  flag.launchPosition[2]  = 0.0f;
  flag.landingPosition[0] = 0.0f;
  flag.landingPosition[1] = 0.0f;
  flag.landingPosition[2] = 0.0f;
  flag.flightTime         = 0.0f;
  flag.flightEnd          = 0.0f;
  flag.initialVelocity    = 0.0f;
  player                  = -1;
  grabs                   = 0;
}

void FlagInfo::setSize(int _numFlags)
{
  // sanity check
  if (_numFlags > 1000000) {
    std::cerr << "WARNING: FlagInfo::setSize was given an insane flag count of " << _numFlags << std::endl;
    std::cerr << "clamping to 1000000 flags just for kicks" << std::endl;
    _numFlags = 100000;
  }

  numFlags = _numFlags;
  delete[] flagList;
  flagList = NULL;
  if (numFlags)
    flagList = new FlagInfo[numFlags];
  for (int i = 0; i < numFlags; i++)
    flagList[i].flagIndex = i;
}

void FlagInfo::setAllowed(std::vector<FlagType*> allowed)
{
  allowedFlags = allowed;
}

void FlagInfo::setExtra(int extra)
{
  numExtraFlags = extra;
}

int FlagInfo::lookupFirstTeamFlag(int teamindex)
{
  for (int i = 0; i < numFlags; i++) {
    if (flagList[i].flag.type->flagTeam == teamindex)
      return i;
  }
  return -1;
}

void FlagInfo::setRequiredFlag(FlagType *desc)
{
  required = true;
  flag.type = desc;
}

void FlagInfo::addFlag()
{
  const float flagAltitude = BZDB.eval(StateDatabase::BZDB_FLAGALTITUDE);
  const float gravity      = BZDBCache::gravity;
  const float maxGrabs     = BZDB.eval(StateDatabase::BZDB_MAXFLAGGRABS);

  // flag in now entering game
  numFlagsInAir++;
  flag.status          = FlagComing;

  // compute drop time
  const float flightTime = 2.0f * sqrtf(-2.0f * flagAltitude / gravity);
  flag.flightTime        = 0.0f;
  flag.flightEnd         = flightTime;
  flag.initialVelocity   = -0.5f * gravity * flightTime;
  dropDone               = TimeKeeper::getCurrent();
  dropDone              += flightTime;

  if (flag.type == Flags::Null)
    // pick a random flag
    flag.type = allowedFlags[(int)(allowedFlags.size() * (float)bzfrand())];

  // decide how sticky the flag will be
  if (flag.type->flagQuality == FlagBad)
    flag.endurance = FlagSticky;
  else
    flag.endurance = FlagUnstable;

  // how times will it stick around
  if ((flag.endurance == FlagSticky) || (flag.type == Flags::Thief))
    grabs = 1;
  else
    grabs = int(floor(maxGrabs * (float)bzfrand())) + 1;
}

void *FlagInfo::pack(void *buf)
{
  buf = nboPackUShort(buf, flagIndex);
  buf = FlagInfo::flagList[flagIndex].flag.pack(buf);
  return buf;
}

void *FlagInfo::fakePack(void *buf)
{
  buf = nboPackUShort(buf, flagIndex);
  if (FlagInfo::flagList[flagIndex].flag.type->flagTeam == ::NoTeam)
    buf = FlagInfo::flagList[flagIndex].flag.fakePack(buf);
  else
    buf = FlagInfo::flagList[flagIndex].flag.pack(buf);
  return buf;
}

void FlagInfo::dropFlag(float pos[3], float landingPos[3], bool vanish)
{
  numFlagsInAir++;
  flag.status             = vanish ? FlagGoing : FlagInAir;

  flag.landingPosition[0] = landingPos[0];
  flag.landingPosition[1] = landingPos[1];
  flag.landingPosition[2] = landingPos[2];

  flag.position[0]       = landingPos[0];
  flag.position[1]       = landingPos[1];
  flag.position[2]       = landingPos[2];
  flag.launchPosition[0] = pos[0];
  flag.launchPosition[1] = pos[1];
  flag.launchPosition[2] = pos[2] + BZDBCache::tankHeight;

  // compute flight info -- flight time depends depends on start and end
  // altitudes and desired height above start altitude
  const float gravity        = BZDBCache::gravity;
  const float flagAltitude   = BZDB.eval(StateDatabase::BZDB_FLAGALTITUDE);
  const float thrownAltitude = (flag.type == Flags::Shield) ?
    BZDB.eval(StateDatabase::BZDB_SHIELDFLIGHT) * flagAltitude : flagAltitude;
  const float maxAltitude    = pos[2] + thrownAltitude;
  const float upTime         = sqrtf(-2.0f * thrownAltitude / gravity);
  const float downTime       = sqrtf(-2.0f * (maxAltitude - pos[2]) / gravity);
  const float flightTime     = upTime + downTime;

  dropDone             = TimeKeeper::getCurrent();
  dropDone            += flightTime;
  flag.flightTime      = 0.0f;
  flag.flightEnd       = flightTime;
  flag.initialVelocity = -gravity * upTime;
}

void FlagInfo::resetFlag(float position[3], bool teamIsEmpty)
{
  // reset a flag's info
  player      = -1;
  // if it's a random flag, reset flag id
  if (flagIndex >= numFlags - numExtraFlags)
    flag.type = Flags::Null;

  flag.position[0] = position[0];
  flag.position[1] = position[1];
  flag.position[2] = position[2];

  // required flags mustn't just disappear
  if (required) {
    if (flag.type->flagTeam == ::NoTeam)
      // flag in now entering game
      addFlag();
    else if (teamIsEmpty)
      flag.status = FlagNoExist;
    else
      flag.status = FlagOnGround;
  } else {
    flag.status = FlagNoExist;
  }
}

void FlagInfo::grab(int playerIndex)
{
  flag.status = FlagOnTank;
  flag.owner  = playerIndex;
  player      = playerIndex;
  numShots    = 0;
}

int FlagInfo::teamIndex()
{
  return flag.type->flagTeam;
}

int FlagInfo::getIndex()
{
  return flagIndex;
}

float FlagInfo::getNextDrop(TimeKeeper &tm)
{
  // find timeout when next flag would hit ground
  float waitTime = 3.0f;
  if (numFlagsInAir > 0) {
    for (int i = 0; i < numFlags; i++) {
      FlagInfo &flag = flagList[i];
      if (flag.flag.status != FlagNoExist &&
	  flag.flag.status != FlagOnTank &&
	  flag.flag.status != FlagOnGround &&
	  flag.dropDone - tm < waitTime)
	waitTime = flag.dropDone - tm;
    }
  }
  return waitTime;
}

bool FlagInfo::landing(const TimeKeeper &tm)
{
  if (numFlagsInAir <= 0)
    return false;

  bool land = false;
  if (flag.status == FlagInAir || flag.status == FlagComing) {
    if (dropDone - tm <= 0.0f) {
      flag.status = FlagOnGround;
      numFlagsInAir--;
      land        = true;
    }
  } else if (flag.status == FlagGoing) {
    if (dropDone - tm <= 0.0f) {
      flag.status = FlagNoExist;
      numFlagsInAir--;
      land        = true;
    }
  }
  return land;
}

void FlagInfo::setNoFlagInAir()
{
  numFlagsInAir = 0;
}

void FlagInfo::getTextualInfo(char *message)
{
  sprintf(message, "%d p:%d r:%d g:%d i:%s s:%d p:%3.1fx%3.1fx%3.1f",
	  flagIndex, player, required, grabs, flag.type->flagAbbv, flag.status,
	  flag.position[0], flag.position[1], flag.position[2]);
}

bool FlagInfo::exist()
{
  return flag.status != FlagNoExist;
}

FlagInfo *FlagInfo::get(int index)
{
  if (index < 0)
    return NULL;
  if (index >= numFlags)
    return NULL;
  return &flagList[index];
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>


<commit_before>/*
 * auxiliary.cpp - Auxiliary public functions
 *
 *   Copyright 2010 Jesús Torres <jmtorres@ull.es>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstring>
#include <string>
#include <vector>

#include <boost/shared_array.hpp>

#include <cli/auxiliary.hpp>

#include "fileno.hpp"

namespace cli { namespace auxiliary
{
    //
    // Functions for std::vector<std::string> to char** conversion
    //

    void deleteArgV(char** argv)
    {
        while(*argv != NULL) {
            delete(*argv);
            ++argv;
        }
    }

    boost::shared_array<char*>
    stdVectorStringToArgV(const std::vector<std::string> &strings)
    {

        int length = strings.size();
        boost::shared_array<char*> argv =
            boost::shared_array<char*>(new char*[length + 1], deleteArgV);
        for (int i = 0; i < length; ++i) {
            argv[i] = new char[strings[i].size() + 1];
            std::strcpy(argv[i], strings[i].c_str());
        }
        argv[length] = NULL;
        return argv;
    }
}}
<commit_msg>some cosmetic changes<commit_after>/*
 * auxiliary.cpp - Auxiliary public functions
 *
 *   Copyright 2010 Jesús Torres <jmtorres@ull.es>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstring>
#include <string>
#include <vector>

#include <boost/shared_array.hpp>

#include <cli/auxiliary.hpp>

#include "fileno.hpp"

namespace cli { namespace auxiliary
{
    //
    // Functions for std::vector<std::string> to char** conversion
    //

    void deleteArgV(char** argv)
    {
        while(*argv != NULL) {
            delete(*argv);
            ++argv;
        }
    }

    boost::shared_array<char*>
    stdVectorStringToArgV(const std::vector<std::string> &strings)
    {

        int length = strings.size();
        boost::shared_array<char*> argv(new char*[length + 1], deleteArgV);
        for (int i = 0; i < length; ++i) {
            argv[i] = new char[strings[i].size() + 1];
            ::strcpy(argv[i], strings[i].c_str());
        }
        argv[length] = NULL;
        return argv;
    }
}}
<|endoftext|>


<commit_before>#include "VseApp.hpp"

#include <stdint.h>
#include <iostream>

#include "OgreMath.h"
#include "OgreEntity.h"
#include "OgreSubEntity.h"
#include "SDL.h"

#include "RigidBodySys.hpp"
#include "RigidBodyComp.hpp"
#include "SceneNodeComp.hpp"
#include "LocalPlayerComp.hpp"
#include "LegSpringComp.hpp"
#include "WalkSignal.hpp"
#include "EntSignal.hpp"
#include "LocationSignal.hpp"

#include "Vec3f.hpp"

namespace vse {

void VseApp::onEntityExists(nres::Entity* entity) {}
void VseApp::onEntityDestroyed(nres::Entity* entity) {}

void VseApp::onEntityBroadcast(nres::Entity* entity, const EntSignal* data) {
    switch(data->getType()) {
        case EntSignal::Type::LOCATION: {
            LocationSignal* signal = (LocationSignal*) data;

            mCamLocNode->setPosition(signal->mLocationUpdate);

            break;
        }
        default: {
            break;
        }
    }
}

VseApp& VseApp::getSingleton() {
    static VseApp instance;
    return instance;
}

VseApp::VseApp() {}
VseApp::~VseApp() {}

void VseApp::onAppBegin(Ogre::Root* ogreRoot, Ogre::RenderWindow* ogreWindow, SDL_Window* sdlWindow) {
    mOgreRoot = ogreRoot;
    mOgreWindow = ogreWindow;
    mSdlWindow = sdlWindow;

    SDL_SetRelativeMouseMode(SDL_TRUE);

    mSmgr = mOgreRoot->createSceneManager(Ogre::ST_GENERIC);
    mRootNode = mSmgr->getRootSceneNode();

    mCam = mSmgr->createCamera("Camera");
    mCam->setNearClipDistance(0.1f);

    mCamLocNode = mRootNode->createChildSceneNode("CameraNode");
    mCamYawNode = mCamLocNode->createChildSceneNode();
    mCamPitchNode = mCamYawNode->createChildSceneNode();
    mCamRollNode = mCamPitchNode->createChildSceneNode();
    mCamRollNode->attachObject(mCam);

    mCamPitch = Ogre::Degree(0);
    mCamYaw = Ogre::Degree(0);
    mCamRoll = Ogre::Degree(0);

    mDollyScale = 5.f;
    mDollyMax = 10.f;
    mDollyMin = 0.f;

    mDollyAngle = Ogre::Degree(10);
    mDollyXCoeff = Ogre::Math::Sin(mDollyAngle);
    mDollyZCoeff = Ogre::Math::Cos(mDollyAngle);

    updateCamDolly();

    mCam->setAspectRatio(Ogre::Real(1280) / Ogre::Real(720));

    mSmgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
    mSmgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE);
    mSmgr->setSkyBox(true, "Test");

    Ogre::Viewport* viewport = ogreWindow->addViewport(mCam);
    viewport->setBackgroundColour(Ogre::ColourValue(0, 0, 0));

    Ogre::SceneNode* groundNode = mSmgr->getRootSceneNode()->createChildSceneNode();
    Ogre::Entity* groundEnt = mSmgr->createEntity("Ground", "ground.mesh");
    //groundEnt->getSubEntity(0)->getMaterial()->setReceiveShadows(true);
    groundEnt->setCastShadows(false);
    groundNode->attachObject(groundEnt);

    Ogre::Light* light = mSmgr->createLight("Light");
    light->setType(Ogre::Light::LT_DIRECTIONAL);
    light->setDirection(-1, -1, -1);

    mBroadphase = new btDbvtBroadphase();
    mCollisionConfiguration = new btDefaultCollisionConfiguration();
    mDispatcher = new btCollisionDispatcher(mCollisionConfiguration);
    mSolver = new btSequentialImpulseConstraintSolver();
    mDynamicsWorld = new btDiscreteDynamicsWorld(mDispatcher, mBroadphase, mSolver, mCollisionConfiguration);
    mDynamicsWorld->setGravity(btVector3(0, -9.8067, 0));

	btStaticPlaneShape* planeShape = new btStaticPlaneShape(btVector3(0, 1, 0), 0);
	btRigidBody* planeRigid = new btRigidBody(0, 0, planeShape);
	mDynamicsWorld->addRigidBody(planeRigid);

    mRigidBodySys = new RigidBodySys(mDynamicsWorld);
    mWorld.attachSystem(mRigidBodySys);

    mLegSpringSys = new LegSpringSys(mDynamicsWorld);
    mWorld.attachSystem(mLegSpringSys);

    mSceneNodeSys = new SceneNodeSys(mSmgr);
    mWorld.attachSystem(mSceneNodeSys);

    mLocalPlayer = mWorld.newEntity();
    btVector3 size(1, 1, 1);
    mLocalPlayer->add(new RigidBodyComp(new btBoxShape(size)));
    mLocalPlayer->add(new SceneNodeComp("Cube.mesh"));
    mLocalPlayer->add(new LocalPlayerComp());
    mLocalPlayer->add(new LegSpringComp(
        Vec3f(0, 0, 0), // Leg start
        Vec3f(0, -3, 0), // Leg end
        80, // Stiffness
        10, // Damping
        30, // Acceleration
        20 // Deceleration
    ));
    mLocalPlayer->addListener(this);
    mLocalPlayer->publish();

}

void VseApp::onAppEnd() {
    delete mDynamicsWorld;
    delete mSolver;
    delete mDispatcher;
    delete mCollisionConfiguration;
    delete mBroadphase;
}
void VseApp::onTick(float tps) {

    mDynamicsWorld->stepSimulation(tps, 5);
    mRigidBodySys->onTick();
    mLegSpringSys->onTick();

    const Uint8* keyStates = SDL_GetKeyboardState(NULL);

    Vec3f moveVec;
    if(keyStates[SDL_GetScancodeFromKey(SDLK_w)]) {
        moveVec.z = -1;
    }
    if(keyStates[SDL_GetScancodeFromKey(SDLK_a)]) {
        moveVec.x = -1;
    }
    if(keyStates[SDL_GetScancodeFromKey(SDLK_s)]) {
        moveVec.z = 1;
    }
    if(keyStates[SDL_GetScancodeFromKey(SDLK_d)]) {
        moveVec.x = 1;
    }

    if(!moveVec.isZero()) {
        Vec3f transl = mCamYawNode->getOrientation() * mCamPitchNode->getOrientation() * moveVec;
        transl.normalize();
        transl *= 5;
        mLocalPlayer->broadcast(new WalkSignal(transl));
    }

    if(keyStates[SDL_GetScancodeFromKey(SDLK_p)]) {
        //mLocalPlayer->broadcast(new LocalPlayerMoveSignal(Vec3f(0, 100, 0)));
    }
}

void VseApp::onKeyPress(const SDL_KeyboardEvent& event) {
    switch(event.keysym.sym) {
        case SDLK_w: {
            break;
        }
        case SDLK_a: {
            break;
        }
        case SDLK_s: {
            break;
        }
        case SDLK_d: {
            break;
        }
        case SDLK_q: {
            nres::Entity* testCube = mWorld.newEntity();
            testCube->add(new RigidBodyComp(new btSphereShape(1)));
            testCube->add(new SceneNodeComp("Ball.mesh"));
            testCube->publish();
            break;
        }
        default: {
            break;
        }
    }
}
void VseApp::onKeyRelease(const SDL_KeyboardEvent& event) {
}
void VseApp::onMouseMove(const SDL_MouseMotionEvent& event) {

    float dx = -event.xrel;
    float dy = -event.yrel;
    Ogre::Radian dYaw = Ogre::Radian(dx / 200);
    Ogre::Radian dPitch = Ogre::Radian(dy / 200);

    mCamPitch += dPitch;
    mCamYaw += dYaw;

    if(mCamPitch > Ogre::Degree(90)) {
        mCamPitch = Ogre::Degree(90);
    }
    else if(mCamPitch < Ogre::Degree(-90)) {
        mCamPitch = Ogre::Degree(-90);
    }

    updateCamDolly();
}

void VseApp::updateCamDolly() {
    mCamYawNode->resetOrientation();
    mCamYawNode->yaw(mCamYaw);
    mCamPitchNode->resetOrientation();
    mCamPitchNode->pitch(mCamPitch);

    mCamPitchNode->setPosition(mDollyXCoeff * mDollyScale, 0, 0);
    mCamRollNode->setPosition(0, 0, mDollyZCoeff * mDollyScale);
}

void VseApp::onMousePress(const SDL_MouseButtonEvent& event) {
}
void VseApp::onMouseRelease(const SDL_MouseButtonEvent& event) {

}

void VseApp::onMouseWheel(const SDL_MouseWheelEvent& event) {
    float delta = -event.y;
    delta *= 0.5f;

    mDollyScale += delta;

    if(mDollyScale < mDollyMin) {
        mDollyScale = mDollyMin;
    }
    if(mDollyScale > mDollyMax) {
        mDollyScale = mDollyMax;
    }

    updateCamDolly();
}
}

<commit_msg>Smoother shadows<commit_after>#include "VseApp.hpp"

#include <stdint.h>
#include <iostream>

#include "OgreMath.h"
#include "OgreEntity.h"
#include "OgreSubEntity.h"
#include "SDL.h"

#include "RigidBodySys.hpp"
#include "RigidBodyComp.hpp"
#include "SceneNodeComp.hpp"
#include "LocalPlayerComp.hpp"
#include "LegSpringComp.hpp"
#include "WalkSignal.hpp"
#include "EntSignal.hpp"
#include "LocationSignal.hpp"

#include "Vec3f.hpp"

namespace vse {

void VseApp::onEntityExists(nres::Entity* entity) {}
void VseApp::onEntityDestroyed(nres::Entity* entity) {}

void VseApp::onEntityBroadcast(nres::Entity* entity, const EntSignal* data) {
    switch(data->getType()) {
        case EntSignal::Type::LOCATION: {
            LocationSignal* signal = (LocationSignal*) data;

            mCamLocNode->setPosition(signal->mLocationUpdate);

            break;
        }
        default: {
            break;
        }
    }
}

VseApp& VseApp::getSingleton() {
    static VseApp instance;
    return instance;
}

VseApp::VseApp() {}
VseApp::~VseApp() {}

void VseApp::onAppBegin(Ogre::Root* ogreRoot, Ogre::RenderWindow* ogreWindow, SDL_Window* sdlWindow) {
    mOgreRoot = ogreRoot;
    mOgreWindow = ogreWindow;
    mSdlWindow = sdlWindow;

    SDL_SetRelativeMouseMode(SDL_TRUE);

    mSmgr = mOgreRoot->createSceneManager(Ogre::ST_GENERIC);
    mRootNode = mSmgr->getRootSceneNode();

    mCam = mSmgr->createCamera("Camera");
    mCam->setNearClipDistance(0.1f);

    mCamLocNode = mRootNode->createChildSceneNode("CameraNode");
    mCamYawNode = mCamLocNode->createChildSceneNode();
    mCamPitchNode = mCamYawNode->createChildSceneNode();
    mCamRollNode = mCamPitchNode->createChildSceneNode();
    mCamRollNode->attachObject(mCam);

    mCamPitch = Ogre::Degree(0);
    mCamYaw = Ogre::Degree(0);
    mCamRoll = Ogre::Degree(0);

    mDollyScale = 5.f;
    mDollyMax = 10.f;
    mDollyMin = 0.f;

    mDollyAngle = Ogre::Degree(10);
    mDollyXCoeff = Ogre::Math::Sin(mDollyAngle);
    mDollyZCoeff = Ogre::Math::Cos(mDollyAngle);

    updateCamDolly();

    mCam->setAspectRatio(Ogre::Real(1280) / Ogre::Real(720));

    mSmgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
    mSmgr->setShadowTextureSize(1024);
    mSmgr->setShadowTextureFSAA(2);
    mSmgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_ADDITIVE); // SHADOWTYPE_TEXTURE_ADDITIVE
    mSmgr->setSkyBox(true, "Test");

    Ogre::Viewport* viewport = ogreWindow->addViewport(mCam);
    viewport->setBackgroundColour(Ogre::ColourValue(0, 0, 0));

    Ogre::SceneNode* groundNode = mSmgr->getRootSceneNode()->createChildSceneNode();
    Ogre::Entity* groundEnt = mSmgr->createEntity("Ground", "ground.mesh");
    //groundEnt->getSubEntity(0)->getMaterial()->setReceiveShadows(true);
    groundEnt->setCastShadows(false);
    groundNode->attachObject(groundEnt);

    Ogre::Light* light = mSmgr->createLight("Light");
    light->setType(Ogre::Light::LT_DIRECTIONAL);
    light->setDirection(-1, -1, -1);

    mBroadphase = new btDbvtBroadphase();
    mCollisionConfiguration = new btDefaultCollisionConfiguration();
    mDispatcher = new btCollisionDispatcher(mCollisionConfiguration);
    mSolver = new btSequentialImpulseConstraintSolver();
    mDynamicsWorld = new btDiscreteDynamicsWorld(mDispatcher, mBroadphase, mSolver, mCollisionConfiguration);
    mDynamicsWorld->setGravity(btVector3(0, -9.8067, 0));

	btStaticPlaneShape* planeShape = new btStaticPlaneShape(btVector3(0, 1, 0), 0);
	btRigidBody* planeRigid = new btRigidBody(0, 0, planeShape);
	mDynamicsWorld->addRigidBody(planeRigid);

    mRigidBodySys = new RigidBodySys(mDynamicsWorld);
    mWorld.attachSystem(mRigidBodySys);

    mLegSpringSys = new LegSpringSys(mDynamicsWorld);
    mWorld.attachSystem(mLegSpringSys);

    mSceneNodeSys = new SceneNodeSys(mSmgr);
    mWorld.attachSystem(mSceneNodeSys);

    mLocalPlayer = mWorld.newEntity();
    btVector3 size(1, 1, 1);
    mLocalPlayer->add(new RigidBodyComp(new btBoxShape(size)));
    mLocalPlayer->add(new SceneNodeComp("Cube.mesh"));
    mLocalPlayer->add(new LocalPlayerComp());
    mLocalPlayer->add(new LegSpringComp(
        Vec3f(0, 0, 0), // Leg start
        Vec3f(0, -3, 0), // Leg end
        80, // Stiffness
        10, // Damping
        30, // Acceleration
        20 // Deceleration
    ));
    mLocalPlayer->addListener(this);
    mLocalPlayer->publish();

}

void VseApp::onAppEnd() {
    delete mDynamicsWorld;
    delete mSolver;
    delete mDispatcher;
    delete mCollisionConfiguration;
    delete mBroadphase;
}
void VseApp::onTick(float tps) {

    mDynamicsWorld->stepSimulation(tps, 5);
    mRigidBodySys->onTick();
    mLegSpringSys->onTick();

    const Uint8* keyStates = SDL_GetKeyboardState(NULL);

    Vec3f moveVec;
    if(keyStates[SDL_GetScancodeFromKey(SDLK_w)]) {
        moveVec.z = -1;
    }
    if(keyStates[SDL_GetScancodeFromKey(SDLK_a)]) {
        moveVec.x = -1;
    }
    if(keyStates[SDL_GetScancodeFromKey(SDLK_s)]) {
        moveVec.z = 1;
    }
    if(keyStates[SDL_GetScancodeFromKey(SDLK_d)]) {
        moveVec.x = 1;
    }

    if(!moveVec.isZero()) {
        Vec3f transl = mCamYawNode->getOrientation() * mCamPitchNode->getOrientation() * moveVec;
        transl.normalize();
        transl *= 5;
        mLocalPlayer->broadcast(new WalkSignal(transl));
    }

    if(keyStates[SDL_GetScancodeFromKey(SDLK_p)]) {
        //mLocalPlayer->broadcast(new LocalPlayerMoveSignal(Vec3f(0, 100, 0)));
    }
}

void VseApp::onKeyPress(const SDL_KeyboardEvent& event) {
    switch(event.keysym.sym) {
        case SDLK_w: {
            break;
        }
        case SDLK_a: {
            break;
        }
        case SDLK_s: {
            break;
        }
        case SDLK_d: {
            break;
        }
        case SDLK_q: {
            nres::Entity* testCube = mWorld.newEntity();
            testCube->add(new RigidBodyComp(new btSphereShape(1)));
            testCube->add(new SceneNodeComp("Ball.mesh"));
            testCube->publish();
            break;
        }
        default: {
            break;
        }
    }
}
void VseApp::onKeyRelease(const SDL_KeyboardEvent& event) {
}
void VseApp::onMouseMove(const SDL_MouseMotionEvent& event) {

    float dx = -event.xrel;
    float dy = -event.yrel;
    Ogre::Radian dYaw = Ogre::Radian(dx / 200);
    Ogre::Radian dPitch = Ogre::Radian(dy / 200);

    mCamPitch += dPitch;
    mCamYaw += dYaw;

    if(mCamPitch > Ogre::Degree(90)) {
        mCamPitch = Ogre::Degree(90);
    }
    else if(mCamPitch < Ogre::Degree(-90)) {
        mCamPitch = Ogre::Degree(-90);
    }

    updateCamDolly();
}

void VseApp::updateCamDolly() {
    mCamYawNode->resetOrientation();
    mCamYawNode->yaw(mCamYaw);
    mCamPitchNode->resetOrientation();
    mCamPitchNode->pitch(mCamPitch);

    mCamPitchNode->setPosition(mDollyXCoeff * mDollyScale, 0, 0);
    mCamRollNode->setPosition(0, 0, mDollyZCoeff * mDollyScale);
}

void VseApp::onMousePress(const SDL_MouseButtonEvent& event) {
}
void VseApp::onMouseRelease(const SDL_MouseButtonEvent& event) {

}

void VseApp::onMouseWheel(const SDL_MouseWheelEvent& event) {
    float delta = -event.y;
    delta *= 0.5f;

    mDollyScale += delta;

    if(mDollyScale < mDollyMin) {
        mDollyScale = mDollyMin;
    }
    if(mDollyScale > mDollyMax) {
        mDollyScale = mDollyMax;
    }

    updateCamDolly();
}
}

<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/logging.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-base/thread/FixedSizeThreadPool.h"
#include "fnord-base/wallclock.h"
#include "fnord-base/VFS.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-rpc/RPCClient.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-http/VFSFileServlet.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedFactory.h"
#include "fnord-feeds/RemoteFeedReader.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-sstable/SSTableServlet.h"
#include "fnord-logtable/LogTableServlet.h"
#include "fnord-logtable/TableRepository.h"
#include "fnord-logtable/TableJanitor.h"
#include "fnord-logtable/TableReplication.h"
#include "fnord-logtable/ArtifactReplication.h"
#include "fnord-logtable/ArtifactIndexReplication.h"
#include "fnord-logtable/NumericBoundsSummary.h"
#include "fnord-mdb/MDB.h"
#include "fnord-mdb/MDBUtil.h"
#include "fnord-tsdb/TSDBNode.h"
#include "fnord-tsdb/TSDBServlet.h"
#include "common.h"
#include "schemas.h"
#include "ModelReplication.h"

using namespace fnord;

std::atomic<bool> shutdown_sig;
fnord::thread::EventLoop ev;

void quit(int n) {
  shutdown_sig = true;
  fnord::logInfo("cm.chunkserver", "Shutting down...");
  // FIXPAUL: wait for http server stop...
  ev.shutdown();
}

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  /* shutdown hook */
  shutdown_sig = false;
  struct sigaction sa;
  memset(&sa, 0, sizeof(struct sigaction));
  sa.sa_handler = quit;
  sigaction(SIGTERM, &sa, NULL);
  sigaction(SIGQUIT, &sa, NULL);
  sigaction(SIGINT, &sa, NULL);

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "readonly",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "readonly",
      "readonly");

  flags.defineFlag(
      "replica",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "replica id",
      "<id>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "datadir path",
      "<path>");

  flags.defineFlag(
      "replicate_from",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "url",
      "<url>");

  flags.defineFlag(
      "fsck",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "fsck",
      "fsck");

  flags.defineFlag(
      "repair",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "repair",
      "repair");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  /* args */
  auto dir = flags.getString("datadir");
  auto readonly = flags.isSet("readonly");
  auto replica = flags.getString("replica");
  auto repl_sources = flags.getStrings("replicate_from");

  Vector<URI> artifact_sources;
  for (const auto& rep : repl_sources) {
    artifact_sources.emplace_back(
        URI(StringUtil::format("http://$0:7005/", rep)));
  }

  /* start http server and worker pools */
  fnord::thread::ThreadPool tpool;
  fnord::thread::FixedSizeThreadPool wpool(8);
  fnord::thread::FixedSizeThreadPool repl_wpool(8);
  http::HTTPConnectionPool http(&ev);
  fnord::http::HTTPRouter http_router;
  fnord::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));
  wpool.start();
  repl_wpool.start();

  /* artifact replication */
  logtable::ArtifactReplication artifact_replication(
      &http,
      &repl_wpool,
      8);

  /* model replication */
  ModelReplication model_replication;

  if (!readonly) {
    model_replication.addArtifactIndexReplication(
        "termstats",
        dir,
        artifact_sources,
        &artifact_replication,
        &http);
  }

  /* logtable */
  logtable::TableRepository table_repo(
      dir,
      replica,
      readonly,
      &wpool);

  auto joined_sessions_schema = joinedSessionsSchema();
  table_repo.addTable("joined_sessions-dawanda", joined_sessions_schema);
  table_repo.addTable("index_feed-dawanda", indexChangeRequestSchema());
  Set<String> tbls  = { "joined_sessions-dawanda", "index_feed-dawanda" };

  logtable::TableReplication table_replication(&http);
  if (!readonly) {
    for (const auto& tbl : tbls) {
      auto table = table_repo.findTableWriter(tbl);

      if (StringUtil::beginsWith(tbl, "joined_sessions")) {
        table->addSummary([joined_sessions_schema] () {
          return new logtable::NumericBoundsSummaryBuilder(
              "search_queries.time-bounds",
              joined_sessions_schema.id("search_queries.time"));
        });
      }

      table->runConsistencyCheck(
          flags.isSet("fsck"),
          flags.isSet("repair"));

      for (const auto& rep : repl_sources) {
        table_replication.replicateTableFrom(
            table,
            URI(StringUtil::format("http://$0:7003/logtable", rep)));
      }

      if (artifact_sources.size() > 0) {
        artifact_replication.replicateArtifactsFrom(
            table->artifactIndex(),
            artifact_sources);
      }
    }
  }

  logtable::TableJanitor table_janitor(&table_repo);
  //if (!readonly) {
  //  table_janitor.start();
  //  table_replication.start();
  //  artifact_replication.start();
  //  model_replication.start();
  //}

  logtable::LogTableServlet logtable_servlet(&table_repo);
  http_router.addRouteByPrefixMatch("/logtable", &logtable_servlet, &tpool);

  tsdb::TSDBNode tsdb_node("xxx", "/tmp/tsdb");
  tsdb::TSDBServlet tsdb_servlet(&tsdb_node);
  http_router.addRouteByPrefixMatch("/tsdb", &tsdb_servlet, &tpool);

  ev.run();

  //if (!readonly) {
  //  table_janitor.stop();
  //  table_janitor.check();
  //  table_replication.stop();
  //  artifact_replication.stop();
  //  model_replication.stop();
  //}

  fnord::logInfo("cm.chunkserver", "Exiting...");

  exit(0);
}

<commit_msg>TSDBNode::configurePrefix<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/logging.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-base/thread/FixedSizeThreadPool.h"
#include "fnord-base/wallclock.h"
#include "fnord-base/VFS.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-rpc/RPCClient.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-http/VFSFileServlet.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedFactory.h"
#include "fnord-feeds/RemoteFeedReader.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-sstable/SSTableServlet.h"
#include "fnord-logtable/LogTableServlet.h"
#include "fnord-logtable/TableRepository.h"
#include "fnord-logtable/TableJanitor.h"
#include "fnord-logtable/TableReplication.h"
#include "fnord-logtable/ArtifactReplication.h"
#include "fnord-logtable/ArtifactIndexReplication.h"
#include "fnord-logtable/NumericBoundsSummary.h"
#include "fnord-mdb/MDB.h"
#include "fnord-mdb/MDBUtil.h"
#include "fnord-tsdb/TSDBNode.h"
#include "fnord-tsdb/TSDBServlet.h"
#include "common.h"
#include "schemas.h"
#include "ModelReplication.h"

using namespace fnord;

std::atomic<bool> shutdown_sig;
fnord::thread::EventLoop ev;

void quit(int n) {
  shutdown_sig = true;
  fnord::logInfo("cm.chunkserver", "Shutting down...");
  // FIXPAUL: wait for http server stop...
  ev.shutdown();
}

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  /* shutdown hook */
  shutdown_sig = false;
  struct sigaction sa;
  memset(&sa, 0, sizeof(struct sigaction));
  sa.sa_handler = quit;
  sigaction(SIGTERM, &sa, NULL);
  sigaction(SIGQUIT, &sa, NULL);
  sigaction(SIGINT, &sa, NULL);

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "readonly",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "readonly",
      "readonly");

  flags.defineFlag(
      "replica",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "replica id",
      "<id>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "datadir path",
      "<path>");

  flags.defineFlag(
      "replicate_from",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "url",
      "<url>");

  flags.defineFlag(
      "fsck",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "fsck",
      "fsck");

  flags.defineFlag(
      "repair",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "repair",
      "repair");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  /* args */
  auto dir = flags.getString("datadir");
  auto readonly = flags.isSet("readonly");
  auto replica = flags.getString("replica");
  auto repl_sources = flags.getStrings("replicate_from");

  Vector<URI> artifact_sources;
  for (const auto& rep : repl_sources) {
    artifact_sources.emplace_back(
        URI(StringUtil::format("http://$0:7005/", rep)));
  }

  /* start http server and worker pools */
  fnord::thread::ThreadPool tpool;
  fnord::thread::FixedSizeThreadPool wpool(8);
  fnord::thread::FixedSizeThreadPool repl_wpool(8);
  http::HTTPConnectionPool http(&ev);
  fnord::http::HTTPRouter http_router;
  fnord::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));
  wpool.start();
  repl_wpool.start();

  /* artifact replication */
  logtable::ArtifactReplication artifact_replication(
      &http,
      &repl_wpool,
      8);

  /* model replication */
  ModelReplication model_replication;

  if (!readonly) {
    model_replication.addArtifactIndexReplication(
        "termstats",
        dir,
        artifact_sources,
        &artifact_replication,
        &http);
  }

  /* logtable */
  logtable::TableRepository table_repo(
      dir,
      replica,
      readonly,
      &wpool);

  auto joined_sessions_schema = joinedSessionsSchema();
  table_repo.addTable("joined_sessions-dawanda", joined_sessions_schema);
  table_repo.addTable("index_feed-dawanda", indexChangeRequestSchema());
  Set<String> tbls  = { "joined_sessions-dawanda", "index_feed-dawanda" };

  logtable::TableReplication table_replication(&http);
  if (!readonly) {
    for (const auto& tbl : tbls) {
      auto table = table_repo.findTableWriter(tbl);

      if (StringUtil::beginsWith(tbl, "joined_sessions")) {
        table->addSummary([joined_sessions_schema] () {
          return new logtable::NumericBoundsSummaryBuilder(
              "search_queries.time-bounds",
              joined_sessions_schema.id("search_queries.time"));
        });
      }

      table->runConsistencyCheck(
          flags.isSet("fsck"),
          flags.isSet("repair"));

      for (const auto& rep : repl_sources) {
        table_replication.replicateTableFrom(
            table,
            URI(StringUtil::format("http://$0:7003/logtable", rep)));
      }

      if (artifact_sources.size() > 0) {
        artifact_replication.replicateArtifactsFrom(
            table->artifactIndex(),
            artifact_sources);
      }
    }
  }

  logtable::TableJanitor table_janitor(&table_repo);
  //if (!readonly) {
  //  table_janitor.start();
  //  table_replication.start();
  //  artifact_replication.start();
  //  model_replication.start();
  //}

  logtable::LogTableServlet logtable_servlet(&table_repo);
  http_router.addRouteByPrefixMatch("/logtable", &logtable_servlet, &tpool);

  tsdb::TSDBNode tsdb_node("xxx", "/tmp/tsdb");
  tsdb_node.configurePrefix(
      "b",
      tsdb::StreamProperties(new msg::MessageSchema(joinedSessionsSchema())));

  tsdb::TSDBServlet tsdb_servlet(&tsdb_node);
  http_router.addRouteByPrefixMatch("/tsdb", &tsdb_servlet, &tpool);

  ev.run();

  //if (!readonly) {
  //  table_janitor.stop();
  //  table_janitor.check();
  //  table_replication.stop();
  //  artifact_replication.stop();
  //  model_replication.stop();
  //}

  fnord::logInfo("cm.chunkserver", "Exiting...");

  exit(0);
}

<|endoftext|>