<commit_before>/**
 * @file SimpleMotionBehaviorControl.cpp
 *
 * @author Heinrich Mellmann
 * @author Daniel Goehring
 * Implementation of class SimpleMotionBehaviorControl
 */

#include "SimpleMotionBehaviorControl.h"

#include "Tools/Debug/DebugRequest.h"
#include "Tools/Debug/DebugModify.h"

SimpleMotionBehaviorControl::SimpleMotionBehaviorControl()
{
  // test head control
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:Search", "Set the HeadMotion-Request to 'search'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:reverseSearchDirection", "Set the head search direction to counterclockwise.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:LookAtBall_image", "Set the HeadMotion-Request to 'look_at_ball'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:LookAtBall_field", "Set the HeadMotion-Request to 'look_at_ball'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:Stabilize", "Set the HeadMotion-Request to 'stabilize'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:SwitchToBottomCamera", "Switch to bottom camera", true);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:look_at_ball_modell", "Search for ball if not seen", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:look_straight_ahead", "look straight ahead", false);
	DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:look_at_attention_point", "look at attention point", false);

  // test motion control
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:standard_stand", "stand as standard or not", true);

  // walk
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:walk_forward", "Walk foraward as fast as possible", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:walk_backward", "Walk backward as fast as possible", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:strafe_left", "Set the motion request to 'strafe'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:strafe_right", "Set the motion request to 'strafe'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:turn_left", "Set the motion request to 'turn_right'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:turn_right", "Set the motion request to 'turn_right'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:walk_forward", "Walk foraward as fast as possible", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:stepping", "walk with zero speed", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:step_control", "test step control", false);

  // key frame motion
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:stand_up_from_front", "Set the motion request to 'stand_up_from_front'", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:stand_up_from_back", "Set the motion request to 'stand_up_from_back'", false);

  // other motions
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:dead", "Set the robot dead.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:stand", "The default motion, otherwise do nothing", true);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:sit", "sit down, has a rest", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:init", "Set the robot init.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:dance", "Let's dance", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:protect_falling", "Don't hurt me!", false);
}

void SimpleMotionBehaviorControl::execute()
{
  // reset some stuff by default
  getMotionRequest().forced = false;
  getMotionRequest().standHeight = -1; // sit in a stable position

  testHead();

  testMotion();

}//end execute

void SimpleMotionBehaviorControl::testHead()
{
  getHeadMotionRequest().cameraID = CameraInfo::Top;
  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:SwitchToBottomCamera",
    getHeadMotionRequest().cameraID = CameraInfo::Bottom;
  );

  // keep the head as forced by default
  getHeadMotionRequest().id = HeadMotionRequest::hold;

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:Search",
    getHeadMotionRequest().id = HeadMotionRequest::search;
    getHeadMotionRequest().searchCenter = Vector3<double>(2000, 0, 0);
    getHeadMotionRequest().searchSize = Vector3<double>(1500, 2000, 0);
  );

  getHeadMotionRequest().searchDirection = true;
  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:reverseSearchDirection",
    getHeadMotionRequest().searchDirection = false;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:Stabilize",
    getHeadMotionRequest().id = HeadMotionRequest::stabilize;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:LookAtBall_image",
    if (getBallPercept().ballWasSeen)
    {
      getHeadMotionRequest().id = HeadMotionRequest::look_at_point;
      getHeadMotionRequest().targetPointInImage = getBallPercept().centerInImage;
    }
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:LookAtBall_field",
    if (getBallPercept().ballWasSeen)
    {
      getHeadMotionRequest().id = HeadMotionRequest::look_at_world_point;
      getHeadMotionRequest().targetPointInTheWorld.x = getBallPercept().bearingBasedOffsetOnField.x;
      getHeadMotionRequest().targetPointInTheWorld.y = getBallPercept().bearingBasedOffsetOnField.y;
      getHeadMotionRequest().targetPointInTheWorld.z = getFieldInfo().ballRadius;
    }
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:look_straight_ahead",
    getHeadMotionRequest().id = HeadMotionRequest::look_straight_ahead;
  );

	DEBUG_REQUEST("SimpleMotionBehaviorControl:head:look_at_attention_point",
		getHeadMotionRequest().id = HeadMotionRequest::look_at_point_on_the_ground;
		getHeadMotionRequest().targetPointOnTheGround = getAttentionModel().mostInterestingPoint;
  );

}//end testHead

void SimpleMotionBehaviorControl::testMotion()
{
  getMotionRequest().walkRequest.target = Pose2D();
  getMotionRequest().walkRequest.character = 0.5;

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:stand",
    getMotionRequest().id = motion::stand;
  );

  getMotionRequest().standardStand = false;
  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:standard_stand",
    getMotionRequest().standardStand = true;
      getMotionRequest().standHeight = -1; // minus means the same value as walk
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:sit",
    getMotionRequest().id = motion::sit;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:walk_forward",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.translation.x = 500;
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:walk_backward",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.translation.x = -500;
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:strafe_right",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.translation.y = -500;
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:strafe_left",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.translation.y = 500;
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:turn_right",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.rotation = Math::fromDegrees(-60);
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:turn_left",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.rotation = Math::fromDegrees(60);
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:stepping",
      getMotionRequest().id = motion::walk;
      getMotionRequest().walkRequest.target = Pose2D();
      getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
    );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:step_control",
   if ( getMotionStatus().stepControl.stepID % 5 == 0)
  {
    getMotionRequest().walkRequest.stepControl.stepID = getMotionStatus().stepControl.stepID;
    switch(getMotionStatus().stepControl.moveableFoot)
  {
    case MotionStatus::StepControlStatus::LEFT:
    case MotionStatus::StepControlStatus::BOTH:
    {
      getMotionRequest().walkRequest.stepControl.moveLeftFoot = true;
      getMotionRequest().walkRequest.coordinate = WalkRequest::LFoot;
      break;
    }
    case MotionStatus::StepControlStatus::RIGHT:
    {
      getMotionRequest().walkRequest.stepControl.moveLeftFoot = false;
      getMotionRequest().walkRequest.coordinate = WalkRequest::RFoot;
      break;
    }
    default: ASSERT(false);
      break;
    }
  double stepTime = 1000;
  double speedDirection = 0;
  MODIFY("StepControl.time",stepTime);
  MODIFY("StepControl.speedDirection",speedDirection);
    getMotionRequest().walkRequest.stepControl.target = Pose2D(0, 100, 0);
    getMotionRequest().walkRequest.stepControl.time = stepTime;
    getMotionRequest().walkRequest.stepControl.speedDirection = Math::fromDegrees(speedDirection);
    getMotionRequest().walkRequest.character = 1;
  }
    );

  double offsetR = 0;
  MODIFY("walk.offset.r", offsetR);
  getMotionRequest().walkRequest.offset.rotation = Math::fromDegrees(offsetR);
  MODIFY("walk.offset.x", getMotionRequest().walkRequest.offset.translation.x);
  MODIFY("walk.offset.y", getMotionRequest().walkRequest.offset.translation.y);

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:stand_up_from_front",
    getMotionRequest().id = motion::stand_up_from_front;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:stand_up_from_back",
    getMotionRequest().id = motion::stand_up_from_back;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:dead",
    getMotionRequest().id = motion::dead;
    getMotionRequest().forced = true;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:init",
    getMotionRequest().id = motion::init;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:dance",
    getMotionRequest().id = motion::dance;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:protect_falling",
    getMotionRequest().id = motion::protect_falling;
  );

}//end testMotion

<commit_msg>modify walk character directly<commit_after>/**
 * @file SimpleMotionBehaviorControl.cpp
 *
 * @author Heinrich Mellmann
 * @author Daniel Goehring
 * Implementation of class SimpleMotionBehaviorControl
 */

#include "SimpleMotionBehaviorControl.h"

#include "Tools/Debug/DebugRequest.h"
#include "Tools/Debug/DebugModify.h"

SimpleMotionBehaviorControl::SimpleMotionBehaviorControl()
{
  // test head control
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:Search", "Set the HeadMotion-Request to 'search'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:reverseSearchDirection", "Set the head search direction to counterclockwise.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:LookAtBall_image", "Set the HeadMotion-Request to 'look_at_ball'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:LookAtBall_field", "Set the HeadMotion-Request to 'look_at_ball'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:Stabilize", "Set the HeadMotion-Request to 'stabilize'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:SwitchToBottomCamera", "Switch to bottom camera", true);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:look_at_ball_modell", "Search for ball if not seen", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:look_straight_ahead", "look straight ahead", false);
	DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:head:look_at_attention_point", "look at attention point", false);

  // test motion control
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:standard_stand", "stand as standard or not", true);

  // walk
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:walk_forward", "Walk foraward as fast as possible", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:walk_backward", "Walk backward as fast as possible", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:strafe_left", "Set the motion request to 'strafe'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:strafe_right", "Set the motion request to 'strafe'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:turn_left", "Set the motion request to 'turn_right'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:turn_right", "Set the motion request to 'turn_right'.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:walk_forward", "Walk foraward as fast as possible", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:stepping", "walk with zero speed", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:step_control", "test step control", false);

  // key frame motion
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:stand_up_from_front", "Set the motion request to 'stand_up_from_front'", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:stand_up_from_back", "Set the motion request to 'stand_up_from_back'", false);

  // other motions
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:dead", "Set the robot dead.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:stand", "The default motion, otherwise do nothing", true);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:sit", "sit down, has a rest", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:init", "Set the robot init.", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:dance", "Let's dance", false);
  DEBUG_REQUEST_REGISTER("SimpleMotionBehaviorControl:motion:protect_falling", "Don't hurt me!", false);
}

void SimpleMotionBehaviorControl::execute()
{
  // reset some stuff by default
  getMotionRequest().forced = false;
  getMotionRequest().standHeight = -1; // sit in a stable position

  testHead();

  testMotion();

}//end execute

void SimpleMotionBehaviorControl::testHead()
{
  getHeadMotionRequest().cameraID = CameraInfo::Top;
  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:SwitchToBottomCamera",
    getHeadMotionRequest().cameraID = CameraInfo::Bottom;
  );

  // keep the head as forced by default
  getHeadMotionRequest().id = HeadMotionRequest::hold;

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:Search",
    getHeadMotionRequest().id = HeadMotionRequest::search;
    getHeadMotionRequest().searchCenter = Vector3<double>(2000, 0, 0);
    getHeadMotionRequest().searchSize = Vector3<double>(1500, 2000, 0);
  );

  getHeadMotionRequest().searchDirection = true;
  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:reverseSearchDirection",
    getHeadMotionRequest().searchDirection = false;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:Stabilize",
    getHeadMotionRequest().id = HeadMotionRequest::stabilize;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:LookAtBall_image",
    if (getBallPercept().ballWasSeen)
    {
      getHeadMotionRequest().id = HeadMotionRequest::look_at_point;
      getHeadMotionRequest().targetPointInImage = getBallPercept().centerInImage;
    }
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:LookAtBall_field",
    if (getBallPercept().ballWasSeen)
    {
      getHeadMotionRequest().id = HeadMotionRequest::look_at_world_point;
      getHeadMotionRequest().targetPointInTheWorld.x = getBallPercept().bearingBasedOffsetOnField.x;
      getHeadMotionRequest().targetPointInTheWorld.y = getBallPercept().bearingBasedOffsetOnField.y;
      getHeadMotionRequest().targetPointInTheWorld.z = getFieldInfo().ballRadius;
    }
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:head:look_straight_ahead",
    getHeadMotionRequest().id = HeadMotionRequest::look_straight_ahead;
  );

	DEBUG_REQUEST("SimpleMotionBehaviorControl:head:look_at_attention_point",
		getHeadMotionRequest().id = HeadMotionRequest::look_at_point_on_the_ground;
		getHeadMotionRequest().targetPointOnTheGround = getAttentionModel().mostInterestingPoint;
  );

}//end testHead

void SimpleMotionBehaviorControl::testMotion()
{
  getMotionRequest().walkRequest.target = Pose2D();
  getMotionRequest().walkRequest.character = 0.5;

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:stand",
    getMotionRequest().id = motion::stand;
  );

  getMotionRequest().standardStand = false;
  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:standard_stand",
    getMotionRequest().standardStand = true;
      getMotionRequest().standHeight = -1; // minus means the same value as walk
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:sit",
    getMotionRequest().id = motion::sit;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:walk_forward",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.translation.x = 500;
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:walk_backward",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.translation.x = -500;
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:strafe_right",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.translation.y = -500;
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:strafe_left",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.translation.y = 500;
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:turn_right",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.rotation = Math::fromDegrees(-60);
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:turn_left",
    getMotionRequest().id = motion::walk;
    getMotionRequest().walkRequest.target.rotation = Math::fromDegrees(60);
    getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:stepping",
      getMotionRequest().id = motion::walk;
      getMotionRequest().walkRequest.target = Pose2D();
      getMotionRequest().walkRequest.coordinate = WalkRequest::Hip;
    );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:step_control",
   if ( getMotionStatus().stepControl.stepID % 5 == 0)
  {
    getMotionRequest().walkRequest.stepControl.stepID = getMotionStatus().stepControl.stepID;
    switch(getMotionStatus().stepControl.moveableFoot)
  {
    case MotionStatus::StepControlStatus::LEFT:
    case MotionStatus::StepControlStatus::BOTH:
    {
      getMotionRequest().walkRequest.stepControl.moveLeftFoot = true;
      getMotionRequest().walkRequest.coordinate = WalkRequest::LFoot;
      break;
    }
    case MotionStatus::StepControlStatus::RIGHT:
    {
      getMotionRequest().walkRequest.stepControl.moveLeftFoot = false;
      getMotionRequest().walkRequest.coordinate = WalkRequest::RFoot;
      break;
    }
    default: ASSERT(false);
      break;
    }
  double stepTime = 1000;
  double speedDirection = 0;
  MODIFY("StepControl.time",stepTime);
  MODIFY("StepControl.speedDirection",speedDirection);
    getMotionRequest().walkRequest.stepControl.target = Pose2D(0, 100, 0);
    getMotionRequest().walkRequest.stepControl.time = stepTime;
    getMotionRequest().walkRequest.stepControl.speedDirection = Math::fromDegrees(speedDirection);
  }
    );

  double offsetR = 0;
  MODIFY("walk.offset.r", offsetR);
  getMotionRequest().walkRequest.offset.rotation = Math::fromDegrees(offsetR);
  MODIFY("walk.offset.x", getMotionRequest().walkRequest.offset.translation.x);
  MODIFY("walk.offset.y", getMotionRequest().walkRequest.offset.translation.y);
  MODIFY("walk.character", getMotionRequest().walkRequest.character);

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:stand_up_from_front",
    getMotionRequest().id = motion::stand_up_from_front;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:stand_up_from_back",
    getMotionRequest().id = motion::stand_up_from_back;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:dead",
    getMotionRequest().id = motion::dead;
    getMotionRequest().forced = true;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:init",
    getMotionRequest().id = motion::init;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:dance",
    getMotionRequest().id = motion::dance;
  );

  DEBUG_REQUEST("SimpleMotionBehaviorControl:motion:protect_falling",
    getMotionRequest().id = motion::protect_falling;
  );

}//end testMotion

<|endoftext|>


<commit_before>// Copyright (c) 2009 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 "chrome/browser/extensions/crx_installer.h"

#include "app/l10n_util.h"
#include "base/file_util.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "base/task.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_file_util.h"
#include "chrome/common/extensions/extension_error_reporter.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "grit/chromium_strings.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/image_decoder.h"

namespace {
  // Helper function to delete files. This is used to avoid ugly casts which
  // would be necessary with PostMessage since file_util::Delete is overloaded.
  static void DeleteFileHelper(const FilePath& path, bool recursive) {
    file_util::Delete(path, recursive);
  }
}

void CrxInstaller::Start(const FilePath& crx_path,
                         const FilePath& install_directory,
                         Extension::Location install_source,
                         const std::string& expected_id,
                         bool delete_crx,
                         bool allow_privilege_increase,
                         MessageLoop* file_loop,
                         ExtensionsService* frontend,
                         ExtensionInstallUI* client) {
  // Note: We don't keep a reference because this object manages its own
  // lifetime.
  new CrxInstaller(crx_path, install_directory, install_source, expected_id,
                   delete_crx, allow_privilege_increase, file_loop, frontend,
                   client);
}

CrxInstaller::CrxInstaller(const FilePath& crx_path,
                           const FilePath& install_directory,
                           Extension::Location install_source,
                           const std::string& expected_id,
                           bool delete_crx,
                           bool allow_privilege_increase,
                           MessageLoop* file_loop,
                           ExtensionsService* frontend,
                           ExtensionInstallUI* client)
    : crx_path_(crx_path),
      install_directory_(install_directory),
      install_source_(install_source),
      expected_id_(expected_id),
      delete_crx_(delete_crx),
      allow_privilege_increase_(allow_privilege_increase),
      file_loop_(file_loop),
      ui_loop_(MessageLoop::current()),
      frontend_(frontend),
      client_(client) {

  extensions_enabled_ = frontend_->extensions_enabled();

  unpacker_ = new SandboxedExtensionUnpacker(
      crx_path, g_browser_process->resource_dispatcher_host(), this);

  file_loop->PostTask(FROM_HERE, NewRunnableMethod(unpacker_,
      &SandboxedExtensionUnpacker::Start));
}

CrxInstaller::~CrxInstaller() {
  // Delete the temp directory and crx file as necessary. Note that the
  // destructor might be called on any thread, so we post a task to the file
  // thread to make sure the delete happens there.
  if (!temp_dir_.value().empty()) {
    file_loop_->PostTask(FROM_HERE, NewRunnableFunction(&DeleteFileHelper,
        temp_dir_, true));  // recursive delete
  }

  if (delete_crx_) {
    file_loop_->PostTask(FROM_HERE, NewRunnableFunction(&DeleteFileHelper,
        crx_path_, false));  // non-recursive delete
  }
}

void CrxInstaller::OnUnpackFailure(const std::string& error_message) {
  DCHECK(MessageLoop::current() == file_loop_);
  ReportFailureFromFileThread(error_message);
}

void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir,
                                   const FilePath& extension_dir,
                                   Extension* extension) {
  DCHECK(MessageLoop::current() == file_loop_);

  // Note: We take ownership of |extension| and |temp_dir|.
  extension_.reset(extension);
  temp_dir_ = temp_dir;

  // The unpack dir we don't have to delete explicity since it is a child of
  // the temp dir.
  unpacked_extension_root_ = extension_dir;
  DCHECK(file_util::ContainsPath(temp_dir_, unpacked_extension_root_));

  // Determine whether to allow installation. We always allow themes and
  // external installs.
  if (!extensions_enabled_ && !extension->IsTheme() &&
      !Extension::IsExternalLocation(install_source_)) {
    ReportFailureFromFileThread("Extensions are not enabled.");
    return;
  }

  // Make sure the expected id matches.
  // TODO(aa): Also support expected version?
  if (!expected_id_.empty() && expected_id_ != extension->id()) {
    ReportFailureFromFileThread(StringPrintf(
        "ID in new extension manifest (%s) does not match expected id (%s)",
        extension->id().c_str(),
        expected_id_.c_str()));
    return;
  }

  if (client_.get()) {
    DecodeInstallIcon(extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE),
                      &install_icon_);
  }
  ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::ConfirmInstall));
}

// static
void CrxInstaller::DecodeInstallIcon(const FilePath& large_icon_path,
                                     scoped_ptr<SkBitmap>* result) {
  if (large_icon_path.empty())
    return;

  std::string file_contents;
  if (!file_util::ReadFileToString(large_icon_path, &file_contents)) {
    LOG(ERROR) << "Could not read icon file: "
               << WideToUTF8(large_icon_path.ToWStringHack());
    return;
  }

  // Decode the image using WebKit's image decoder.
  const unsigned char* data =
      reinterpret_cast<const unsigned char*>(file_contents.data());
  webkit_glue::ImageDecoder decoder;
  scoped_ptr<SkBitmap> decoded(new SkBitmap());
  *decoded = decoder.Decode(data, file_contents.length());
  if (decoded->empty()) {
    LOG(ERROR) << "Could not decode icon file: "
               << WideToUTF8(large_icon_path.ToWStringHack());
    return;
  }

  if (decoded->width() != 128 || decoded->height() != 128) {
    LOG(ERROR) << "Icon file has unexpected size: "
               << IntToString(decoded->width()) << "x"
               << IntToString(decoded->height());
    return;
  }

  result->swap(decoded);
}

void CrxInstaller::ConfirmInstall() {
  DCHECK(MessageLoop::current() == ui_loop_);
  if (frontend_->extension_prefs()->IsExtensionBlacklisted(extension_->id())) {
    LOG(INFO) << "This extension: " << extension_->id()
      << " is blacklisted. Install failed.";
    if (client_.get()) {
      client_->OnInstallFailure("This extension is blacklisted.");
    }
    return;
  }

  current_version_ =
      frontend_->extension_prefs()->GetVersionString(extension_->id());

  if (client_.get()) {
    AddRef();  // balanced in ContinueInstall() and AbortInstall().
    client_->ConfirmInstall(this, extension_.get(), install_icon_.get());
  } else {
    file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::CompleteInstall));
  }
  return;
}

void CrxInstaller::ContinueInstall() {
  file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::CompleteInstall));

  Release();  // balanced in ConfirmInstall().
}

void CrxInstaller::AbortInstall() {
  Release();  // balanced in ConfirmInstall().

  // We're done. Since we don't post any more tasks to ourself, our ref count
  // should go to zero and we die. The destructor will clean up the temp dir.
}

void CrxInstaller::CompleteInstall() {
  DCHECK(MessageLoop::current() == file_loop_);

  FilePath version_dir;
  Extension::InstallType install_type =
      extension_file_util::CompareToInstalledVersion(
          install_directory_, extension_->id(), current_version_,
          extension_->VersionString(), &version_dir);

  if (install_type == Extension::DOWNGRADE) {
    ReportFailureFromFileThread("Attempted to downgrade extension.");
    return;
  }

  if (install_type == Extension::REINSTALL) {
    // We use this as a signal to switch themes.
    ReportOverinstallFromFileThread();
    return;
  }

  std::string error_msg;
  if (!extension_file_util::InstallExtension(unpacked_extension_root_,
                                             version_dir, &error_msg)) {
    ReportFailureFromFileThread(error_msg);
    return;
  }

  // This is lame, but we must reload the extension because absolute paths
  // inside the content scripts are established inside InitFromValue() and we
  // just moved the extension.
  // TODO(aa): All paths to resources inside extensions should be created
  // lazily and based on the Extension's root path at that moment.
  std::string error;
  extension_.reset(extension_file_util::LoadExtension(version_dir, true,
                                                      &error));
  DCHECK(error.empty());
  extension_->set_location(install_source_);

  ReportSuccessFromFileThread();
}

void CrxInstaller::ReportFailureFromFileThread(const std::string& error) {
  DCHECK(MessageLoop::current() == file_loop_);
  ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::ReportFailureFromUIThread, error));
}

void CrxInstaller::ReportFailureFromUIThread(const std::string& error) {
  DCHECK(MessageLoop::current() == ui_loop_);

  NotificationService* service = NotificationService::current();
  service->Notify(NotificationType::NO_THEME_DETECTED,
                  Source<CrxInstaller>(this),
                  NotificationService::NoDetails());

  // This isn't really necessary, it is only used because unit tests expect to
  // see errors get reported via this interface.
  //
  // TODO(aa): Need to go through unit tests and clean them up too, probably get
  // rid of this line.
  ExtensionErrorReporter::GetInstance()->ReportError(error, false);  // quiet

  if (client_.get())
    client_->OnInstallFailure(error);
}

void CrxInstaller::ReportOverinstallFromFileThread() {
  DCHECK(MessageLoop::current() == file_loop_);
  ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::ReportOverinstallFromUIThread));
}

void CrxInstaller::ReportOverinstallFromUIThread() {
  DCHECK(MessageLoop::current() == ui_loop_);

  if (client_.get())
    client_->OnOverinstallAttempted(extension_.get());

  frontend_->OnExtensionOverinstallAttempted(extension_->id());
}

void CrxInstaller::ReportSuccessFromFileThread() {
  DCHECK(MessageLoop::current() == file_loop_);
  ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::ReportSuccessFromUIThread));
}

void CrxInstaller::ReportSuccessFromUIThread() {
  DCHECK(MessageLoop::current() == ui_loop_);

  // If there is a client, tell the client about installation.
  if (client_.get())
    client_->OnInstallSuccess(extension_.get());

  // Tell the frontend about the installation and hand off ownership of
  // extension_ to it.
  frontend_->OnExtensionInstalled(extension_.release(),
                                  allow_privilege_increase_);

  // We're done. We don't post any more tasks to ourselves so we are deleted
  // soon.
}
<commit_msg>Make sure theme loading bubble is cancelled when extension install is cancelled.<commit_after>// Copyright (c) 2009 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 "chrome/browser/extensions/crx_installer.h"

#include "app/l10n_util.h"
#include "base/file_util.h"
#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "base/task.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_file_util.h"
#include "chrome/common/extensions/extension_error_reporter.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "grit/chromium_strings.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/image_decoder.h"

namespace {
  // Helper function to delete files. This is used to avoid ugly casts which
  // would be necessary with PostMessage since file_util::Delete is overloaded.
  static void DeleteFileHelper(const FilePath& path, bool recursive) {
    file_util::Delete(path, recursive);
  }
}

void CrxInstaller::Start(const FilePath& crx_path,
                         const FilePath& install_directory,
                         Extension::Location install_source,
                         const std::string& expected_id,
                         bool delete_crx,
                         bool allow_privilege_increase,
                         MessageLoop* file_loop,
                         ExtensionsService* frontend,
                         ExtensionInstallUI* client) {
  // Note: We don't keep a reference because this object manages its own
  // lifetime.
  new CrxInstaller(crx_path, install_directory, install_source, expected_id,
                   delete_crx, allow_privilege_increase, file_loop, frontend,
                   client);
}

CrxInstaller::CrxInstaller(const FilePath& crx_path,
                           const FilePath& install_directory,
                           Extension::Location install_source,
                           const std::string& expected_id,
                           bool delete_crx,
                           bool allow_privilege_increase,
                           MessageLoop* file_loop,
                           ExtensionsService* frontend,
                           ExtensionInstallUI* client)
    : crx_path_(crx_path),
      install_directory_(install_directory),
      install_source_(install_source),
      expected_id_(expected_id),
      delete_crx_(delete_crx),
      allow_privilege_increase_(allow_privilege_increase),
      file_loop_(file_loop),
      ui_loop_(MessageLoop::current()),
      frontend_(frontend),
      client_(client) {

  extensions_enabled_ = frontend_->extensions_enabled();

  unpacker_ = new SandboxedExtensionUnpacker(
      crx_path, g_browser_process->resource_dispatcher_host(), this);

  file_loop->PostTask(FROM_HERE, NewRunnableMethod(unpacker_,
      &SandboxedExtensionUnpacker::Start));
}

CrxInstaller::~CrxInstaller() {
  // Delete the temp directory and crx file as necessary. Note that the
  // destructor might be called on any thread, so we post a task to the file
  // thread to make sure the delete happens there.
  if (!temp_dir_.value().empty()) {
    file_loop_->PostTask(FROM_HERE, NewRunnableFunction(&DeleteFileHelper,
        temp_dir_, true));  // recursive delete
  }

  if (delete_crx_) {
    file_loop_->PostTask(FROM_HERE, NewRunnableFunction(&DeleteFileHelper,
        crx_path_, false));  // non-recursive delete
  }
}

void CrxInstaller::OnUnpackFailure(const std::string& error_message) {
  DCHECK(MessageLoop::current() == file_loop_);
  ReportFailureFromFileThread(error_message);
}

void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir,
                                   const FilePath& extension_dir,
                                   Extension* extension) {
  DCHECK(MessageLoop::current() == file_loop_);

  // Note: We take ownership of |extension| and |temp_dir|.
  extension_.reset(extension);
  temp_dir_ = temp_dir;

  // The unpack dir we don't have to delete explicity since it is a child of
  // the temp dir.
  unpacked_extension_root_ = extension_dir;
  DCHECK(file_util::ContainsPath(temp_dir_, unpacked_extension_root_));

  // Determine whether to allow installation. We always allow themes and
  // external installs.
  if (!extensions_enabled_ && !extension->IsTheme() &&
      !Extension::IsExternalLocation(install_source_)) {
    ReportFailureFromFileThread("Extensions are not enabled.");
    return;
  }

  // Make sure the expected id matches.
  // TODO(aa): Also support expected version?
  if (!expected_id_.empty() && expected_id_ != extension->id()) {
    ReportFailureFromFileThread(StringPrintf(
        "ID in new extension manifest (%s) does not match expected id (%s)",
        extension->id().c_str(),
        expected_id_.c_str()));
    return;
  }

  if (client_.get()) {
    DecodeInstallIcon(extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE),
                      &install_icon_);
  }
  ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::ConfirmInstall));
}

// static
void CrxInstaller::DecodeInstallIcon(const FilePath& large_icon_path,
                                     scoped_ptr<SkBitmap>* result) {
  if (large_icon_path.empty())
    return;

  std::string file_contents;
  if (!file_util::ReadFileToString(large_icon_path, &file_contents)) {
    LOG(ERROR) << "Could not read icon file: "
               << WideToUTF8(large_icon_path.ToWStringHack());
    return;
  }

  // Decode the image using WebKit's image decoder.
  const unsigned char* data =
      reinterpret_cast<const unsigned char*>(file_contents.data());
  webkit_glue::ImageDecoder decoder;
  scoped_ptr<SkBitmap> decoded(new SkBitmap());
  *decoded = decoder.Decode(data, file_contents.length());
  if (decoded->empty()) {
    LOG(ERROR) << "Could not decode icon file: "
               << WideToUTF8(large_icon_path.ToWStringHack());
    return;
  }

  if (decoded->width() != 128 || decoded->height() != 128) {
    LOG(ERROR) << "Icon file has unexpected size: "
               << IntToString(decoded->width()) << "x"
               << IntToString(decoded->height());
    return;
  }

  result->swap(decoded);
}

void CrxInstaller::ConfirmInstall() {
  DCHECK(MessageLoop::current() == ui_loop_);
  if (frontend_->extension_prefs()->IsExtensionBlacklisted(extension_->id())) {
    LOG(INFO) << "This extension: " << extension_->id()
      << " is blacklisted. Install failed.";
    if (client_.get()) {
      client_->OnInstallFailure("This extension is blacklisted.");
    }
    return;
  }

  current_version_ =
      frontend_->extension_prefs()->GetVersionString(extension_->id());

  if (client_.get()) {
    AddRef();  // balanced in ContinueInstall() and AbortInstall().
    client_->ConfirmInstall(this, extension_.get(), install_icon_.get());
  } else {
    file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::CompleteInstall));
  }
  return;
}

void CrxInstaller::ContinueInstall() {
  file_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::CompleteInstall));

  Release();  // balanced in ConfirmInstall().
}

void CrxInstaller::AbortInstall() {
  // Kill the theme loading bubble.
  NotificationService* service = NotificationService::current();
  service->Notify(NotificationType::NO_THEME_DETECTED,
                  Source<CrxInstaller>(this),
                  NotificationService::NoDetails());
  Release();  // balanced in ConfirmInstall().

  // We're done. Since we don't post any more tasks to ourself, our ref count
  // should go to zero and we die. The destructor will clean up the temp dir.
}

void CrxInstaller::CompleteInstall() {
  DCHECK(MessageLoop::current() == file_loop_);

  FilePath version_dir;
  Extension::InstallType install_type =
      extension_file_util::CompareToInstalledVersion(
          install_directory_, extension_->id(), current_version_,
          extension_->VersionString(), &version_dir);

  if (install_type == Extension::DOWNGRADE) {
    ReportFailureFromFileThread("Attempted to downgrade extension.");
    return;
  }

  if (install_type == Extension::REINSTALL) {
    // We use this as a signal to switch themes.
    ReportOverinstallFromFileThread();
    return;
  }

  std::string error_msg;
  if (!extension_file_util::InstallExtension(unpacked_extension_root_,
                                             version_dir, &error_msg)) {
    ReportFailureFromFileThread(error_msg);
    return;
  }

  // This is lame, but we must reload the extension because absolute paths
  // inside the content scripts are established inside InitFromValue() and we
  // just moved the extension.
  // TODO(aa): All paths to resources inside extensions should be created
  // lazily and based on the Extension's root path at that moment.
  std::string error;
  extension_.reset(extension_file_util::LoadExtension(version_dir, true,
                                                      &error));
  DCHECK(error.empty());
  extension_->set_location(install_source_);

  ReportSuccessFromFileThread();
}

void CrxInstaller::ReportFailureFromFileThread(const std::string& error) {
  DCHECK(MessageLoop::current() == file_loop_);
  ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::ReportFailureFromUIThread, error));
}

void CrxInstaller::ReportFailureFromUIThread(const std::string& error) {
  DCHECK(MessageLoop::current() == ui_loop_);

  NotificationService* service = NotificationService::current();
  service->Notify(NotificationType::NO_THEME_DETECTED,
                  Source<CrxInstaller>(this),
                  NotificationService::NoDetails());

  // This isn't really necessary, it is only used because unit tests expect to
  // see errors get reported via this interface.
  //
  // TODO(aa): Need to go through unit tests and clean them up too, probably get
  // rid of this line.
  ExtensionErrorReporter::GetInstance()->ReportError(error, false);  // quiet

  if (client_.get())
    client_->OnInstallFailure(error);
}

void CrxInstaller::ReportOverinstallFromFileThread() {
  DCHECK(MessageLoop::current() == file_loop_);
  ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::ReportOverinstallFromUIThread));
}

void CrxInstaller::ReportOverinstallFromUIThread() {
  DCHECK(MessageLoop::current() == ui_loop_);

  if (client_.get())
    client_->OnOverinstallAttempted(extension_.get());

  frontend_->OnExtensionOverinstallAttempted(extension_->id());
}

void CrxInstaller::ReportSuccessFromFileThread() {
  DCHECK(MessageLoop::current() == file_loop_);
  ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
      &CrxInstaller::ReportSuccessFromUIThread));
}

void CrxInstaller::ReportSuccessFromUIThread() {
  DCHECK(MessageLoop::current() == ui_loop_);

  // If there is a client, tell the client about installation.
  if (client_.get())
    client_->OnInstallSuccess(extension_.get());

  // Tell the frontend about the installation and hand off ownership of
  // extension_ to it.
  frontend_->OnExtensionInstalled(extension_.release(),
                                  allow_privilege_increase_);

  // We're done. We don't post any more tasks to ourselves so we are deleted
  // soon.
}
<|endoftext|>


<commit_before>#include "doofit/plotting/Plot/Plot.h"

// STL
#include <string>
#include <sstream>
#include <vector>

// boost
#include <boost/regex.hpp>

// ROOT
#include "TIterator.h"

// from RooFit
#include "RooArgList.h"
#include "RooAbsRealLValue.h"
#include "RooAbsData.h"
#include "RooAbsPdf.h"
#include "RooPlot.h"
#include "RooHist.h"

// from Project
#include "doocore/io/MsgStream.h"
#include "doocore/lutils/lutils.h"
#include "doofit/plotting/Plot/PlotConfig.h"

using namespace ROOT;
using namespace RooFit;
using namespace doocore::io;

namespace doofit {
namespace plotting {

Plot::Plot(const PlotConfig& cfg_plot, const RooAbsRealLValue& dimension, const RooAbsData& dataset, const RooArgList& pdfs, const std::string& plot_name)
: config_plot_(cfg_plot),
  dimension_(dimension),
  datasets_(),
  plot_name_(plot_name)
{
  datasets_.push_back(&dataset);
  pdf_ = dynamic_cast<RooAbsPdf*>(pdfs.first());

  if (&dimension_ == NULL) {
    serr << "Plot::Plot(): Dimension is invalid." << endmsg;
    throw 1;
  }
  if (datasets_.front() == NULL) {
    serr << "Plot::Plot(): Dataset is invalid." << endmsg;
    throw 1;
  }
  if (plot_name_ == "") {
    plot_name_ = dimension_.GetName();
  }

  for (int i=1; i<pdfs.getSize(); ++i) {
    RooAbsArg* sub_arg = pdfs.at(i);
    const RooAbsPdf* sub_pdf = dynamic_cast<RooAbsPdf*>(sub_arg);

    if (sub_pdf != NULL) {
      components_.push_back(RooArgSet(*sub_pdf));
    }
  }
}

Plot::Plot(const PlotConfig& cfg_plot, const RooAbsRealLValue& dimension, const RooAbsData& dataset, const RooAbsPdf& pdf, const std::vector<std::string>& components, const std::string& plot_name)
: config_plot_(cfg_plot),
  dimension_(dimension),
  datasets_(),
  plot_name_(plot_name)
{
  datasets_.push_back(&dataset);
  pdf_ = &pdf;

  if (pdf_ == NULL) {
    serr << "Plot::Plot(): Main PDF is invalid." << endmsg;
    throw 1;
  }
  if (&dimension_ == NULL) {
    serr << "Plot::Plot(): Dimension is invalid." << endmsg;
    throw 1;
  }
  if (datasets_.front() == NULL) {
    serr << "Plot::Plot(): Dataset is invalid." << endmsg;
    throw 1;
  }
  if (plot_name_ == "") {
    plot_name_ = dimension_.GetName();
  }

  // iterate over sub PDFs and match supplied regular expressions
  RooArgSet nodes;
  pdf.branchNodeServerList(&nodes);

  for (std::vector<std::string>::const_iterator it = components.begin();
       it != components.end(); ++it) {
    boost::regex r(*it);
    components_.push_back(RooArgSet());

    TIterator* it_nodes = nodes.createIterator();
    RooAbsArg* node = NULL;

    while ((node = dynamic_cast<RooAbsArg*>(it_nodes->Next()))) {
      RooAbsPdf* pdf_node = dynamic_cast<RooAbsPdf*>(node);
      if (pdf_node != NULL) {
        std::string pdf_name = pdf_node->GetName();

        // exclude resolution models generated by RooFit and match the rest
        if (pdf_name.find("_conv_") == -1 && regex_match(pdf_name,r)) {
          components_.back().add(*pdf_node);
        }
      }
    }
    delete it_nodes;
  }
}

void Plot::PlotHandler(ScaleType sc_y, std::string suffix) const {
  if (suffix == "") suffix = "_log";

  std::string plot_name = plot_name_;

  std::stringstream log_plot_name_sstr;
  log_plot_name_sstr << plot_name << suffix;
  std::string log_plot_name = log_plot_name_sstr.str();

  std::stringstream pull_plot_sstr;
  pull_plot_sstr << plot_name << "_pull";
  std::string pull_plot_name = pull_plot_sstr.str();

  std::stringstream log_pull_plot_sstr;
  log_pull_plot_sstr << plot_name << "_pull" << suffix;
  std::string log_pull_plot_name = log_pull_plot_sstr.str();

  sinfo << "Plotting " << dimension_.GetName() << " into " << config_plot_.plot_directory() << plot_name << endmsg;

  doocore::lutils::setStyle("LHCb");

  RooCmdArg range_arg;

  // x range
  if (!dimension_.hasMin() && !dimension_.hasMax()) {
    double min, max;

    // ugly const_cast because RooFit is stupid (RooDataSet::getRange needs non-const RooRealVar)
    RooRealVar* dimension_non_const = const_cast<RooRealVar*>(dynamic_cast<const RooRealVar*>(&dimension_));
    datasets_.front()->getRange(*dimension_non_const, min, max);

    double min_t, max_t;
    for (std::vector<const RooAbsData*>::const_iterator it = datasets_.begin()+1;
         it != datasets_.end(); ++it) {
      (*it)->getRange(*dimension_non_const, min_t, max_t);
      if (min_t < min) min = min_t;
      if (max_t > max) max = max_t;
    }

    range_arg = Range(min, max);
  }
  RooPlot* plot_frame = dimension_.frame(range_arg);

  for (std::vector<const RooAbsData*>::const_iterator it = datasets_.begin();
       it != datasets_.end(); ++it) {
    (*it)->plotOn(plot_frame/*, Rescale(1.0/(*it)->sumEntries())*/);
  }

  // y range adaptively for log scale
  RooHist * data = (RooHist*) plot_frame->findObject(0,RooHist::Class());
  double x,y;
  data->GetPoint(0,x,y);
  double min_data_entry = y;
  for (unsigned int i = 1; i < data->GetN(); ++i) {
    data->GetPoint(0,x,y);
    if (min_data_entry > y) min_data_entry = y;
  }
  double min_plot = TMath::Power(10.0,TMath::Log10(min_data_entry)-0.7);

  sdebug << "minimum entry in histogram: " << min_data_entry << endmsg;
  sdebug << "minimum for plot range: " << min_plot << endmsg;

  TLatex label(0.65,0.85,"LHCb");

  config_plot_.OnDemandOpenPlotStack();
  if (pdf_ != NULL) {
    RooPlot* plot_frame_pull = dimension_.frame(range_arg);
    for (std::vector<const RooAbsData*>::const_iterator it = datasets_.begin();
         it != datasets_.end(); ++it) {
      (*it)->plotOn(plot_frame_pull);
    }

    // I feel so stupid doing this but apparently RooFit leaves me no other way...
    RooCmdArg arg1, arg2, arg3, arg4, arg5, arg6, arg7;
    if (plot_args_.size() > 0) arg1 = plot_args_[0];
    if (plot_args_.size() > 1) arg2 = plot_args_[1];
    if (plot_args_.size() > 2) arg3 = plot_args_[2];
    if (plot_args_.size() > 3) arg4 = plot_args_[3];
    if (plot_args_.size() > 4) arg5 = plot_args_[4];
    if (plot_args_.size() > 5) arg6 = plot_args_[5];
    if (plot_args_.size() > 6) arg7 = plot_args_[6];

    int i=1;
    for (std::vector<RooArgSet>::const_iterator it = components_.begin();
         it != components_.end(); ++it) {
      if (it->getSize() > 0) {
        sinfo << "Plotting component " << it->first()->GetName() << endmsg;
        pdf_->plotOn(plot_frame, Components(*it), LineColor(config_plot_.GetPdfLineColor(i)), LineStyle(config_plot_.GetPdfLineStyle(i)), arg1, arg2, arg3, arg4, arg5, arg6, arg7);
        pdf_->plotOn(plot_frame_pull, Components(*it), LineColor(config_plot_.GetPdfLineColor(i)), LineStyle(config_plot_.GetPdfLineStyle(i)), arg1, arg2, arg3, arg4, arg5, arg6, arg7);
        ++i;
      }
    }

    pdf_->plotOn(plot_frame, LineColor(config_plot_.GetPdfLineColor(0)), LineStyle(config_plot_.GetPdfLineStyle(0)), arg1, arg2, arg3, arg4, arg5, arg6, arg7);
    pdf_->plotOn(plot_frame_pull, LineColor(config_plot_.GetPdfLineColor(0)), LineStyle(config_plot_.GetPdfLineStyle(0)), arg1, arg2, arg3, arg4, arg5, arg6, arg7);

    // =10^(ln(11)/ln(10)-0.5)
    //plot_frame_pull->SetMinimum(0.5);

    plot_frame_pull->SetMinimum(0.5);
    plot_frame_pull->SetMaximum(1.3*plot_frame_pull->GetMaximum());
    if (sc_y == kLinear || sc_y == kBoth) {
      doocore::lutils::PlotPulls(pull_plot_name, plot_frame_pull, label, config_plot_.plot_directory(), false, false, true);
      doocore::lutils::PlotPulls("AllPlots", plot_frame_pull, label, config_plot_.plot_directory(), false, false, true, "");
    }

    plot_frame_pull->SetMinimum(min_plot);
    if (sc_y == kLogarithmic || sc_y == kBoth) {
      doocore::lutils::PlotPulls(log_pull_plot_name, plot_frame_pull, label, config_plot_.plot_directory(), true, false, true);
      doocore::lutils::PlotPulls("AllPlots", plot_frame_pull, label, config_plot_.plot_directory(), true, false, true, "");
    }

    delete plot_frame_pull;
  }

  plot_frame->SetMinimum(0.0);
  plot_frame->SetMaximum(1.3*plot_frame->GetMaximum());
  if (sc_y == kLinear || sc_y == kBoth) {
    doocore::lutils::PlotSimple(plot_name, plot_frame, label, config_plot_.plot_directory(), false);
    doocore::lutils::PlotSimple("AllPlots", plot_frame, label, config_plot_.plot_directory(), false);
  }

  plot_frame->SetMinimum(min_plot);
  if (sc_y == kLogarithmic || sc_y == kBoth) {
    doocore::lutils::PlotSimple(log_plot_name, plot_frame, label, config_plot_.plot_directory(), true);
    doocore::lutils::PlotSimple("AllPlots", plot_frame, label, config_plot_.plot_directory(), true);
  }

  delete plot_frame;
}

Plot::~Plot() {}

} // namespace plotting
} // namespace doofit
<commit_msg>Plotting: fixing other bugs in automated y range estimator<commit_after>#include "doofit/plotting/Plot/Plot.h"

// STL
#include <string>
#include <sstream>
#include <vector>

// boost
#include <boost/regex.hpp>

// ROOT
#include "TIterator.h"

// from RooFit
#include "RooArgList.h"
#include "RooAbsRealLValue.h"
#include "RooAbsData.h"
#include "RooAbsPdf.h"
#include "RooPlot.h"
#include "RooHist.h"

// from Project
#include "doocore/io/MsgStream.h"
#include "doocore/lutils/lutils.h"
#include "doofit/plotting/Plot/PlotConfig.h"

using namespace ROOT;
using namespace RooFit;
using namespace doocore::io;

namespace doofit {
namespace plotting {

Plot::Plot(const PlotConfig& cfg_plot, const RooAbsRealLValue& dimension, const RooAbsData& dataset, const RooArgList& pdfs, const std::string& plot_name)
: config_plot_(cfg_plot),
  dimension_(dimension),
  datasets_(),
  plot_name_(plot_name)
{
  datasets_.push_back(&dataset);
  pdf_ = dynamic_cast<RooAbsPdf*>(pdfs.first());

  if (&dimension_ == NULL) {
    serr << "Plot::Plot(): Dimension is invalid." << endmsg;
    throw 1;
  }
  if (datasets_.front() == NULL) {
    serr << "Plot::Plot(): Dataset is invalid." << endmsg;
    throw 1;
  }
  if (plot_name_ == "") {
    plot_name_ = dimension_.GetName();
  }

  for (int i=1; i<pdfs.getSize(); ++i) {
    RooAbsArg* sub_arg = pdfs.at(i);
    const RooAbsPdf* sub_pdf = dynamic_cast<RooAbsPdf*>(sub_arg);

    if (sub_pdf != NULL) {
      components_.push_back(RooArgSet(*sub_pdf));
    }
  }
}

Plot::Plot(const PlotConfig& cfg_plot, const RooAbsRealLValue& dimension, const RooAbsData& dataset, const RooAbsPdf& pdf, const std::vector<std::string>& components, const std::string& plot_name)
: config_plot_(cfg_plot),
  dimension_(dimension),
  datasets_(),
  plot_name_(plot_name)
{
  datasets_.push_back(&dataset);
  pdf_ = &pdf;

  if (pdf_ == NULL) {
    serr << "Plot::Plot(): Main PDF is invalid." << endmsg;
    throw 1;
  }
  if (&dimension_ == NULL) {
    serr << "Plot::Plot(): Dimension is invalid." << endmsg;
    throw 1;
  }
  if (datasets_.front() == NULL) {
    serr << "Plot::Plot(): Dataset is invalid." << endmsg;
    throw 1;
  }
  if (plot_name_ == "") {
    plot_name_ = dimension_.GetName();
  }

  // iterate over sub PDFs and match supplied regular expressions
  RooArgSet nodes;
  pdf.branchNodeServerList(&nodes);

  for (std::vector<std::string>::const_iterator it = components.begin();
       it != components.end(); ++it) {
    boost::regex r(*it);
    components_.push_back(RooArgSet());

    TIterator* it_nodes = nodes.createIterator();
    RooAbsArg* node = NULL;

    while ((node = dynamic_cast<RooAbsArg*>(it_nodes->Next()))) {
      RooAbsPdf* pdf_node = dynamic_cast<RooAbsPdf*>(node);
      if (pdf_node != NULL) {
        std::string pdf_name = pdf_node->GetName();

        // exclude resolution models generated by RooFit and match the rest
        if (pdf_name.find("_conv_") == -1 && regex_match(pdf_name,r)) {
          components_.back().add(*pdf_node);
        }
      }
    }
    delete it_nodes;
  }
}

void Plot::PlotHandler(ScaleType sc_y, std::string suffix) const {
  if (suffix == "") suffix = "_log";

  std::string plot_name = plot_name_;

  std::stringstream log_plot_name_sstr;
  log_plot_name_sstr << plot_name << suffix;
  std::string log_plot_name = log_plot_name_sstr.str();

  std::stringstream pull_plot_sstr;
  pull_plot_sstr << plot_name << "_pull";
  std::string pull_plot_name = pull_plot_sstr.str();

  std::stringstream log_pull_plot_sstr;
  log_pull_plot_sstr << plot_name << "_pull" << suffix;
  std::string log_pull_plot_name = log_pull_plot_sstr.str();

  sinfo << "Plotting " << dimension_.GetName() << " into " << config_plot_.plot_directory() << plot_name << endmsg;

  doocore::lutils::setStyle("LHCb");

  RooCmdArg range_arg;

  // x range
  if (!dimension_.hasMin() && !dimension_.hasMax()) {
    double min, max;

    // ugly const_cast because RooFit is stupid (RooDataSet::getRange needs non-const RooRealVar)
    RooRealVar* dimension_non_const = const_cast<RooRealVar*>(dynamic_cast<const RooRealVar*>(&dimension_));
    datasets_.front()->getRange(*dimension_non_const, min, max);

    double min_t, max_t;
    for (std::vector<const RooAbsData*>::const_iterator it = datasets_.begin()+1;
         it != datasets_.end(); ++it) {
      (*it)->getRange(*dimension_non_const, min_t, max_t);
      if (min_t < min) min = min_t;
      if (max_t > max) max = max_t;
    }

    range_arg = Range(min, max);
  }
  RooPlot* plot_frame = dimension_.frame(range_arg);

  for (std::vector<const RooAbsData*>::const_iterator it = datasets_.begin();
       it != datasets_.end(); ++it) {
    (*it)->plotOn(plot_frame/*, Rescale(1.0/(*it)->sumEntries())*/);
  }

  // y range adaptively for log scale
  RooHist * data = (RooHist*) plot_frame->findObject(0,RooHist::Class());
  double x,y;
  data->GetPoint(0,x,y);
  double min_data_entry = y;
  for (unsigned int i = 1; i < data->GetN(); ++i) {
    data->GetPoint(i,x,y);
    sdebug << y << endmsg;
    if (min_data_entry > y) min_data_entry = y;
  }
  double min_plot = TMath::Power(10.0,TMath::Log10(min_data_entry)-0.7);

  sdebug << "minimum entry in histogram: " << min_data_entry << endmsg;
  sdebug << "minimum for plot range: " << min_plot << endmsg;

  TLatex label(0.65,0.85,"LHCb");

  config_plot_.OnDemandOpenPlotStack();
  if (pdf_ != NULL) {
    RooPlot* plot_frame_pull = dimension_.frame(range_arg);
    for (std::vector<const RooAbsData*>::const_iterator it = datasets_.begin();
         it != datasets_.end(); ++it) {
      (*it)->plotOn(plot_frame_pull);
    }

    // I feel so stupid doing this but apparently RooFit leaves me no other way...
    RooCmdArg arg1, arg2, arg3, arg4, arg5, arg6, arg7;
    if (plot_args_.size() > 0) arg1 = plot_args_[0];
    if (plot_args_.size() > 1) arg2 = plot_args_[1];
    if (plot_args_.size() > 2) arg3 = plot_args_[2];
    if (plot_args_.size() > 3) arg4 = plot_args_[3];
    if (plot_args_.size() > 4) arg5 = plot_args_[4];
    if (plot_args_.size() > 5) arg6 = plot_args_[5];
    if (plot_args_.size() > 6) arg7 = plot_args_[6];

    int i=1;
    for (std::vector<RooArgSet>::const_iterator it = components_.begin();
         it != components_.end(); ++it) {
      if (it->getSize() > 0) {
        sinfo << "Plotting component " << it->first()->GetName() << endmsg;
        pdf_->plotOn(plot_frame, Components(*it), LineColor(config_plot_.GetPdfLineColor(i)), LineStyle(config_plot_.GetPdfLineStyle(i)), arg1, arg2, arg3, arg4, arg5, arg6, arg7);
        pdf_->plotOn(plot_frame_pull, Components(*it), LineColor(config_plot_.GetPdfLineColor(i)), LineStyle(config_plot_.GetPdfLineStyle(i)), arg1, arg2, arg3, arg4, arg5, arg6, arg7);
        ++i;
      }
    }

    pdf_->plotOn(plot_frame, LineColor(config_plot_.GetPdfLineColor(0)), LineStyle(config_plot_.GetPdfLineStyle(0)), arg1, arg2, arg3, arg4, arg5, arg6, arg7);
    pdf_->plotOn(plot_frame_pull, LineColor(config_plot_.GetPdfLineColor(0)), LineStyle(config_plot_.GetPdfLineStyle(0)), arg1, arg2, arg3, arg4, arg5, arg6, arg7);

    // =10^(ln(11)/ln(10)-0.5)
    //plot_frame_pull->SetMinimum(0.5);

    plot_frame_pull->SetMinimum(0.5);
    plot_frame_pull->SetMaximum(1.3*plot_frame_pull->GetMaximum());
    if (sc_y == kLinear || sc_y == kBoth) {
      doocore::lutils::PlotPulls(pull_plot_name, plot_frame_pull, label, config_plot_.plot_directory(), false, false, true);
      doocore::lutils::PlotPulls("AllPlots", plot_frame_pull, label, config_plot_.plot_directory(), false, false, true, "");
    }

    plot_frame_pull->SetMinimum(min_plot);
    if (sc_y == kLogarithmic || sc_y == kBoth) {
      doocore::lutils::PlotPulls(log_pull_plot_name, plot_frame_pull, label, config_plot_.plot_directory(), true, false, true);
      doocore::lutils::PlotPulls("AllPlots", plot_frame_pull, label, config_plot_.plot_directory(), true, false, true, "");
    }

    delete plot_frame_pull;
  }

  plot_frame->SetMinimum(0.0);
  plot_frame->SetMaximum(1.3*plot_frame->GetMaximum());
  if (sc_y == kLinear || sc_y == kBoth) {
    doocore::lutils::PlotSimple(plot_name, plot_frame, label, config_plot_.plot_directory(), false);
    doocore::lutils::PlotSimple("AllPlots", plot_frame, label, config_plot_.plot_directory(), false);
  }

  plot_frame->SetMinimum(min_plot);
  if (sc_y == kLogarithmic || sc_y == kBoth) {
    doocore::lutils::PlotSimple(log_plot_name, plot_frame, label, config_plot_.plot_directory(), true);
    doocore::lutils::PlotSimple("AllPlots", plot_frame, label, config_plot_.plot_directory(), true);
  }

  delete plot_frame;
}

Plot::~Plot() {}

} // namespace plotting
} // namespace doofit
<|endoftext|>


<commit_before>#include "country.hpp"

#include "../version/version.hpp"

#include "../platform/platform.hpp"

#include "../indexer/data_header.hpp"

#include "../coding/streams_sink.hpp"
#include "../coding/file_reader.hpp"
#include "../coding/file_writer.hpp"
#include "../coding/file_container.hpp"

#include "../base/logging.hpp"
#include "../base/std_serialization.hpp"
#include "../base/string_utils.hpp"

#include "../std/fstream.hpp"
#include "../std/ctime.hpp"

namespace storage
{
  /// Simple check - compare url size with real file size on disk
  bool IsTileDownloaded(TTile const & tile)
  {
    uint64_t size = 0;
    if (!GetPlatform().GetFileSize(GetPlatform().WritablePathForFile(tile.first), size))
      return false;
    return true;//tile.second == size;
  }

  struct CountryBoundsCalculator
  {
    m2::RectD & m_bounds;
    CountryBoundsCalculator(m2::RectD & bounds) : m_bounds(bounds) {}
    void operator()(TTile const & tile)
    {
      feature::DataHeader header;
      FilesContainerR reader(GetPlatform().WritablePathForFile(tile.first));
      header.Load(reader.GetReader(HEADER_FILE_TAG));
      m_bounds.Add(header.GetBounds());
    }
  };

  m2::RectD Country::Bounds() const
  {
    m2::RectD bounds;
    std::for_each(m_tiles.begin(), m_tiles.end(), CountryBoundsCalculator(bounds));
    return bounds;
  }

  struct SizeCalculator
  {
    uint64_t & m_localSize;
    uint64_t & m_remoteSize;
    SizeCalculator(uint64_t & localSize, uint64_t & remoteSize)
      : m_localSize(localSize), m_remoteSize(remoteSize) {}
    void operator()(TTile const & tile)
    {
      if (IsTileDownloaded(tile))
        m_localSize += tile.second;
      m_remoteSize += tile.second;
    }
  };

  TLocalAndRemoteSize Country::Size() const
  {
    uint64_t localSize = 0;
    uint64_t remoteSize = 0;
    std::for_each(m_tiles.begin(), m_tiles.end(), SizeCalculator(localSize, remoteSize));
    return TLocalAndRemoteSize(localSize, remoteSize);
  }

  void Country::AddTile(TTile const & tile)
  {
    m_tiles.push_back(tile);
  }

  ////////////////////////////////////////////////////////////////////////

//  template <class TArchive> TArchive & operator << (TArchive & ar, storage::Country const & country)
//  {
//    ar << country.m_name;
//    ar << country.m_tiles;
//    return ar;
//  }

  inline bool IsCellId(string const & cellId)
  {
    size_t const size = cellId.size();
    if (size == 0)
      return false;
    for (size_t i = 0; i < size; ++i)
    {
      if (cellId[i] < '0' || cellId[i] > '3')
        return false;
    }
    return true;
  }

  bool LoadCountries(file_t const & file, TTilesContainer const & sortedTiles,
                     TCountriesContainer & countries)
  {
    countries.Clear();

    string buffer;
    file.ReadAsString(buffer);
    istringstream stream(buffer);

    std::string line;
    Country * currentCountry = &countries.Value();
    while (stream.good())
    {
      std::getline(stream, line);
      if (line.empty())
        continue;

      // calculate spaces - depth inside the tree
      int spaces = 0;
      for (size_t i = 0; i < line.size(); ++i)
      {
        if (line[i] == ' ')
          ++spaces;
        else
          break;
      }
      switch (spaces)
      {
      case 0:
        CHECK(false, ("We should never be here"));
        break;
      case 1: // country group
      case 2: // country name
      case 3: // region
        {
          line = line.substr(spaces);
          strings::SimpleTokenizer tokIt(line, "|");
          // first string is country name, not always equal to country file name
          currentCountry = &countries.AddAtDepth(spaces - 1, Country(*tokIt));
          // skip if > 1 names in the list - first name never corresponds to tile file
          if (!tokIt.IsLast())
            ++tokIt;
          while (tokIt)
          {
            TTilesContainer::const_iterator const first = sortedTiles.begin();
            TTilesContainer::const_iterator const last = sortedTiles.end();
            string const nameWithExt = *tokIt + DATA_FILE_EXTENSION;
            TTilesContainer::const_iterator found = lower_bound(
                first, last, TTile(nameWithExt, 0));
            if (found != last && !(nameWithExt < found->first))
              currentCountry->AddTile(*found);
            ++tokIt;
          }
        }
        break;
      default:
        return false;
      }
    }
    return countries.SiblingsCount() > 0;
  }

  void SaveTiles(string const & file, int32_t level, TDataFiles const & cellFiles, TCommonFiles const & commonFiles)
  {
    FileWriter writer(file);
    stream::SinkWriterStream<Writer> wStream(writer);

    // save version - it's equal to current date in GMT
    time_t rawTime = time(NULL);
    tm * pTm = gmtime(&rawTime);
    uint32_t const version = (pTm->tm_year - 100) * 10000 + (pTm->tm_mon + 1) * 100 + pTm->tm_mday;
    wStream << static_cast<uint32_t>(version);
    wStream << level;
    wStream << cellFiles;
    wStream << commonFiles;
  }

  bool LoadTiles(file_t const & file, TTilesContainer & tiles, uint32_t & dataVersion)
  {
    tiles.clear();

    try
    {
      ReaderSource<file_t> source(file);
      stream::SinkReaderStream<ReaderSource<file_t> > stream(source);

      TDataFiles dataFiles;
      TCommonFiles commonFiles;

      int32_t level = -1;
      stream >> dataVersion;
      stream >> level;
      stream >> dataFiles;
      stream >> commonFiles;

      tiles.reserve(dataFiles.size() + commonFiles.size());

      for (TDataFiles::iterator it = dataFiles.begin(); it != dataFiles.end(); ++it)
        tiles.push_back(TTile(CountryCellId::FromBitsAndLevel(it->first, level).ToString(), it->second));
      for (TCommonFiles::iterator it = commonFiles.begin(); it != commonFiles.end(); ++it)
        tiles.push_back(TTile(it->first, it->second));

      sort(tiles.begin(), tiles.end());
    }
    catch (RootException const & e)
    {
      LOG(LWARNING, ("Can't read tiles file", e.what()));
      return false;
    }

    return true;
  }

//  void SaveCountries(TCountriesContainer const & countries, Writer & writer)
//  {
//    stream::SinkWriterStream<Writer> wStream(writer);
//    wStream << MAPS_MAJOR_VERSION_BINARY_FORMAT;
//    wStream << countries;
//  }
}
<commit_msg>Added const qualifier<commit_after>#include "country.hpp"

#include "../version/version.hpp"

#include "../platform/platform.hpp"

#include "../indexer/data_header.hpp"

#include "../coding/streams_sink.hpp"
#include "../coding/file_reader.hpp"
#include "../coding/file_writer.hpp"
#include "../coding/file_container.hpp"

#include "../base/logging.hpp"
#include "../base/std_serialization.hpp"
#include "../base/string_utils.hpp"

#include "../std/fstream.hpp"
#include "../std/ctime.hpp"

namespace storage
{
  /// Simple check - compare url size with real file size on disk
  bool IsTileDownloaded(TTile const & tile)
  {
    uint64_t size = 0;
    if (!GetPlatform().GetFileSize(GetPlatform().WritablePathForFile(tile.first), size))
      return false;
    return true;//tile.second == size;
  }

  struct CountryBoundsCalculator
  {
    m2::RectD & m_bounds;
    CountryBoundsCalculator(m2::RectD & bounds) : m_bounds(bounds) {}
    void operator()(TTile const & tile)
    {
      feature::DataHeader header;
      FilesContainerR reader(GetPlatform().WritablePathForFile(tile.first));
      header.Load(reader.GetReader(HEADER_FILE_TAG));
      m_bounds.Add(header.GetBounds());
    }
  };

  m2::RectD Country::Bounds() const
  {
    m2::RectD bounds;
    std::for_each(m_tiles.begin(), m_tiles.end(), CountryBoundsCalculator(bounds));
    return bounds;
  }

  struct SizeCalculator
  {
    uint64_t & m_localSize;
    uint64_t & m_remoteSize;
    SizeCalculator(uint64_t & localSize, uint64_t & remoteSize)
      : m_localSize(localSize), m_remoteSize(remoteSize) {}
    void operator()(TTile const & tile)
    {
      if (IsTileDownloaded(tile))
        m_localSize += tile.second;
      m_remoteSize += tile.second;
    }
  };

  TLocalAndRemoteSize Country::Size() const
  {
    uint64_t localSize = 0;
    uint64_t remoteSize = 0;
    std::for_each(m_tiles.begin(), m_tiles.end(), SizeCalculator(localSize, remoteSize));
    return TLocalAndRemoteSize(localSize, remoteSize);
  }

  void Country::AddTile(TTile const & tile)
  {
    m_tiles.push_back(tile);
  }

  ////////////////////////////////////////////////////////////////////////

//  template <class TArchive> TArchive & operator << (TArchive & ar, storage::Country const & country)
//  {
//    ar << country.m_name;
//    ar << country.m_tiles;
//    return ar;
//  }

  inline bool IsCellId(string const & cellId)
  {
    size_t const size = cellId.size();
    if (size == 0)
      return false;
    for (size_t i = 0; i < size; ++i)
    {
      if (cellId[i] < '0' || cellId[i] > '3')
        return false;
    }
    return true;
  }

  bool LoadCountries(file_t const & file, TTilesContainer const & sortedTiles,
                     TCountriesContainer & countries)
  {
    countries.Clear();

    string buffer;
    file.ReadAsString(buffer);
    istringstream stream(buffer);

    std::string line;
    Country * currentCountry = &countries.Value();
    while (stream.good())
    {
      std::getline(stream, line);
      if (line.empty())
        continue;

      // calculate spaces - depth inside the tree
      int spaces = 0;
      for (size_t i = 0; i < line.size(); ++i)
      {
        if (line[i] == ' ')
          ++spaces;
        else
          break;
      }
      switch (spaces)
      {
      case 0:
        CHECK(false, ("We should never be here"));
        break;
      case 1: // country group
      case 2: // country name
      case 3: // region
        {
          line = line.substr(spaces);
          strings::SimpleTokenizer tokIt(line, "|");
          // first string is country name, not always equal to country file name
          currentCountry = &countries.AddAtDepth(spaces - 1, Country(*tokIt));
          // skip if > 1 names in the list - first name never corresponds to tile file
          if (!tokIt.IsLast())
            ++tokIt;
          while (tokIt)
          {
            TTilesContainer::const_iterator const first = sortedTiles.begin();
            TTilesContainer::const_iterator const last = sortedTiles.end();
            string const nameWithExt = *tokIt + DATA_FILE_EXTENSION;
            TTilesContainer::const_iterator const found = lower_bound(
                first, last, TTile(nameWithExt, 0));
            if (found != last && !(nameWithExt < found->first))
              currentCountry->AddTile(*found);
            ++tokIt;
          }
        }
        break;
      default:
        return false;
      }
    }
    return countries.SiblingsCount() > 0;
  }

  void SaveTiles(string const & file, int32_t level, TDataFiles const & cellFiles, TCommonFiles const & commonFiles)
  {
    FileWriter writer(file);
    stream::SinkWriterStream<Writer> wStream(writer);

    // save version - it's equal to current date in GMT
    time_t rawTime = time(NULL);
    tm * pTm = gmtime(&rawTime);
    uint32_t const version = (pTm->tm_year - 100) * 10000 + (pTm->tm_mon + 1) * 100 + pTm->tm_mday;
    wStream << static_cast<uint32_t>(version);
    wStream << level;
    wStream << cellFiles;
    wStream << commonFiles;
  }

  bool LoadTiles(file_t const & file, TTilesContainer & tiles, uint32_t & dataVersion)
  {
    tiles.clear();

    try
    {
      ReaderSource<file_t> source(file);
      stream::SinkReaderStream<ReaderSource<file_t> > stream(source);

      TDataFiles dataFiles;
      TCommonFiles commonFiles;

      int32_t level = -1;
      stream >> dataVersion;
      stream >> level;
      stream >> dataFiles;
      stream >> commonFiles;

      tiles.reserve(dataFiles.size() + commonFiles.size());

      for (TDataFiles::iterator it = dataFiles.begin(); it != dataFiles.end(); ++it)
        tiles.push_back(TTile(CountryCellId::FromBitsAndLevel(it->first, level).ToString(), it->second));
      for (TCommonFiles::iterator it = commonFiles.begin(); it != commonFiles.end(); ++it)
        tiles.push_back(TTile(it->first, it->second));

      sort(tiles.begin(), tiles.end());
    }
    catch (RootException const & e)
    {
      LOG(LWARNING, ("Can't read tiles file", e.what()));
      return false;
    }

    return true;
  }

//  void SaveCountries(TCountriesContainer const & countries, Writer & writer)
//  {
//    stream::SinkWriterStream<Writer> wStream(writer);
//    wStream << MAPS_MAJOR_VERSION_BINARY_FORMAT;
//    wStream << countries;
//  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "chrome/browser/net/load_timing_observer.h"

#include "base/time.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "chrome/common/resource_response.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_netlog_params.h"

using base::Time;
using base::TimeTicks;
using webkit_glue::ResourceLoaderBridge;
using webkit_glue::ResourceLoadTimingInfo;

const size_t kMaxNumEntries = 1000;

namespace {

// We know that this conversion is not solid and suffers from world clock
// changes, but it should be good enough for the load timing info.
static Time TimeTicksToTime(const TimeTicks& time_ticks) {
  static int64 tick_to_time_offset;
  static bool tick_to_time_offset_available = false;
  if (!tick_to_time_offset_available) {
    int64 cur_time = (Time::Now() - Time()).InMicroseconds();
    int64 cur_time_ticks = (TimeTicks::Now() - TimeTicks()).InMicroseconds();
    // If we add this number to a time tick value, it gives the timestamp.
    tick_to_time_offset = cur_time - cur_time_ticks;
    tick_to_time_offset_available = true;
  }
  return Time::FromInternalValue(time_ticks.ToInternalValue() +
                                 tick_to_time_offset);
}

static int32 TimeTicksToOffset(
    const TimeTicks& time_ticks,
    LoadTimingObserver::URLRequestRecord* record) {
  return static_cast<int32>(
      (time_ticks - record->base_ticks).InMillisecondsRoundedUp());
}

}  // namespace

LoadTimingObserver::URLRequestRecord::URLRequestRecord()
    : connect_job_id(net::NetLog::Source::kInvalidId),
      socket_log_id(net::NetLog::Source::kInvalidId),
      socket_reused(false) {
}

LoadTimingObserver::LoadTimingObserver()
    : ThreadSafeObserver(net::NetLog::LOG_BASIC),
      last_connect_job_id_(net::NetLog::Source::kInvalidId) {
}

LoadTimingObserver::~LoadTimingObserver() {
}

LoadTimingObserver::URLRequestRecord*
LoadTimingObserver::GetURLRequestRecord(uint32 source_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  URLRequestToRecordMap::iterator it = url_request_to_record_.find(source_id);
  if (it != url_request_to_record_.end())
    return &it->second;
  return NULL;
}

void LoadTimingObserver::OnAddEntry(net::NetLog::EventType type,
                                    const base::TimeTicks& time,
                                    const net::NetLog::Source& source,
                                    net::NetLog::EventPhase phase,
                                    net::NetLog::EventParameters* params) {
  // The events that the Observer is interested in only occur on the IO thread.
  if (!BrowserThread::CurrentlyOn(BrowserThread::IO))
    return;
  if (source.type == net::NetLog::SOURCE_URL_REQUEST)
    OnAddURLRequestEntry(type, time, source, phase, params);
  else if (source.type == net::NetLog::SOURCE_CONNECT_JOB)
    OnAddConnectJobEntry(type, time, source, phase, params);
  else if (source.type == net::NetLog::SOURCE_SOCKET)
    OnAddSocketEntry(type, time, source, phase, params);
}

// static
void LoadTimingObserver::PopulateTimingInfo(net::URLRequest* request,
                                            ResourceResponse* response) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (!(request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING))
    return;

  ChromeNetLog* chrome_net_log = static_cast<ChromeNetLog*>(
      request->net_log().net_log());
  if (chrome_net_log == NULL)
    return;

  uint32 source_id = request->net_log().source().id;
  LoadTimingObserver* observer = chrome_net_log->load_timing_observer();
  LoadTimingObserver::URLRequestRecord* record =
      observer->GetURLRequestRecord(source_id);
  if (record) {
    response->response_head.connection_id = record->socket_log_id;
    response->response_head.connection_reused = record->socket_reused;
    response->response_head.load_timing = record->timing;
  }
}

void LoadTimingObserver::OnAddURLRequestEntry(
    net::NetLog::EventType type,
    const base::TimeTicks& time,
    const net::NetLog::Source& source,
    net::NetLog::EventPhase phase,
    net::NetLog::EventParameters* params) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  bool is_begin = phase == net::NetLog::PHASE_BEGIN;
  bool is_end = phase == net::NetLog::PHASE_END;

  if (type == net::NetLog::TYPE_URL_REQUEST_START_JOB) {
    if (is_begin) {
      // Only record timing for entries with corresponding flag.
      int load_flags = static_cast<URLRequestStartEventParameters*>(params)->
          load_flags();
      if (!(load_flags & net::LOAD_ENABLE_LOAD_TIMING))
        return;

      // Prevents us from passively growing the memory memory unbounded in case
      // something went wrong. Should not happen.
      if (url_request_to_record_.size() > kMaxNumEntries) {
        LOG(WARNING) << "The load timing observer url request count has grown "
                        "larger than expected, resetting";
        url_request_to_record_.clear();
      }

      URLRequestRecord& record = url_request_to_record_[source.id];
      record.base_ticks = time;
      record.timing.base_time = TimeTicksToTime(time);
    }
    return;
  } else if (type == net::NetLog::TYPE_REQUEST_ALIVE) {
    // Cleanup records based on the TYPE_REQUEST_ALIVE entry.
    if (is_end)
      url_request_to_record_.erase(source.id);
    return;
  }

  URLRequestRecord* record = GetURLRequestRecord(source.id);
  if (!record)
    return;

  ResourceLoadTimingInfo& timing = record->timing;

  switch (type) {
    case net::NetLog::TYPE_PROXY_SERVICE:
      if (is_begin)
        timing.proxy_start = TimeTicksToOffset(time, record);
      else if (is_end)
        timing.proxy_end = TimeTicksToOffset(time, record);
      break;
    case net::NetLog::TYPE_SOCKET_POOL:
      if (is_begin)
        timing.connect_start = TimeTicksToOffset(time, record);
      else if (is_end)
        timing.connect_end = TimeTicksToOffset(time, record);
      break;
    case net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB:
      {
        uint32 connect_job_id = static_cast<net::NetLogSourceParameter*>(
            params)->value().id;
        if (last_connect_job_id_ == connect_job_id &&
            !last_connect_job_record_.dns_start.is_null()) {
          timing.dns_start =
              TimeTicksToOffset(last_connect_job_record_.dns_start, record);
          timing.dns_end =
              TimeTicksToOffset(last_connect_job_record_.dns_end, record);
        }
      }
      break;
    case net::NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET:
      record->socket_reused = true;
      break;
    case net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET:
      record->socket_log_id = static_cast<net::NetLogSourceParameter*>(
          params)->value().id;
      if (!record->socket_reused) {
        SocketToRecordMap::iterator it =
            socket_to_record_.find(record->socket_log_id);
        if (it != socket_to_record_.end() && !it->second.ssl_start.is_null()) {
          timing.ssl_start = TimeTicksToOffset(it->second.ssl_start, record);
          timing.ssl_end = TimeTicksToOffset(it->second.ssl_end, record);
        }
      }
      break;
    case net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST:
      if (is_begin)
        timing.send_start = TimeTicksToOffset(time, record);
      else if (is_end)
        timing.send_end = TimeTicksToOffset(time, record);
      break;
    case net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS:
      if (is_begin)
        timing.receive_headers_start =  TimeTicksToOffset(time, record);
      else if (is_end)
        timing.receive_headers_end =  TimeTicksToOffset(time, record);
      break;
    default:
      break;
  }
}

void LoadTimingObserver::OnAddConnectJobEntry(
    net::NetLog::EventType type,
    const base::TimeTicks& time,
    const net::NetLog::Source& source,
    net::NetLog::EventPhase phase,
    net::NetLog::EventParameters* params) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  bool is_begin = phase == net::NetLog::PHASE_BEGIN;
  bool is_end = phase == net::NetLog::PHASE_END;

  // Manage record lifetime based on the SOCKET_POOL_CONNECT_JOB entry.
  if (type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB) {
    if (is_begin) {
      // Prevents us from passively growing the memory memory unbounded in case
      // something went wrong. Should not happen.
      if (connect_job_to_record_.size() > kMaxNumEntries) {
        LOG(WARNING) << "The load timing observer connect job count has grown "
                        "larger than expected, resetting";
        connect_job_to_record_.clear();
      }

      connect_job_to_record_.insert(
          std::make_pair(source.id, ConnectJobRecord()));
    } else if (is_end) {
      ConnectJobToRecordMap::iterator it =
          connect_job_to_record_.find(source.id);
      if (it != connect_job_to_record_.end()) {
        last_connect_job_id_ = it->first;
        last_connect_job_record_ = it->second;
        connect_job_to_record_.erase(it);
      }
    }
  } else if (type == net::NetLog::TYPE_HOST_RESOLVER_IMPL) {
    ConnectJobToRecordMap::iterator it =
        connect_job_to_record_.find(source.id);
    if (it != connect_job_to_record_.end()) {
      if (is_begin)
        it->second.dns_start = time;
      else if (is_end)
        it->second.dns_end = time;
    }
  }
}

void LoadTimingObserver::OnAddSocketEntry(
    net::NetLog::EventType type,
    const base::TimeTicks& time,
    const net::NetLog::Source& source,
    net::NetLog::EventPhase phase,
    net::NetLog::EventParameters* params) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  bool is_begin = phase == net::NetLog::PHASE_BEGIN;
  bool is_end = phase == net::NetLog::PHASE_END;

  // Manage record lifetime based on the SOCKET_ALIVE entry.
  if (type == net::NetLog::TYPE_SOCKET_ALIVE) {
    if (is_begin) {
      // Prevents us from passively growing the memory memory unbounded in case
      // something went wrong. Should not happen.
      if (socket_to_record_.size() > kMaxNumEntries) {
        LOG(WARNING) << "The load timing observer socket count has grown "
                        "larger than expected, resetting";
        socket_to_record_.clear();
      }

      socket_to_record_.insert(
          std::make_pair(source.id, SocketRecord()));
    } else if (is_end) {
      socket_to_record_.erase(source.id);
    }
    return;
  }
  SocketToRecordMap::iterator it = socket_to_record_.find(source.id);
  if (it == socket_to_record_.end())
    return;

  if (type == net::NetLog::TYPE_SSL_CONNECT) {
    if (is_begin)
      it->second.ssl_start = time;
    else if (is_end)
      it->second.ssl_end = time;
  }
}
<commit_msg>DevTools: Network requests are timed with 1.6 days.<commit_after>// Copyright (c) 2010 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 "chrome/browser/net/load_timing_observer.h"

#include "base/time.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "chrome/common/resource_response.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_netlog_params.h"

using base::Time;
using base::TimeTicks;
using webkit_glue::ResourceLoaderBridge;
using webkit_glue::ResourceLoadTimingInfo;

const size_t kMaxNumEntries = 1000;

namespace {

const int64 kSyncPeriodMicroseconds = 1000 * 1000 * 10;

// We know that this conversion is not solid and suffers from world clock
// changes, but given that we sync clock every 10 seconds, it should be good
// enough for the load timing info.
static Time TimeTicksToTime(const TimeTicks& time_ticks) {
  static int64 tick_to_time_offset;
  static int64 last_sync_ticks = 0;
  if (time_ticks.ToInternalValue() - last_sync_ticks >
          kSyncPeriodMicroseconds) {
    int64 cur_time = (Time::Now() - Time()).InMicroseconds();
    int64 cur_time_ticks = (TimeTicks::Now() - TimeTicks()).InMicroseconds();
    // If we add this number to a time tick value, it gives the timestamp.
    tick_to_time_offset = cur_time - cur_time_ticks;
    last_sync_ticks = time_ticks.ToInternalValue();
  }
  return Time::FromInternalValue(time_ticks.ToInternalValue() +
                                 tick_to_time_offset);
}

static int32 TimeTicksToOffset(
    const TimeTicks& time_ticks,
    LoadTimingObserver::URLRequestRecord* record) {
  return static_cast<int32>(
      (time_ticks - record->base_ticks).InMillisecondsRoundedUp());
}

}  // namespace

LoadTimingObserver::URLRequestRecord::URLRequestRecord()
    : connect_job_id(net::NetLog::Source::kInvalidId),
      socket_log_id(net::NetLog::Source::kInvalidId),
      socket_reused(false) {
}

LoadTimingObserver::LoadTimingObserver()
    : ThreadSafeObserver(net::NetLog::LOG_BASIC),
      last_connect_job_id_(net::NetLog::Source::kInvalidId) {
}

LoadTimingObserver::~LoadTimingObserver() {
}

LoadTimingObserver::URLRequestRecord*
LoadTimingObserver::GetURLRequestRecord(uint32 source_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  URLRequestToRecordMap::iterator it = url_request_to_record_.find(source_id);
  if (it != url_request_to_record_.end())
    return &it->second;
  return NULL;
}

void LoadTimingObserver::OnAddEntry(net::NetLog::EventType type,
                                    const base::TimeTicks& time,
                                    const net::NetLog::Source& source,
                                    net::NetLog::EventPhase phase,
                                    net::NetLog::EventParameters* params) {
  // The events that the Observer is interested in only occur on the IO thread.
  if (!BrowserThread::CurrentlyOn(BrowserThread::IO))
    return;
  if (source.type == net::NetLog::SOURCE_URL_REQUEST)
    OnAddURLRequestEntry(type, time, source, phase, params);
  else if (source.type == net::NetLog::SOURCE_CONNECT_JOB)
    OnAddConnectJobEntry(type, time, source, phase, params);
  else if (source.type == net::NetLog::SOURCE_SOCKET)
    OnAddSocketEntry(type, time, source, phase, params);
}

// static
void LoadTimingObserver::PopulateTimingInfo(net::URLRequest* request,
                                            ResourceResponse* response) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (!(request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING))
    return;

  ChromeNetLog* chrome_net_log = static_cast<ChromeNetLog*>(
      request->net_log().net_log());
  if (chrome_net_log == NULL)
    return;

  uint32 source_id = request->net_log().source().id;
  LoadTimingObserver* observer = chrome_net_log->load_timing_observer();
  LoadTimingObserver::URLRequestRecord* record =
      observer->GetURLRequestRecord(source_id);
  if (record) {
    response->response_head.connection_id = record->socket_log_id;
    response->response_head.connection_reused = record->socket_reused;
    response->response_head.load_timing = record->timing;
  }
}

void LoadTimingObserver::OnAddURLRequestEntry(
    net::NetLog::EventType type,
    const base::TimeTicks& time,
    const net::NetLog::Source& source,
    net::NetLog::EventPhase phase,
    net::NetLog::EventParameters* params) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  bool is_begin = phase == net::NetLog::PHASE_BEGIN;
  bool is_end = phase == net::NetLog::PHASE_END;

  if (type == net::NetLog::TYPE_URL_REQUEST_START_JOB) {
    if (is_begin) {
      // Only record timing for entries with corresponding flag.
      int load_flags = static_cast<URLRequestStartEventParameters*>(params)->
          load_flags();
      if (!(load_flags & net::LOAD_ENABLE_LOAD_TIMING))
        return;

      // Prevents us from passively growing the memory memory unbounded in case
      // something went wrong. Should not happen.
      if (url_request_to_record_.size() > kMaxNumEntries) {
        LOG(WARNING) << "The load timing observer url request count has grown "
                        "larger than expected, resetting";
        url_request_to_record_.clear();
      }

      URLRequestRecord& record = url_request_to_record_[source.id];
      record.base_ticks = time;
      record.timing.base_time = TimeTicksToTime(time);
    }
    return;
  } else if (type == net::NetLog::TYPE_REQUEST_ALIVE) {
    // Cleanup records based on the TYPE_REQUEST_ALIVE entry.
    if (is_end)
      url_request_to_record_.erase(source.id);
    return;
  }

  URLRequestRecord* record = GetURLRequestRecord(source.id);
  if (!record)
    return;

  ResourceLoadTimingInfo& timing = record->timing;

  switch (type) {
    case net::NetLog::TYPE_PROXY_SERVICE:
      if (is_begin)
        timing.proxy_start = TimeTicksToOffset(time, record);
      else if (is_end)
        timing.proxy_end = TimeTicksToOffset(time, record);
      break;
    case net::NetLog::TYPE_SOCKET_POOL:
      if (is_begin)
        timing.connect_start = TimeTicksToOffset(time, record);
      else if (is_end)
        timing.connect_end = TimeTicksToOffset(time, record);
      break;
    case net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB:
      {
        uint32 connect_job_id = static_cast<net::NetLogSourceParameter*>(
            params)->value().id;
        if (last_connect_job_id_ == connect_job_id &&
            !last_connect_job_record_.dns_start.is_null()) {
          timing.dns_start =
              TimeTicksToOffset(last_connect_job_record_.dns_start, record);
          timing.dns_end =
              TimeTicksToOffset(last_connect_job_record_.dns_end, record);
        }
      }
      break;
    case net::NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET:
      record->socket_reused = true;
      break;
    case net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET:
      record->socket_log_id = static_cast<net::NetLogSourceParameter*>(
          params)->value().id;
      if (!record->socket_reused) {
        SocketToRecordMap::iterator it =
            socket_to_record_.find(record->socket_log_id);
        if (it != socket_to_record_.end() && !it->second.ssl_start.is_null()) {
          timing.ssl_start = TimeTicksToOffset(it->second.ssl_start, record);
          timing.ssl_end = TimeTicksToOffset(it->second.ssl_end, record);
        }
      }
      break;
    case net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST:
      if (is_begin)
        timing.send_start = TimeTicksToOffset(time, record);
      else if (is_end)
        timing.send_end = TimeTicksToOffset(time, record);
      break;
    case net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS:
      if (is_begin)
        timing.receive_headers_start =  TimeTicksToOffset(time, record);
      else if (is_end)
        timing.receive_headers_end =  TimeTicksToOffset(time, record);
      break;
    default:
      break;
  }
}

void LoadTimingObserver::OnAddConnectJobEntry(
    net::NetLog::EventType type,
    const base::TimeTicks& time,
    const net::NetLog::Source& source,
    net::NetLog::EventPhase phase,
    net::NetLog::EventParameters* params) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  bool is_begin = phase == net::NetLog::PHASE_BEGIN;
  bool is_end = phase == net::NetLog::PHASE_END;

  // Manage record lifetime based on the SOCKET_POOL_CONNECT_JOB entry.
  if (type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB) {
    if (is_begin) {
      // Prevents us from passively growing the memory memory unbounded in case
      // something went wrong. Should not happen.
      if (connect_job_to_record_.size() > kMaxNumEntries) {
        LOG(WARNING) << "The load timing observer connect job count has grown "
                        "larger than expected, resetting";
        connect_job_to_record_.clear();
      }

      connect_job_to_record_.insert(
          std::make_pair(source.id, ConnectJobRecord()));
    } else if (is_end) {
      ConnectJobToRecordMap::iterator it =
          connect_job_to_record_.find(source.id);
      if (it != connect_job_to_record_.end()) {
        last_connect_job_id_ = it->first;
        last_connect_job_record_ = it->second;
        connect_job_to_record_.erase(it);
      }
    }
  } else if (type == net::NetLog::TYPE_HOST_RESOLVER_IMPL) {
    ConnectJobToRecordMap::iterator it =
        connect_job_to_record_.find(source.id);
    if (it != connect_job_to_record_.end()) {
      if (is_begin)
        it->second.dns_start = time;
      else if (is_end)
        it->second.dns_end = time;
    }
  }
}

void LoadTimingObserver::OnAddSocketEntry(
    net::NetLog::EventType type,
    const base::TimeTicks& time,
    const net::NetLog::Source& source,
    net::NetLog::EventPhase phase,
    net::NetLog::EventParameters* params) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  bool is_begin = phase == net::NetLog::PHASE_BEGIN;
  bool is_end = phase == net::NetLog::PHASE_END;

  // Manage record lifetime based on the SOCKET_ALIVE entry.
  if (type == net::NetLog::TYPE_SOCKET_ALIVE) {
    if (is_begin) {
      // Prevents us from passively growing the memory memory unbounded in case
      // something went wrong. Should not happen.
      if (socket_to_record_.size() > kMaxNumEntries) {
        LOG(WARNING) << "The load timing observer socket count has grown "
                        "larger than expected, resetting";
        socket_to_record_.clear();
      }

      socket_to_record_.insert(
          std::make_pair(source.id, SocketRecord()));
    } else if (is_end) {
      socket_to_record_.erase(source.id);
    }
    return;
  }
  SocketToRecordMap::iterator it = socket_to_record_.find(source.id);
  if (it == socket_to_record_.end())
    return;

  if (type == net::NetLog::TYPE_SSL_CONNECT) {
    if (is_begin)
      it->second.ssl_start = time;
    else if (is_end)
      it->second.ssl_end = time;
  }
}
<|endoftext|>