<commit_before>/*
 * Copyright (c) 2002 - present, H. Hernan Saez
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the copyright holder nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef CRIMILD_MATHEMATICS_ORTHO_
#define CRIMILD_MATHEMATICS_ORTHO_

#include "Foundation/Macros.hpp"
#include "Mathematics/Matrix4.hpp"

namespace crimild {

    [[nodiscard]] constexpr Matrix4 ortho( Real l, Real r, Real b, Real t, Real n, Real f ) noexcept
    {
#if CRIMILD_USE_DEPTH_RANGE_ZERO_TO_ONE
        return Matrix4 {
            { Real( 2 ) / ( r - l ), 0, 0, 0 },
            { 0, Real( 2 ) / ( t - b ), 0, 0 },
            { 0, 0, Real( 1 ) / ( f - n ), 0 },
            { -( r + l ) / ( r - l ), -( t + b ) / ( t - b ), -n / ( f - n ), 1 },
        };
#else
        return Matrix4 {
            { Real( 2 ) / ( r - l ), 0, 0, 0 },
            { 0, Real( 2 ) / ( t - b ), 0, 0 },
            { 0, 0, Real( 2 ) / ( f - n ), 0 },
            { -( r + l ) / ( r - l ), -( t + b ) / ( t - b ), -( f + n ) / ( f - n ), 1 },
        };
#endif
    }

}

#endif
<commit_msg>Fix orthographic projection<commit_after>/*
 * Copyright (c) 2002 - present, H. Hernan Saez
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the copyright holder nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef CRIMILD_MATHEMATICS_ORTHO_
#define CRIMILD_MATHEMATICS_ORTHO_

#include "Foundation/Macros.hpp"
#include "Mathematics/Matrix4.hpp"

namespace crimild {

    [[nodiscard]] constexpr Matrix4 ortho( Real l, Real r, Real b, Real t, Real n, Real f ) noexcept
    {
#if CRIMILD_USE_DEPTH_RANGE_ZERO_TO_ONE
        return Matrix4 {
            { Real( 2 ) / ( r - l ), 0, 0, 0 },
            { 0, Real( 2 ) / ( t - b ), 0, 0 },
            { 0, 0, -Real( 1 ) / ( f - n ), 0 },
            { -( r + l ) / ( r - l ), -( t + b ) / ( t - b ), -n / ( f - n ), 1 },
        };
#else
        return Matrix4 {
            { Real( 2 ) / ( r - l ), 0, 0, 0 },
            { 0, Real( 2 ) / ( t - b ), 0, 0 },
            { 0, 0, -Real( 2 ) / ( f - n ), 0 },
            { -( r + l ) / ( r - l ), -( t + b ) / ( t - b ), -( f + n ) / ( f - n ), 1 },
        };
#endif
    }

}

#endif
<|endoftext|>


<commit_before><commit_msg>Move IBL settings in their own category<commit_after><|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/
#include "modules/control/control_component.h"

#include "cyber/common/file.h"
#include "cyber/common/log.h"
#include "modules/common/adapters/adapter_gflags.h"
#include "modules/common/time/time.h"
#include "modules/common/vehicle_state/vehicle_state_provider.h"
#include "modules/control/common/control_gflags.h"

namespace apollo {
namespace control {

using apollo::canbus::Chassis;
using apollo::common::ErrorCode;
using apollo::common::Status;
using apollo::common::VehicleStateProvider;
using apollo::common::time::Clock;
using apollo::localization::LocalizationEstimate;
using apollo::planning::ADCTrajectory;

ControlComponent::ControlComponent()
    : monitor_logger_buffer_(common::monitor::MonitorMessageItem::CONTROL) {}

bool ControlComponent::Init() {
  // init_time_ = Clock::NowInSeconds();

  AINFO << "Control init, starting ...";

  CHECK(
      cyber::common::GetProtoFromFile(FLAGS_control_conf_file, &control_conf_))
      << "Unable to load control conf file: " + FLAGS_control_conf_file;

  AINFO << "Conf file: " << FLAGS_control_conf_file << " is loaded.";

  AINFO << "Conf file: " << ConfigFilePath() << " is loaded.";

  // set controller
  if (!controller_agent_.Init(&control_conf_).ok()) {
    monitor_logger_buffer_.ERROR("Control init controller failed! Stopping...");
    return false;
  }

  cyber::ReaderConfig chassis_reader_config;
  chassis_reader_config.channel_name = FLAGS_chassis_topic;
  chassis_reader_config.pending_queue_size = FLAGS_chassis_pending_queue_size;

  chassis_reader_ =
      node_->CreateReader<Chassis>(chassis_reader_config, nullptr);
  CHECK(chassis_reader_ != nullptr);

  cyber::ReaderConfig planning_reader_config;
  planning_reader_config.channel_name = FLAGS_planning_trajectory_topic;
  planning_reader_config.pending_queue_size = FLAGS_planning_pending_queue_size;

  trajectory_reader_ =
      node_->CreateReader<ADCTrajectory>(planning_reader_config, nullptr);
  CHECK(trajectory_reader_ != nullptr);

  cyber::ReaderConfig localization_reader_config;
  localization_reader_config.channel_name = FLAGS_localization_topic;
  localization_reader_config.pending_queue_size =
      FLAGS_localization_pending_queue_size;

  localization_reader_ = node_->CreateReader<LocalizationEstimate>(
      localization_reader_config, nullptr);
  CHECK(localization_reader_ != nullptr);

  cyber::ReaderConfig pad_msg_reader_config;
  pad_msg_reader_config.channel_name = FLAGS_pad_topic;
  pad_msg_reader_config.pending_queue_size = FLAGS_pad_msg_pending_queue_size;

  pad_msg_reader_ =
      node_->CreateReader<PadMessage>(pad_msg_reader_config, nullptr);
  CHECK(pad_msg_reader_ != nullptr);

  control_cmd_writer_ =
      node_->CreateWriter<ControlCommand>(FLAGS_control_command_topic);
  CHECK(control_cmd_writer_ != nullptr);

  // set initial vehicle state by cmd
  // need to sleep, because advertised channel is not ready immediately
  // simple test shows a short delay of 80 ms or so
  AINFO << "Control resetting vehicle state, sleeping for 1000 ms ...";
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));

  // should init_vehicle first, let car enter work status, then use status msg
  // trigger control

  AINFO << "Control default driving action is "
        << DrivingAction_Name(control_conf_.action());
  pad_msg_.set_action(control_conf_.action());

  return true;
}

void ControlComponent::OnPad(const std::shared_ptr<PadMessage> &pad) {
  pad_msg_.CopyFrom(*pad);
  ADEBUG << "Received Pad Msg:" << pad_msg_.DebugString();
  AERROR_IF(!pad_msg_.has_action()) << "pad message check failed!";

  // do something according to pad message
  if (pad_msg_.action() == DrivingAction::RESET) {
    AINFO << "Control received RESET action!";
    estop_ = false;
    estop_reason_.clear();
  }
  pad_received_ = true;
}

void ControlComponent::OnChassis(const std::shared_ptr<Chassis> &chassis) {
  ADEBUG << "Received chassis data: run chassis callback.";
  std::lock_guard<std::mutex> lock(mutex_);
  latest_chassis_.CopyFrom(*chassis);
}

void ControlComponent::OnPlanning(
    const std::shared_ptr<ADCTrajectory> &trajectory) {
  ADEBUG << "Received chassis data: run trajectory callback.";
  std::lock_guard<std::mutex> lock(mutex_);
  latest_trajectory_.CopyFrom(*trajectory);
}

void ControlComponent::OnLocalization(
    const std::shared_ptr<LocalizationEstimate> &localization) {
  ADEBUG << "Received control data: run localization message callback.";
  std::lock_guard<std::mutex> lock(mutex_);
  latest_localization_.CopyFrom(*localization);
}

void ControlComponent::OnMonitor(
    const common::monitor::MonitorMessage &monitor_message) {
  for (const auto &item : monitor_message.item()) {
    if (item.log_level() == common::monitor::MonitorMessageItem::FATAL) {
      estop_ = true;
      return;
    }
  }
}

Status ControlComponent::ProduceControlCommand(
    ControlCommand *control_command) {
  {
    std::lock_guard<std::mutex> lock(mutex_);
    local_view_.chassis = latest_chassis_;
    local_view_.trajectory = latest_trajectory_;
    local_view_.localization = latest_localization_;
  }

  Status status = CheckInput(&local_view_);
  // check data

  if (!status.ok()) {
    AERROR_EVERY(100) << "Control input data failed: "
                      << status.error_message();
    control_command->mutable_engage_advice()->set_advice(
        apollo::common::EngageAdvice::DISALLOW_ENGAGE);
    control_command->mutable_engage_advice()->set_reason(
        status.error_message());
    estop_ = true;
    estop_reason_ = status.error_message();
  } else {
    Status status_ts = CheckTimestamp(local_view_);
    if (!status_ts.ok()) {
      AERROR << "Input messages timeout";
      // estop_ = true;
      status = status_ts;
      if (local_view_.chassis.driving_mode() !=
          apollo::canbus::Chassis::COMPLETE_AUTO_DRIVE) {
        control_command->mutable_engage_advice()->set_advice(
            apollo::common::EngageAdvice::DISALLOW_ENGAGE);
        control_command->mutable_engage_advice()->set_reason(
            status.error_message());
      }
    } else {
      control_command->mutable_engage_advice()->set_advice(
          apollo::common::EngageAdvice::READY_TO_ENGAGE);
    }
  }

  // check estop
  estop_ = control_conf_.enable_persistent_estop()
               ? estop_ || local_view_.trajectory.estop().is_estop()
               : local_view_.trajectory.estop().is_estop();

  if (local_view_.trajectory.estop().is_estop()) {
    estop_reason_ = "estop from planning";
  }

  if (local_view_.trajectory.trajectory_point_size() == 0) {
    AWARN_EVERY(100) << "planning has no trajectory point. ";
    estop_ = true;
    estop_reason_ = "estop for empty planning trajectory";
  }

  // if planning set estop, then no control process triggered
  if (!estop_) {
    if (local_view_.chassis.driving_mode() == Chassis::COMPLETE_MANUAL) {
      controller_agent_.Reset();
      AINFO_EVERY(100) << "Reset Controllers in Manual Mode";
    }

    auto debug = control_command->mutable_debug()->mutable_input_debug();
    debug->mutable_localization_header()->CopyFrom(
        local_view_.localization.header());
    debug->mutable_canbus_header()->CopyFrom(local_view_.chassis.header());
    debug->mutable_trajectory_header()->CopyFrom(
        local_view_.trajectory.header());

    Status status_compute = controller_agent_.ComputeControlCommand(
        &local_view_.localization, &local_view_.chassis,
        &local_view_.trajectory, control_command);

    if (!status_compute.ok()) {
      AERROR << "Control main function failed"
             << " with localization: "
             << local_view_.localization.ShortDebugString()
             << " with chassis: " << local_view_.chassis.ShortDebugString()
             << " with trajectory: "
             << local_view_.trajectory.ShortDebugString()
             << " with cmd: " << control_command->ShortDebugString()
             << " status:" << status_compute.error_message();
      estop_ = true;
      estop_reason_ = status_compute.error_message();
      status = status_compute;
    }
  }

  if (estop_) {
    AWARN_EVERY(100) << "Estop triggered! No control core method executed!";
    // set Estop command
    control_command->set_speed(0);
    control_command->set_throttle(0);
    control_command->set_brake(control_conf_.soft_estop_brake());
    control_command->set_gear_location(Chassis::GEAR_DRIVE);
  }
  // check signal
  if (local_view_.trajectory.decision().has_vehicle_signal()) {
    control_command->mutable_signal()->CopyFrom(
        local_view_.trajectory.decision().vehicle_signal());
  }
  return status;
}

bool ControlComponent::Proc() {
  double start_timestamp = Clock::NowInSeconds();

  chassis_reader_->Observe();
  const auto &chassis_msg = chassis_reader_->GetLatestObserved();
  if (chassis_msg == nullptr) {
    AERROR << "Chassis msg is not ready!";
    return false;
  }

  OnChassis(chassis_msg);

  trajectory_reader_->Observe();
  const auto &trajectory_msg = trajectory_reader_->GetLatestObserved();
  if (trajectory_msg == nullptr) {
    AERROR << "planning msg is not ready!";
    return false;
  }
  OnPlanning(trajectory_msg);

  localization_reader_->Observe();
  const auto &localization_msg = localization_reader_->GetLatestObserved();
  if (localization_msg == nullptr) {
    AERROR << "localization msg is not ready!";
    return false;
  }
  OnLocalization(localization_msg);

  pad_msg_reader_->Observe();
  const auto &pad_msg = pad_msg_reader_->GetLatestObserved();
  if (pad_msg != nullptr) {
    OnPad(pad_msg);
  }

  if (control_conf_.is_control_test_mode() &&
      control_conf_.control_test_duration() > 0 &&
      (start_timestamp - init_time_) > control_conf_.control_test_duration()) {
    AERROR << "Control finished testing. exit";
    return false;
  }

  ControlCommand control_command;

  Status status = ProduceControlCommand(&control_command);
  AERROR_IF(!status.ok()) << "Failed to produce control command:"
                          << status.error_message();

  double end_timestamp = Clock::NowInSeconds();

  if (pad_received_) {
    control_command.mutable_pad_msg()->CopyFrom(pad_msg_);
    pad_received_ = false;
  }

  const double time_diff_ms = (end_timestamp - start_timestamp) * 1000;
  control_command.mutable_latency_stats()->set_total_time_ms(time_diff_ms);
  control_command.mutable_latency_stats()->set_total_time_exceeded(
      time_diff_ms < control_conf_.control_period());
  ADEBUG << "control cycle time is: " << time_diff_ms << " ms.";
  status.Save(control_command.mutable_header()->mutable_status());

  // forward estop reason among following control frames.
  if (estop_) {
    control_command.mutable_header()->mutable_status()->set_msg(estop_reason_);
  }

  // set header
  control_command.mutable_header()->set_lidar_timestamp(
      local_view_.trajectory.header().lidar_timestamp());
  control_command.mutable_header()->set_camera_timestamp(
      local_view_.trajectory.header().camera_timestamp());
  control_command.mutable_header()->set_radar_timestamp(
      local_view_.trajectory.header().radar_timestamp());

  common::util::FillHeader(node_->Name(), &control_command);

  ADEBUG << control_command.ShortDebugString();
  if (control_conf_.is_control_test_mode()) {
    ADEBUG << "Skip publish control command in test mode";
    return true;
  }

  control_cmd_writer_->Write(std::make_shared<ControlCommand>(control_command));

  return true;
}

Status ControlComponent::CheckInput(LocalView *local_view) {
  ADEBUG << "Received localization:"
         << local_view->localization.ShortDebugString();
  ADEBUG << "Received chassis:" << local_view->chassis.ShortDebugString();

  if (!local_view->trajectory.estop().is_estop() &&
      local_view->trajectory.trajectory_point_size() == 0) {
    AWARN_EVERY(100) << "planning has no trajectory point. ";
    std::string msg("planning has no trajectory point. planning_seq_num:");
    msg += std::to_string(local_view->trajectory.header().sequence_num());
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR, msg);
  }

  for (auto &trajectory_point :
       *local_view->trajectory.mutable_trajectory_point()) {
    if (std::abs(trajectory_point.v()) <
        control_conf_.minimum_speed_resolution()) {
      trajectory_point.set_v(0.0);
      trajectory_point.set_a(0.0);
    }
  }

  VehicleStateProvider::Instance()->Update(local_view->localization,
                                           local_view->chassis);

  return Status::OK();
}

Status ControlComponent::CheckTimestamp(const LocalView &local_view) {
  if (!control_conf_.enable_input_timestamp_check() ||
      control_conf_.is_control_test_mode()) {
    ADEBUG << "Skip input timestamp check by gflags.";
    return Status::OK();
  }
  double current_timestamp = Clock::NowInSeconds();
  double localization_diff =
      current_timestamp - local_view.localization.header().timestamp_sec();
  if (localization_diff > (control_conf_.max_localization_miss_num() *
                           control_conf_.localization_period())) {
    AERROR << "Localization msg lost for " << std::setprecision(6)
           << localization_diff << "s";
    monitor_logger_buffer_.ERROR("Localization msg lost");
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR, "Localization msg timeout");
  }

  double chassis_diff =
      current_timestamp - local_view.chassis.header().timestamp_sec();
  if (chassis_diff >
      (control_conf_.max_chassis_miss_num() * control_conf_.chassis_period())) {
    AERROR << "Chassis msg lost for " << std::setprecision(6) << chassis_diff
           << "s";
    monitor_logger_buffer_.ERROR("Chassis msg lost");
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR, "Chassis msg timeout");
  }

  double trajectory_diff =
      current_timestamp - local_view.trajectory.header().timestamp_sec();
  if (trajectory_diff > (control_conf_.max_planning_miss_num() *
                         control_conf_.trajectory_period())) {
    AERROR << "Trajectory msg lost for " << std::setprecision(6)
           << trajectory_diff << "s";
    monitor_logger_buffer_.ERROR("Trajectory msg lost");
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR, "Trajectory msg timeout");
  }
  return Status::OK();
}

}  // namespace control
}  // namespace apollo
<commit_msg>Control: fix time_exceeded judgement error<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/
#include "modules/control/control_component.h"

#include "cyber/common/file.h"
#include "cyber/common/log.h"
#include "modules/common/adapters/adapter_gflags.h"
#include "modules/common/time/time.h"
#include "modules/common/vehicle_state/vehicle_state_provider.h"
#include "modules/control/common/control_gflags.h"

namespace apollo {
namespace control {

using apollo::canbus::Chassis;
using apollo::common::ErrorCode;
using apollo::common::Status;
using apollo::common::VehicleStateProvider;
using apollo::common::time::Clock;
using apollo::localization::LocalizationEstimate;
using apollo::planning::ADCTrajectory;

ControlComponent::ControlComponent()
    : monitor_logger_buffer_(common::monitor::MonitorMessageItem::CONTROL) {}

bool ControlComponent::Init() {
  // init_time_ = Clock::NowInSeconds();

  AINFO << "Control init, starting ...";

  CHECK(
      cyber::common::GetProtoFromFile(FLAGS_control_conf_file, &control_conf_))
      << "Unable to load control conf file: " + FLAGS_control_conf_file;

  AINFO << "Conf file: " << FLAGS_control_conf_file << " is loaded.";

  AINFO << "Conf file: " << ConfigFilePath() << " is loaded.";

  // set controller
  if (!controller_agent_.Init(&control_conf_).ok()) {
    monitor_logger_buffer_.ERROR("Control init controller failed! Stopping...");
    return false;
  }

  cyber::ReaderConfig chassis_reader_config;
  chassis_reader_config.channel_name = FLAGS_chassis_topic;
  chassis_reader_config.pending_queue_size = FLAGS_chassis_pending_queue_size;

  chassis_reader_ =
      node_->CreateReader<Chassis>(chassis_reader_config, nullptr);
  CHECK(chassis_reader_ != nullptr);

  cyber::ReaderConfig planning_reader_config;
  planning_reader_config.channel_name = FLAGS_planning_trajectory_topic;
  planning_reader_config.pending_queue_size = FLAGS_planning_pending_queue_size;

  trajectory_reader_ =
      node_->CreateReader<ADCTrajectory>(planning_reader_config, nullptr);
  CHECK(trajectory_reader_ != nullptr);

  cyber::ReaderConfig localization_reader_config;
  localization_reader_config.channel_name = FLAGS_localization_topic;
  localization_reader_config.pending_queue_size =
      FLAGS_localization_pending_queue_size;

  localization_reader_ = node_->CreateReader<LocalizationEstimate>(
      localization_reader_config, nullptr);
  CHECK(localization_reader_ != nullptr);

  cyber::ReaderConfig pad_msg_reader_config;
  pad_msg_reader_config.channel_name = FLAGS_pad_topic;
  pad_msg_reader_config.pending_queue_size = FLAGS_pad_msg_pending_queue_size;

  pad_msg_reader_ =
      node_->CreateReader<PadMessage>(pad_msg_reader_config, nullptr);
  CHECK(pad_msg_reader_ != nullptr);

  control_cmd_writer_ =
      node_->CreateWriter<ControlCommand>(FLAGS_control_command_topic);
  CHECK(control_cmd_writer_ != nullptr);

  // set initial vehicle state by cmd
  // need to sleep, because advertised channel is not ready immediately
  // simple test shows a short delay of 80 ms or so
  AINFO << "Control resetting vehicle state, sleeping for 1000 ms ...";
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));

  // should init_vehicle first, let car enter work status, then use status msg
  // trigger control

  AINFO << "Control default driving action is "
        << DrivingAction_Name(control_conf_.action());
  pad_msg_.set_action(control_conf_.action());

  return true;
}

void ControlComponent::OnPad(const std::shared_ptr<PadMessage> &pad) {
  pad_msg_.CopyFrom(*pad);
  ADEBUG << "Received Pad Msg:" << pad_msg_.DebugString();
  AERROR_IF(!pad_msg_.has_action()) << "pad message check failed!";

  // do something according to pad message
  if (pad_msg_.action() == DrivingAction::RESET) {
    AINFO << "Control received RESET action!";
    estop_ = false;
    estop_reason_.clear();
  }
  pad_received_ = true;
}

void ControlComponent::OnChassis(const std::shared_ptr<Chassis> &chassis) {
  ADEBUG << "Received chassis data: run chassis callback.";
  std::lock_guard<std::mutex> lock(mutex_);
  latest_chassis_.CopyFrom(*chassis);
}

void ControlComponent::OnPlanning(
    const std::shared_ptr<ADCTrajectory> &trajectory) {
  ADEBUG << "Received chassis data: run trajectory callback.";
  std::lock_guard<std::mutex> lock(mutex_);
  latest_trajectory_.CopyFrom(*trajectory);
}

void ControlComponent::OnLocalization(
    const std::shared_ptr<LocalizationEstimate> &localization) {
  ADEBUG << "Received control data: run localization message callback.";
  std::lock_guard<std::mutex> lock(mutex_);
  latest_localization_.CopyFrom(*localization);
}

void ControlComponent::OnMonitor(
    const common::monitor::MonitorMessage &monitor_message) {
  for (const auto &item : monitor_message.item()) {
    if (item.log_level() == common::monitor::MonitorMessageItem::FATAL) {
      estop_ = true;
      return;
    }
  }
}

Status ControlComponent::ProduceControlCommand(
    ControlCommand *control_command) {
  {
    std::lock_guard<std::mutex> lock(mutex_);
    local_view_.chassis = latest_chassis_;
    local_view_.trajectory = latest_trajectory_;
    local_view_.localization = latest_localization_;
  }

  Status status = CheckInput(&local_view_);
  // check data

  if (!status.ok()) {
    AERROR_EVERY(100) << "Control input data failed: "
                      << status.error_message();
    control_command->mutable_engage_advice()->set_advice(
        apollo::common::EngageAdvice::DISALLOW_ENGAGE);
    control_command->mutable_engage_advice()->set_reason(
        status.error_message());
    estop_ = true;
    estop_reason_ = status.error_message();
  } else {
    Status status_ts = CheckTimestamp(local_view_);
    if (!status_ts.ok()) {
      AERROR << "Input messages timeout";
      // estop_ = true;
      status = status_ts;
      if (local_view_.chassis.driving_mode() !=
          apollo::canbus::Chassis::COMPLETE_AUTO_DRIVE) {
        control_command->mutable_engage_advice()->set_advice(
            apollo::common::EngageAdvice::DISALLOW_ENGAGE);
        control_command->mutable_engage_advice()->set_reason(
            status.error_message());
      }
    } else {
      control_command->mutable_engage_advice()->set_advice(
          apollo::common::EngageAdvice::READY_TO_ENGAGE);
    }
  }

  // check estop
  estop_ = control_conf_.enable_persistent_estop()
               ? estop_ || local_view_.trajectory.estop().is_estop()
               : local_view_.trajectory.estop().is_estop();

  if (local_view_.trajectory.estop().is_estop()) {
    estop_reason_ = "estop from planning";
  }

  if (local_view_.trajectory.trajectory_point_size() == 0) {
    AWARN_EVERY(100) << "planning has no trajectory point. ";
    estop_ = true;
    estop_reason_ = "estop for empty planning trajectory";
  }

  // if planning set estop, then no control process triggered
  if (!estop_) {
    if (local_view_.chassis.driving_mode() == Chassis::COMPLETE_MANUAL) {
      controller_agent_.Reset();
      AINFO_EVERY(100) << "Reset Controllers in Manual Mode";
    }

    auto debug = control_command->mutable_debug()->mutable_input_debug();
    debug->mutable_localization_header()->CopyFrom(
        local_view_.localization.header());
    debug->mutable_canbus_header()->CopyFrom(local_view_.chassis.header());
    debug->mutable_trajectory_header()->CopyFrom(
        local_view_.trajectory.header());

    Status status_compute = controller_agent_.ComputeControlCommand(
        &local_view_.localization, &local_view_.chassis,
        &local_view_.trajectory, control_command);

    if (!status_compute.ok()) {
      AERROR << "Control main function failed"
             << " with localization: "
             << local_view_.localization.ShortDebugString()
             << " with chassis: " << local_view_.chassis.ShortDebugString()
             << " with trajectory: "
             << local_view_.trajectory.ShortDebugString()
             << " with cmd: " << control_command->ShortDebugString()
             << " status:" << status_compute.error_message();
      estop_ = true;
      estop_reason_ = status_compute.error_message();
      status = status_compute;
    }
  }

  if (estop_) {
    AWARN_EVERY(100) << "Estop triggered! No control core method executed!";
    // set Estop command
    control_command->set_speed(0);
    control_command->set_throttle(0);
    control_command->set_brake(control_conf_.soft_estop_brake());
    control_command->set_gear_location(Chassis::GEAR_DRIVE);
  }
  // check signal
  if (local_view_.trajectory.decision().has_vehicle_signal()) {
    control_command->mutable_signal()->CopyFrom(
        local_view_.trajectory.decision().vehicle_signal());
  }
  return status;
}

bool ControlComponent::Proc() {
  double start_timestamp = Clock::NowInSeconds();

  chassis_reader_->Observe();
  const auto &chassis_msg = chassis_reader_->GetLatestObserved();
  if (chassis_msg == nullptr) {
    AERROR << "Chassis msg is not ready!";
    return false;
  }

  OnChassis(chassis_msg);

  trajectory_reader_->Observe();
  const auto &trajectory_msg = trajectory_reader_->GetLatestObserved();
  if (trajectory_msg == nullptr) {
    AERROR << "planning msg is not ready!";
    return false;
  }
  OnPlanning(trajectory_msg);

  localization_reader_->Observe();
  const auto &localization_msg = localization_reader_->GetLatestObserved();
  if (localization_msg == nullptr) {
    AERROR << "localization msg is not ready!";
    return false;
  }
  OnLocalization(localization_msg);

  pad_msg_reader_->Observe();
  const auto &pad_msg = pad_msg_reader_->GetLatestObserved();
  if (pad_msg != nullptr) {
    OnPad(pad_msg);
  }

  if (control_conf_.is_control_test_mode() &&
      control_conf_.control_test_duration() > 0 &&
      (start_timestamp - init_time_) > control_conf_.control_test_duration()) {
    AERROR << "Control finished testing. exit";
    return false;
  }

  ControlCommand control_command;

  Status status = ProduceControlCommand(&control_command);
  AERROR_IF(!status.ok()) << "Failed to produce control command:"
                          << status.error_message();

  double end_timestamp = Clock::NowInSeconds();

  if (pad_received_) {
    control_command.mutable_pad_msg()->CopyFrom(pad_msg_);
    pad_received_ = false;
  }

  const double time_diff_ms = (end_timestamp - start_timestamp) * 1000;
  control_command.mutable_latency_stats()->set_total_time_ms(time_diff_ms);
  control_command.mutable_latency_stats()->set_total_time_exceeded(
      time_diff_ms > control_conf_.control_period());
  ADEBUG << "control cycle time is: " << time_diff_ms << " ms.";
  status.Save(control_command.mutable_header()->mutable_status());

  // forward estop reason among following control frames.
  if (estop_) {
    control_command.mutable_header()->mutable_status()->set_msg(estop_reason_);
  }

  // set header
  control_command.mutable_header()->set_lidar_timestamp(
      local_view_.trajectory.header().lidar_timestamp());
  control_command.mutable_header()->set_camera_timestamp(
      local_view_.trajectory.header().camera_timestamp());
  control_command.mutable_header()->set_radar_timestamp(
      local_view_.trajectory.header().radar_timestamp());

  common::util::FillHeader(node_->Name(), &control_command);

  ADEBUG << control_command.ShortDebugString();
  if (control_conf_.is_control_test_mode()) {
    ADEBUG << "Skip publish control command in test mode";
    return true;
  }

  control_cmd_writer_->Write(std::make_shared<ControlCommand>(control_command));

  return true;
}

Status ControlComponent::CheckInput(LocalView *local_view) {
  ADEBUG << "Received localization:"
         << local_view->localization.ShortDebugString();
  ADEBUG << "Received chassis:" << local_view->chassis.ShortDebugString();

  if (!local_view->trajectory.estop().is_estop() &&
      local_view->trajectory.trajectory_point_size() == 0) {
    AWARN_EVERY(100) << "planning has no trajectory point. ";
    std::string msg("planning has no trajectory point. planning_seq_num:");
    msg += std::to_string(local_view->trajectory.header().sequence_num());
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR, msg);
  }

  for (auto &trajectory_point :
       *local_view->trajectory.mutable_trajectory_point()) {
    if (std::abs(trajectory_point.v()) <
        control_conf_.minimum_speed_resolution()) {
      trajectory_point.set_v(0.0);
      trajectory_point.set_a(0.0);
    }
  }

  VehicleStateProvider::Instance()->Update(local_view->localization,
                                           local_view->chassis);

  return Status::OK();
}

Status ControlComponent::CheckTimestamp(const LocalView &local_view) {
  if (!control_conf_.enable_input_timestamp_check() ||
      control_conf_.is_control_test_mode()) {
    ADEBUG << "Skip input timestamp check by gflags.";
    return Status::OK();
  }
  double current_timestamp = Clock::NowInSeconds();
  double localization_diff =
      current_timestamp - local_view.localization.header().timestamp_sec();
  if (localization_diff > (control_conf_.max_localization_miss_num() *
                           control_conf_.localization_period())) {
    AERROR << "Localization msg lost for " << std::setprecision(6)
           << localization_diff << "s";
    monitor_logger_buffer_.ERROR("Localization msg lost");
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR, "Localization msg timeout");
  }

  double chassis_diff =
      current_timestamp - local_view.chassis.header().timestamp_sec();
  if (chassis_diff >
      (control_conf_.max_chassis_miss_num() * control_conf_.chassis_period())) {
    AERROR << "Chassis msg lost for " << std::setprecision(6) << chassis_diff
           << "s";
    monitor_logger_buffer_.ERROR("Chassis msg lost");
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR, "Chassis msg timeout");
  }

  double trajectory_diff =
      current_timestamp - local_view.trajectory.header().timestamp_sec();
  if (trajectory_diff > (control_conf_.max_planning_miss_num() *
                         control_conf_.trajectory_period())) {
    AERROR << "Trajectory msg lost for " << std::setprecision(6)
           << trajectory_diff << "s";
    monitor_logger_buffer_.ERROR("Trajectory msg lost");
    return Status(ErrorCode::CONTROL_COMPUTE_ERROR, "Trajectory msg timeout");
  }
  return Status::OK();
}

}  // namespace control
}  // namespace apollo
<|endoftext|>


<commit_before><commit_msg>Added onObjLoad function<commit_after><|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/routing/routing_component.h"

#include "modules/common/adapters/adapter_gflags.h"
#include "modules/routing/common/routing_gflags.h"

DECLARE_string(flagfile);

namespace apollo {
namespace routing {

bool RoutingComponent::Init() {
  AINFO << "Loading gflag from file: " << ConfigFilePath();
  google::SetCommandLineOption("flagfile", ConfigFilePath().c_str());

  response_writer_ =
      node_->CreateWriter<RoutingResponse>(FLAGS_routing_response_topic);

  return routing_.Init().ok() && routing_.Start().ok();
}

bool RoutingComponent::Proc(const std::shared_ptr<RoutingRequest>& request) {
  auto response = std::make_shared<RoutingResponse>();
  if (!routing_.Process(request, response.get())) {
    return false;
  }
  response_writer_->Write(response);
  return true;
}

}  // namespace routing
}  // namespace apollo

<commit_msg>routing: add pb header into routing response.<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/routing/routing_component.h"

#include "modules/common/adapters/adapter_gflags.h"
#include "modules/routing/common/routing_gflags.h"

DECLARE_string(flagfile);

namespace apollo {
namespace routing {

bool RoutingComponent::Init() {
  AINFO << "Loading gflag from file: " << ConfigFilePath();
  google::SetCommandLineOption("flagfile", ConfigFilePath().c_str());

  response_writer_ =
      node_->CreateWriter<RoutingResponse>(FLAGS_routing_response_topic);

  return routing_.Init().ok() && routing_.Start().ok();
}

bool RoutingComponent::Proc(const std::shared_ptr<RoutingRequest>& request) {
  auto response = std::make_shared<RoutingResponse>();
  if (!routing_.Process(request, response.get())) {
    return false;
  }
  common::util::FillHeader(node_->Name(), response.get());

  response_writer_->Write(response);
  return true;
}

}  // namespace routing
}  // namespace apollo

<|endoftext|>


<commit_before>#include "glesplash.h"
#include "shaders.h"

#include <EGL/egl.h>

const float vertexArray[] = {
   -1.0,  1.0,  0.0,
   -1.0, -1.0,  0.0,
    1.0, -1.0,  0.0,
    1.0,  1.0,  0.0,
   -1.0,  1.0,  0.0
};

const float textureArray[] = {
    0.0,  1.0,
    0.0,  0.0,
    1.0,  0.0,
    1.0,  1.0,
    0.0,  1.0
};

EGLDisplay  egl_display;
EGLContext  egl_context;
EGLSurface  egl_surface;

GLint
    position_loc,
    texCoord_loc,
    texSampl_loc;

void render()
{
    static int init = 0;

    if(!init) {
#ifdef X11
        XWindowAttributes gwa;
        XGetWindowAttributes(x_display, win, &gwa);
        glViewport(0, 0, gwa.width, gwa.height);
#else
        glViewport(0, 0, 854, 480);
#endif
        glClearColor(0.0, 0.0, 0.0, 1.0);
        init = 1;
    }

    glClear(GL_COLOR_BUFFER_BIT);

    glVertexAttribPointer(position_loc, 3, GL_FLOAT, false, 0, vertexArray);
    glVertexAttribPointer(texCoord_loc, 2, GL_FLOAT, false, 0, textureArray);
    glEnableVertexAttribArray(position_loc);
    glEnableVertexAttribArray(texCoord_loc);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 5);
    eglSwapBuffers(egl_display, egl_surface);
}

int create_egl_context()
{
    EGLConfig egl_config;
    EGLint num_config;
    EGLint attr[] = {
        EGL_BUFFER_SIZE, 16,
        EGL_RENDERABLE_TYPE,
        EGL_OPENGL_ES2_BIT,
        EGL_NONE
    };
    EGLint ctx_attr[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };

#ifdef X11
    egl_display = eglGetDisplay((EGLNativeDisplayType)x_display);
#else
    egl_display = eglGetDisplay(NULL);
#endif
    if(egl_display == EGL_NO_DISPLAY)
    {
        cerr << "Could not get EGL display" << endl;
        return EXIT_FAILURE;
    }

    if(!eglInitialize(egl_display, NULL, NULL))
    {
        cerr << "Unable to initialize EGL" << endl;
        return EXIT_FAILURE;
    }

    if(!eglChooseConfig(egl_display, attr, &egl_config, 1, &num_config))
    {
        cerr << "Failed to configure EGL context" << endl;
        return EXIT_FAILURE;
    }

    if(num_config != 1)
    {
        cerr << "Multiple configurations returned, got " << num_config << " configurations" << endl;
        return EXIT_FAILURE;
    }

#ifdef X11
    egl_surface = eglCreateWindowSurface(egl_display, egl_config, (EGLNativeWindowType)win, NULL);
#else
    egl_surface = eglCreateWindowSurface(egl_display, egl_config, (EGLNativeWindowType)NULL, NULL);
#endif
    if(egl_surface == EGL_NO_SURFACE)
    {
        cerr << "Unable to create EGL surface: " << eglGetError() << endl;
        return EXIT_FAILURE;
    }

    egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, ctx_attr);
    if(egl_context == EGL_NO_CONTEXT)
    {
        cerr << "Unable to create EGL context: " << eglGetError() << endl;
        return EXIT_FAILURE;
    }

    eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
    return EXIT_SUCCESS;
}

int init_gl_context()
{
    ///////  the openGL part  ///////////////////////////////////////////////////////////////
    GLuint shaderProgram  = glCreateProgram();
    GLuint vertexShader   = load_shader(vertex_src, GL_VERTEX_SHADER);
    GLuint fragmentShader = load_shader(fragment_src, GL_FRAGMENT_SHADER);

    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);

    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);

    //// now get the locations (kind of handle) of the shaders variables
    position_loc  = glGetAttribLocation(shaderProgram, "aPosition");
    texCoord_loc  = glGetAttribLocation(shaderProgram, "aTexCoord");
    texSampl_loc  = glGetUniformLocation(shaderProgram, "tex");

    if(position_loc < 0) {
        cerr << "Unable to get position attribute" << endl;
        return EXIT_FAILURE;
    }

    if(texCoord_loc < 0) {
        cerr << "Unable to get texCoord attribute" << endl;
        return EXIT_FAILURE;
    }

    if(texSampl_loc < 0) {
        cerr << "Unable to get texSampl uniform" << endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
<commit_msg>Viewport offset fix when running in framebuffer mode.<commit_after>#include "glesplash.h"
#include "shaders.h"

#include <EGL/egl.h>

const float vertexArray[] = {
   -1.0,  1.0,  0.0,
   -1.0, -1.0,  0.0,
    1.0, -1.0,  0.0,
    1.0,  1.0,  0.0,
   -1.0,  1.0,  0.0
};

const float textureArray[] = {
    0.0,  1.0,
    0.0,  0.0,
    1.0,  0.0,
    1.0,  1.0,
    0.0,  1.0
};

EGLDisplay  egl_display;
EGLContext  egl_context;
EGLSurface  egl_surface;

GLint
    position_loc,
    texCoord_loc,
    texSampl_loc;

void render()
{
    static int init = 0;

    if(!init) {
#ifdef X11
        XWindowAttributes gwa;
        XGetWindowAttributes(x_display, win, &gwa);
        glViewport(0, 0, gwa.width, gwa.height);
#else
        glViewport(0, 288, 854, 480);
#endif
        glClearColor(1.0, 0.0, 1.0, 1.0);
        init = 1;
    }

    glClear(GL_COLOR_BUFFER_BIT);

    glVertexAttribPointer(position_loc, 3, GL_FLOAT, false, 0, vertexArray);
    glVertexAttribPointer(texCoord_loc, 2, GL_FLOAT, false, 0, textureArray);
    glEnableVertexAttribArray(position_loc);
    glEnableVertexAttribArray(texCoord_loc);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 5);
    eglSwapBuffers(egl_display, egl_surface);
}

int create_egl_context()
{
    EGLConfig egl_config;
    EGLint num_config;
    EGLint attr[] = {
        EGL_BUFFER_SIZE, 16,
        EGL_RENDERABLE_TYPE,
        EGL_OPENGL_ES2_BIT,
        EGL_NONE
    };
    EGLint ctx_attr[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };

#ifdef X11
    egl_display = eglGetDisplay((EGLNativeDisplayType)x_display);
#else
    egl_display = eglGetDisplay(NULL);
#endif
    if(egl_display == EGL_NO_DISPLAY)
    {
        cerr << "Could not get EGL display" << endl;
        return EXIT_FAILURE;
    }

    if(!eglInitialize(egl_display, NULL, NULL))
    {
        cerr << "Unable to initialize EGL" << endl;
        return EXIT_FAILURE;
    }

    if(!eglChooseConfig(egl_display, attr, &egl_config, 1, &num_config))
    {
        cerr << "Failed to configure EGL context" << endl;
        return EXIT_FAILURE;
    }

    if(num_config < 1)
    {
        cerr << "No EGL configurations found" << endl;
        return EXIT_FAILURE;
    }

#ifdef X11
    egl_surface = eglCreateWindowSurface(egl_display, egl_config, (EGLNativeWindowType)win, NULL);
#else
    egl_surface = eglCreateWindowSurface(egl_display, egl_config, (EGLNativeWindowType)NULL, NULL);
#endif
    if(egl_surface == EGL_NO_SURFACE)
    {
        cerr << "Unable to create EGL surface: " << eglGetError() << endl;
        return EXIT_FAILURE;
    }

    egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, ctx_attr);
    if(egl_context == EGL_NO_CONTEXT)
    {
        cerr << "Unable to create EGL context: " << eglGetError() << endl;
        return EXIT_FAILURE;
    }

    eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
    return EXIT_SUCCESS;
}

int init_gl_context()
{
    ///////  the openGL part  ///////////////////////////////////////////////////////////////
    GLuint shaderProgram  = glCreateProgram();
    GLuint vertexShader   = load_shader(vertex_src, GL_VERTEX_SHADER);
    GLuint fragmentShader = load_shader(fragment_src, GL_FRAGMENT_SHADER);

    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);

    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);

    //// now get the locations (kind of handle) of the shaders variables
    position_loc  = glGetAttribLocation(shaderProgram, "aPosition");
    texCoord_loc  = glGetAttribLocation(shaderProgram, "aTexCoord");
    texSampl_loc  = glGetUniformLocation(shaderProgram, "tex");

    if(position_loc < 0) {
        cerr << "Unable to get position attribute" << endl;
        return EXIT_FAILURE;
    }

    if(texCoord_loc < 0) {
        cerr << "Unable to get texCoord attribute" << endl;
        return EXIT_FAILURE;
    }

    if(texSampl_loc < 0) {
        cerr << "Unable to get texSampl uniform" << endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "rdb_protocol/terms/terms.hpp"

#include "rdb_protocol/error.hpp"
#include "rdb_protocol/op.hpp"

namespace ql {

class pend_term_t : public op_term_t {
public:
    pend_term_t(env_t *env, protob_t<const Term> term) : op_term_t(env, term, argspec_t(2)) { }
protected:
    enum which_pend_t {PRE, AP};
    counted_t<val_t> pend(which_pend_t which_pend) {
        counted_t<const datum_t> arr = arg(0)->as_datum();
        counted_t<const datum_t> new_el = arg(1)->as_datum();
        arr->check_type(datum_t::R_ARRAY);
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        if (which_pend == PRE) {
            // TODO: this is horrendously inefficient.
            out->add(new_el);
            for (size_t i = 0; i < arr->size(); ++i) out->add(arr->get(i));
        } else {
            // TODO: this is horrendously inefficient.
            for (size_t i = 0; i < arr->size(); ++i) out->add(arr->get(i));
            out->add(new_el);
        }
        return new_val(counted_t<const datum_t>(out.release()));
    }
};

class append_term_t : public pend_term_t {
public:
    append_term_t(env_t *env, protob_t<const Term> term) : pend_term_t(env, term) { }
private:
    virtual counted_t<val_t> eval_impl() {
        return pend(AP);
    }
    virtual const char *name() const { return "append"; }
};

class prepend_term_t : public pend_term_t {
public:
    prepend_term_t(env_t *env, protob_t<const Term> term) : pend_term_t(env, term) { }
private:
    virtual counted_t<val_t> eval_impl() {
        return pend(PRE);
    }
    virtual const char *name() const { return "prepend"; }
};

// This gets the literal index of a (possibly negative) index relative to a
// fixed size.
size_t canonicalize(const term_t *t, int32_t index, size_t size, bool *oob_out = 0) {
    CT_ASSERT(sizeof(size_t) >= sizeof(int32_t));
    if (index >= 0) return index;
    if (size_t(index * -1) > size) {
        if (oob_out) {
            *oob_out = true;
        } else {
            rfail_target(t, "Index out of bounds: %d", index);
        }
        return 0;
    }
    return size + index;
}

class nth_term_t : public op_term_t {
public:
    nth_term_t(env_t *env, protob_t<const Term> term) : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<val_t> v = arg(0);
        int32_t n = arg(1)->as_int<int32_t>();
        if (v->get_type().is_convertible(val_t::type_t::DATUM)) {
            counted_t<const datum_t> arr = v->as_datum();
            size_t real_n = canonicalize(this, n, arr->size());
            return new_val(arr->get(real_n));
        } else {
            counted_t<datum_stream_t> s = v->as_seq();
            rcheck(n >= -1, strprintf("Cannot use an index < -1 (%d) on a stream.", n));

            counted_t<const datum_t> last_d;
            for (int32_t i = 0; ; ++i) {
                counted_t<const datum_t> d = s->next();
                if (!d.has()) {
                    rcheck(n == -1 && last_d.has(),
                           strprintf("Index out of bounds: %d", n));
                    return new_val(last_d);
                }
                if (i == n) return new_val(d);
                last_d = d;
                r_sanity_check(n == -1 || i < n);
            }
        }
    }
    virtual const char *name() const { return "nth"; }
};

// TODO: this kinda sucks.
class slice_term_t : public op_term_t {
public:
    slice_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(3)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<val_t> v = arg(0);
        int32_t fake_l = arg(1)->as_int<int32_t>();
        int32_t fake_r = arg(2)->as_int<int32_t>();
        if (v->get_type().is_convertible(val_t::type_t::DATUM)) {
            counted_t<const datum_t> arr = v->as_datum();
            rcheck(arr->get_type() == datum_t::R_ARRAY, "Cannot slice non-sequences.");
            bool l_oob = false;
            size_t real_l = canonicalize(this, fake_l, arr->size(), &l_oob);
            if (l_oob) real_l = 0;
            bool r_oob = false;
            size_t real_r = canonicalize(this, fake_r, arr->size(), &r_oob);

            scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
            if (!r_oob) {
                for (size_t i = real_l; i <= real_r; ++i) {
                    if (i >= arr->size()) break;
                    out->add(arr->get(i));
                }
            }
            return new_val(counted_t<const datum_t>(out.release()));
        } else if (v->get_type().is_convertible(val_t::type_t::SEQUENCE)) {
            counted_t<table_t> t;
            counted_t<datum_stream_t> seq;
            if (v->get_type().is_convertible(val_t::type_t::SELECTION)) {
                std::pair<counted_t<table_t>, counted_t<datum_stream_t> > t_seq
                    = v->as_selection();
                t = t_seq.first;
                seq = t_seq.second;
            } else {
                seq = v->as_seq();
            }

            rcheck(fake_l >= 0, "Cannot use a negative left index on a stream.");
            rcheck(fake_r >= -1, "Cannot use a right index < -1 on a stream");
            counted_t<datum_stream_t> new_ds = seq->slice(fake_l, fake_r);
            return t.has() ? new_val(new_ds, t) : new_val(new_ds);
        }
        rfail("Cannot slice non-sequences.");
        unreachable();
    }
    virtual const char *name() const { return "slice"; }
};

class limit_term_t : public op_term_t {
public:
    limit_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<val_t> v = arg(0);
        counted_t<table_t> t;
        if (v->get_type().is_convertible(val_t::type_t::SELECTION)) {
            t = v->as_selection().first;
        }
        counted_t<datum_stream_t> ds = v->as_seq();
        int32_t r = arg(1)->as_int<int32_t>();
        rcheck(r >= 0, strprintf("LIMIT takes a non-negative argument (got %d)", r));
        counted_t<datum_stream_t> new_ds;
        if (r == 0) {
            new_ds = ds->slice(1, 0); // (0, -1) has a different meaning
        } else {
            new_ds = ds->slice(0, r-1); // note that both bounds are inclusive
        }
        return t.has() ? new_val(new_ds, t) : new_val(new_ds);
    }
    virtual const char *name() const { return "limit"; }
};

class set_insert_term_t : public op_term_t {
public:
    set_insert_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<const datum_t> arr = arg(0)->as_datum();
        counted_t<const datum_t> new_el = arg(1)->as_datum();
        arr->check_type(datum_t::R_ARRAY);
        std::set<counted_t<const datum_t> > el_set;
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        for (size_t i = 0; i < arr->size(); ++i) {
            if(el_set.insert(arr->get(i)).second) {
                out->add(arr->get(i));
            }
        }
        if (!std_contains(el_set, new_el)) {
            out->add(new_el);
        }

        return new_val(counted_t<const datum_t>(out.release()));
    }

    virtual const char *name() const { return "set_insert"; }
};

class set_union_term_t : public op_term_t {
public:
    set_union_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<const datum_t> arr1 = arg(0)->as_datum();
        counted_t<const datum_t> arr2 = arg(1)->as_datum();
        arr1->check_type(datum_t::R_ARRAY);
        arr2->check_type(datum_t::R_ARRAY);
        std::set<counted_t<const datum_t> > el_set;
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        for (size_t i = 0; i < arr1->size(); ++i) {
            if(el_set.insert(arr1->get(i)).second) {
                out->add(arr1->get(i));
            }
        }
        for (size_t i = 0; i < arr2->size(); ++i) {
            if(el_set.insert(arr2->get(i)).second) {
                out->add(arr2->get(i));
            }
        }

        return new_val(counted_t<const datum_t>(out.release()));
    }

    virtual const char *name() const { return "set_union"; }
};

class set_intersection_term_t : public op_term_t {
public:
    set_intersection_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<const datum_t> arr1 = arg(0)->as_datum();
        counted_t<const datum_t> arr2 = arg(1)->as_datum();
        arr1->check_type(datum_t::R_ARRAY);
        arr2->check_type(datum_t::R_ARRAY);
        std::set<counted_t<const datum_t> > el_set;
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        for (size_t i = 0; i < arr1->size(); ++i) {
            el_set.insert(arr1->get(i));
        }
        for (size_t i = 0; i < arr2->size(); ++i) {
            if (std_contains(el_set, arr2->get(i))) {
                out->add(arr2->get(i));
                el_set.erase(arr2->get(i));
            }
        }

        return new_val(counted_t<const datum_t>(out.release()));
    }

    virtual const char *name() const { return "set_intersection"; }
};

class set_difference_term_t : public op_term_t {
public:
    set_difference_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<const datum_t> arr1 = arg(0)->as_datum();
        counted_t<const datum_t> arr2 = arg(1)->as_datum();
        arr1->check_type(datum_t::R_ARRAY);
        arr2->check_type(datum_t::R_ARRAY);
        std::set<counted_t<const datum_t> > el_set;
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        for (size_t i = 0; i < arr2->size(); ++i) {
            el_set.insert(arr2->get(i));
        }
        for (size_t i = 0; i < arr1->size(); ++i) {
            if (!std_contains(el_set, arr1->get(i))) {
                out->add(arr1->get(i));
                el_set.insert(arr1->get(i));
            }
        }

        return new_val(counted_t<const datum_t>(out.release()));
    }

    virtual const char *name() const { return "set_difference"; }
};

counted_t<term_t> make_append_term(env_t *env, protob_t<const Term> term) {
    return make_counted<append_term_t>(env, term);
}

counted_t<term_t> make_prepend_term(env_t *env, protob_t<const Term> term) {
    return make_counted<prepend_term_t>(env, term);
}

counted_t<term_t> make_nth_term(env_t *env, protob_t<const Term> term) {
    return make_counted<nth_term_t>(env, term);
}

counted_t<term_t> make_slice_term(env_t *env, protob_t<const Term> term) {
    return make_counted<slice_term_t>(env, term);
}

counted_t<term_t> make_limit_term(env_t *env, protob_t<const Term> term) {
    return make_counted<limit_term_t>(env, term);
}

counted_t<term_t> make_set_insert_term(env_t *env, protob_t<const Term> term) {
    return make_counted<set_insert_term_t>(env, term);
}

counted_t<term_t> make_set_union_term(env_t *env, protob_t<const Term> term) {
    return make_counted<set_union_term_t>(env, term);
}

counted_t<term_t> make_set_intersection_term(env_t *env, protob_t<const Term> term) {
    return make_counted<set_intersection_term_t>(env, term);
}

counted_t<term_t> make_set_difference_term(env_t *env, protob_t<const Term> term) {
    return make_counted<set_difference_term_t>(env, term);
}
}  // namespace ql
<commit_msg>Remove some unneeded calls to `check_type`.<commit_after>#include "rdb_protocol/terms/terms.hpp"

#include "rdb_protocol/error.hpp"
#include "rdb_protocol/op.hpp"

namespace ql {

class pend_term_t : public op_term_t {
public:
    pend_term_t(env_t *env, protob_t<const Term> term) : op_term_t(env, term, argspec_t(2)) { }
protected:
    enum which_pend_t {PRE, AP};
    counted_t<val_t> pend(which_pend_t which_pend) {
        counted_t<const datum_t> arr = arg(0)->as_datum();
        counted_t<const datum_t> new_el = arg(1)->as_datum();
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        if (which_pend == PRE) {
            // TODO: this is horrendously inefficient.
            out->add(new_el);
            for (size_t i = 0; i < arr->size(); ++i) out->add(arr->get(i));
        } else {
            // TODO: this is horrendously inefficient.
            for (size_t i = 0; i < arr->size(); ++i) out->add(arr->get(i));
            out->add(new_el);
        }
        return new_val(counted_t<const datum_t>(out.release()));
    }
};

class append_term_t : public pend_term_t {
public:
    append_term_t(env_t *env, protob_t<const Term> term) : pend_term_t(env, term) { }
private:
    virtual counted_t<val_t> eval_impl() {
        return pend(AP);
    }
    virtual const char *name() const { return "append"; }
};

class prepend_term_t : public pend_term_t {
public:
    prepend_term_t(env_t *env, protob_t<const Term> term) : pend_term_t(env, term) { }
private:
    virtual counted_t<val_t> eval_impl() {
        return pend(PRE);
    }
    virtual const char *name() const { return "prepend"; }
};

// This gets the literal index of a (possibly negative) index relative to a
// fixed size.
size_t canonicalize(const term_t *t, int32_t index, size_t size, bool *oob_out = 0) {
    CT_ASSERT(sizeof(size_t) >= sizeof(int32_t));
    if (index >= 0) return index;
    if (size_t(index * -1) > size) {
        if (oob_out) {
            *oob_out = true;
        } else {
            rfail_target(t, "Index out of bounds: %d", index);
        }
        return 0;
    }
    return size + index;
}

class nth_term_t : public op_term_t {
public:
    nth_term_t(env_t *env, protob_t<const Term> term) : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<val_t> v = arg(0);
        int32_t n = arg(1)->as_int<int32_t>();
        if (v->get_type().is_convertible(val_t::type_t::DATUM)) {
            counted_t<const datum_t> arr = v->as_datum();
            size_t real_n = canonicalize(this, n, arr->size());
            return new_val(arr->get(real_n));
        } else {
            counted_t<datum_stream_t> s = v->as_seq();
            rcheck(n >= -1, strprintf("Cannot use an index < -1 (%d) on a stream.", n));

            counted_t<const datum_t> last_d;
            for (int32_t i = 0; ; ++i) {
                counted_t<const datum_t> d = s->next();
                if (!d.has()) {
                    rcheck(n == -1 && last_d.has(),
                           strprintf("Index out of bounds: %d", n));
                    return new_val(last_d);
                }
                if (i == n) return new_val(d);
                last_d = d;
                r_sanity_check(n == -1 || i < n);
            }
        }
    }
    virtual const char *name() const { return "nth"; }
};

// TODO: this kinda sucks.
class slice_term_t : public op_term_t {
public:
    slice_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(3)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<val_t> v = arg(0);
        int32_t fake_l = arg(1)->as_int<int32_t>();
        int32_t fake_r = arg(2)->as_int<int32_t>();
        if (v->get_type().is_convertible(val_t::type_t::DATUM)) {
            counted_t<const datum_t> arr = v->as_datum();
            rcheck(arr->get_type() == datum_t::R_ARRAY, "Cannot slice non-sequences.");
            bool l_oob = false;
            size_t real_l = canonicalize(this, fake_l, arr->size(), &l_oob);
            if (l_oob) real_l = 0;
            bool r_oob = false;
            size_t real_r = canonicalize(this, fake_r, arr->size(), &r_oob);

            scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
            if (!r_oob) {
                for (size_t i = real_l; i <= real_r; ++i) {
                    if (i >= arr->size()) break;
                    out->add(arr->get(i));
                }
            }
            return new_val(counted_t<const datum_t>(out.release()));
        } else if (v->get_type().is_convertible(val_t::type_t::SEQUENCE)) {
            counted_t<table_t> t;
            counted_t<datum_stream_t> seq;
            if (v->get_type().is_convertible(val_t::type_t::SELECTION)) {
                std::pair<counted_t<table_t>, counted_t<datum_stream_t> > t_seq
                    = v->as_selection();
                t = t_seq.first;
                seq = t_seq.second;
            } else {
                seq = v->as_seq();
            }

            rcheck(fake_l >= 0, "Cannot use a negative left index on a stream.");
            rcheck(fake_r >= -1, "Cannot use a right index < -1 on a stream");
            counted_t<datum_stream_t> new_ds = seq->slice(fake_l, fake_r);
            return t.has() ? new_val(new_ds, t) : new_val(new_ds);
        }
        rfail("Cannot slice non-sequences.");
        unreachable();
    }
    virtual const char *name() const { return "slice"; }
};

class limit_term_t : public op_term_t {
public:
    limit_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<val_t> v = arg(0);
        counted_t<table_t> t;
        if (v->get_type().is_convertible(val_t::type_t::SELECTION)) {
            t = v->as_selection().first;
        }
        counted_t<datum_stream_t> ds = v->as_seq();
        int32_t r = arg(1)->as_int<int32_t>();
        rcheck(r >= 0, strprintf("LIMIT takes a non-negative argument (got %d)", r));
        counted_t<datum_stream_t> new_ds;
        if (r == 0) {
            new_ds = ds->slice(1, 0); // (0, -1) has a different meaning
        } else {
            new_ds = ds->slice(0, r-1); // note that both bounds are inclusive
        }
        return t.has() ? new_val(new_ds, t) : new_val(new_ds);
    }
    virtual const char *name() const { return "limit"; }
};

class set_insert_term_t : public op_term_t {
public:
    set_insert_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<const datum_t> arr = arg(0)->as_datum();
        counted_t<const datum_t> new_el = arg(1)->as_datum();
        std::set<counted_t<const datum_t> > el_set;
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        for (size_t i = 0; i < arr->size(); ++i) {
            if(el_set.insert(arr->get(i)).second) {
                out->add(arr->get(i));
            }
        }
        if (!std_contains(el_set, new_el)) {
            out->add(new_el);
        }

        return new_val(counted_t<const datum_t>(out.release()));
    }

    virtual const char *name() const { return "set_insert"; }
};

class set_union_term_t : public op_term_t {
public:
    set_union_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<const datum_t> arr1 = arg(0)->as_datum();
        counted_t<const datum_t> arr2 = arg(1)->as_datum();
        std::set<counted_t<const datum_t> > el_set;
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        for (size_t i = 0; i < arr1->size(); ++i) {
            if(el_set.insert(arr1->get(i)).second) {
                out->add(arr1->get(i));
            }
        }
        for (size_t i = 0; i < arr2->size(); ++i) {
            if(el_set.insert(arr2->get(i)).second) {
                out->add(arr2->get(i));
            }
        }

        return new_val(counted_t<const datum_t>(out.release()));
    }

    virtual const char *name() const { return "set_union"; }
};

class set_intersection_term_t : public op_term_t {
public:
    set_intersection_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<const datum_t> arr1 = arg(0)->as_datum();
        counted_t<const datum_t> arr2 = arg(1)->as_datum();
        std::set<counted_t<const datum_t> > el_set;
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        for (size_t i = 0; i < arr1->size(); ++i) {
            el_set.insert(arr1->get(i));
        }
        for (size_t i = 0; i < arr2->size(); ++i) {
            if (std_contains(el_set, arr2->get(i))) {
                out->add(arr2->get(i));
                el_set.erase(arr2->get(i));
            }
        }

        return new_val(counted_t<const datum_t>(out.release()));
    }

    virtual const char *name() const { return "set_intersection"; }
};

class set_difference_term_t : public op_term_t {
public:
    set_difference_term_t(env_t *env, protob_t<const Term> term)
        : op_term_t(env, term, argspec_t(2)) { }
private:
    virtual counted_t<val_t> eval_impl() {
        counted_t<const datum_t> arr1 = arg(0)->as_datum();
        counted_t<const datum_t> arr2 = arg(1)->as_datum();
        std::set<counted_t<const datum_t> > el_set;
        scoped_ptr_t<datum_t> out(new datum_t(datum_t::R_ARRAY));
        for (size_t i = 0; i < arr2->size(); ++i) {
            el_set.insert(arr2->get(i));
        }
        for (size_t i = 0; i < arr1->size(); ++i) {
            if (!std_contains(el_set, arr1->get(i))) {
                out->add(arr1->get(i));
                el_set.insert(arr1->get(i));
            }
        }

        return new_val(counted_t<const datum_t>(out.release()));
    }

    virtual const char *name() const { return "set_difference"; }
};

counted_t<term_t> make_append_term(env_t *env, protob_t<const Term> term) {
    return make_counted<append_term_t>(env, term);
}

counted_t<term_t> make_prepend_term(env_t *env, protob_t<const Term> term) {
    return make_counted<prepend_term_t>(env, term);
}

counted_t<term_t> make_nth_term(env_t *env, protob_t<const Term> term) {
    return make_counted<nth_term_t>(env, term);
}

counted_t<term_t> make_slice_term(env_t *env, protob_t<const Term> term) {
    return make_counted<slice_term_t>(env, term);
}

counted_t<term_t> make_limit_term(env_t *env, protob_t<const Term> term) {
    return make_counted<limit_term_t>(env, term);
}

counted_t<term_t> make_set_insert_term(env_t *env, protob_t<const Term> term) {
    return make_counted<set_insert_term_t>(env, term);
}

counted_t<term_t> make_set_union_term(env_t *env, protob_t<const Term> term) {
    return make_counted<set_union_term_t>(env, term);
}

counted_t<term_t> make_set_intersection_term(env_t *env, protob_t<const Term> term) {
    return make_counted<set_intersection_term_t>(env, term);
}

counted_t<term_t> make_set_difference_term(env_t *env, protob_t<const Term> term) {
    return make_counted<set_difference_term_t>(env, term);
}
}  // namespace ql
<|endoftext|>


<commit_before><commit_msg>more tests for ScRangeList::DeleteArea<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: servobj.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 21:49:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SC_SERVOBJ_HXX
#define SC_SERVOBJ_HXX

#ifndef _SFXLSTNER_HXX //autogen
#include <svtools/lstner.hxx>
#endif
#ifndef _SVT_LISTENER_HXX
#include <svtools/listener.hxx>
#endif
#ifndef _LINKSRC_HXX //autogen
#include <sfx2/linksrc.hxx>
#endif

#ifndef SC_SCGLOB_HXX
#include "global.hxx"
#endif

#ifndef SC_ADDRESS_HXX
#include "address.hxx"
#endif

class ScDocShell;
class ScServerObject;

class ScServerObjectSvtListenerForwarder : public SvtListener
{
    ScServerObject* pObj;
    SfxBroadcaster  aBroadcaster;
public:
                    ScServerObjectSvtListenerForwarder( ScServerObject* pObjP);
    virtual         ~ScServerObjectSvtListenerForwarder();
    virtual void    Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
};

class ScServerObject : public ::sfx2::SvLinkSource, public SfxListener
{
private:
    ScServerObjectSvtListenerForwarder  aForwarder;
    ScDocShell*     pDocSh;
    ScRange         aRange;
    String          aItemStr;
    BOOL            bRefreshListener;

    void    Clear();

public:
            ScServerObject( ScDocShell* pShell, const String& rItem );
    virtual ~ScServerObject();

    virtual BOOL GetData( ::com::sun::star::uno::Any & rData /*out param*/,
                             const String & rMimeType,
                             BOOL bSynchron = FALSE );

    virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
                         const SfxHint& rHint, const TypeId& rHintType );
            void    EndListeningAll();
};

//SO2_DECL_REF( ScServerObject )

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.5.700); FILE MERGED 2008/04/01 15:31:00 thb 1.5.700.3: #i85898# Stripping all external header guards 2008/04/01 12:36:49 thb 1.5.700.2: #i85898# Stripping all external header guards 2008/03/31 17:15:47 rt 1.5.700.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: servobj.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SC_SERVOBJ_HXX
#define SC_SERVOBJ_HXX

#include <svtools/lstner.hxx>
#include <svtools/listener.hxx>
#include <sfx2/linksrc.hxx>
#include "global.hxx"
#include "address.hxx"

class ScDocShell;
class ScServerObject;

class ScServerObjectSvtListenerForwarder : public SvtListener
{
    ScServerObject* pObj;
    SfxBroadcaster  aBroadcaster;
public:
                    ScServerObjectSvtListenerForwarder( ScServerObject* pObjP);
    virtual         ~ScServerObjectSvtListenerForwarder();
    virtual void    Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
};

class ScServerObject : public ::sfx2::SvLinkSource, public SfxListener
{
private:
    ScServerObjectSvtListenerForwarder  aForwarder;
    ScDocShell*     pDocSh;
    ScRange         aRange;
    String          aItemStr;
    BOOL            bRefreshListener;

    void    Clear();

public:
            ScServerObject( ScDocShell* pShell, const String& rItem );
    virtual ~ScServerObject();

    virtual BOOL GetData( ::com::sun::star::uno::Any & rData /*out param*/,
                             const String & rMimeType,
                             BOOL bSynchron = FALSE );

    virtual void SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
                         const SfxHint& rHint, const TypeId& rHintType );
            void    EndListeningAll();
};

//SO2_DECL_REF( ScServerObject )

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: olkact.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: nn $ $Date: 2000-09-22 18:37:37 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "ui_pch.hxx"
#endif

#pragma hdrstop

//------------------------------------------------------------------

#define _BIGINT_HXX
#define _CACHESTR_HXX
#define _CONFIG_HXX
#define _CURSOR_HXX
#define _CTRLTOOL_HXX
#define _DLGCFG_HXX
#define _DYNARR_HXX
#define _EXTATTR_HXX
#define _FILDLG_HXX
#define _FONTDLG_HXX
#define _FRM3D_HXX
#define _INTRO_HXX
#define _ISETBWR_HXX
#define _NO_SVRTF_PARSER_HXX
#define _MACRODLG_HXX
#define _MODALDLG_HXX
#define _MOREBUTTON_HXX
#define _OUTLINER_HXX
#define _PASSWD_HXX
#define _PRNDLG_HXX
//#define _POLY_HXX
#define _PVRWIN_HXX
#define _QUEUE_HXX
#define _RULER_HXX
#define _SCRWIN_HXX
#define _SETBRW_HXX
#define _STACK_HXX
//#define _STATUS_HXX ***
#define _STDMENU_HXX
#define _TABBAR_HXX
//#define _VCBRW_HXX
#define _VCTRLS_HXX
//#define _VCSBX_HXX
#define _VCONT_HXX
#define _VDRWOBJ_HXX

//sfx
#define _SFXAPPWIN_HXX
#define _SFXCTRLITEM
#define _SFXDISPATCH_HXX
#define _SFXFILEDLG_HXX
#define _SFXIMGMGR_HXX
#define _SFXIPFRM_HXX
#define _SFX_MACRO_HXX
#define _SFXMULTISEL_HXX
#define _SFX_MINFITEM_HXX

//sfxcore.hxx
//#define _SFXINIMGR_HXX ***
//#define _SFXCFGITEM_HXX
//#define _SFX_PRINTER_HXX
#define _SFXGENLINK_HXX
#define _SFXHINTPOST_HXX
#define _SFXDOCINF_HXX
#define _SFXLINKHDL_HXX
//#define _SFX_PROGRESS_HXX

//sfxsh.hxx
//#define _SFX_SHELL_HXX
//#define _SFXAPP_HXX
//#define _SFXDISPATCH_HXX
//#define _SFXMSG_HXX ***
//#define _SFXOBJFACE_HXX ***
//#define _SFXREQUEST_HXX
#define _SFXMACRO_HXX

// SFX
//#define _SFXAPPWIN_HXX ***
#define _SFX_SAVEOPT_HXX
//#define _SFX_CHILDWIN_HXX
//#define _SFXCTRLITEM_HXX
#define _SFXPRNMON_HXX
#define _INTRO_HXX
#define _SFXMSGDESCR_HXX
#define _SFXMSGPOOL_HXX
#define _SFXFILEDLG_HXX
#define _PASSWD_HXX
#define _SFXTBXCTRL_HXX
#define _SFXSTBITEM_HXX
#define _SFXMNUITEM_HXX
#define _SFXIMGMGR_HXX
#define _SFXTBXMGR_HXX
#define _SFXSTBMGR_HXX
#define _SFX_MINFITEM_HXX
#define _SFXEVENT_HXX

//sfxdoc.hxx
//#define _SFX_OBJSH_HXX
//#define _SFX_CLIENTSH_HXX
//#define _SFXDOCINF_HXX
//#define _SFX_OBJFAC_HXX
#define _SFX_DOCFILT_HXX
//#define _SFXDOCFILE_HXX ***
//define _VIEWFAC_HXX
//#define _SFXVIEWFRM_HXX
//#define _SFXVIEWSH_HXX
//#define _MDIFRM_HXX ***
#define _SFX_IPFRM_HXX
//#define _SFX_INTERNO_HXX

//sfxdlg.hxx
//#define _SFXTABDLG_HXX
//#define _BASEDLGS_HXX ***
#define _SFX_DINFDLG_HXX
#define _SFXDINFEDT_HXX
#define _SFX_MGETEMPL_HXX
#define _SFX_TPLPITEM_HXX
//#define _SFX_STYLEDLG_HXX
#define _NEWSTYLE_HXX
//#define _SFXDOCTEMPL_HXX ***
//#define _SFXDOCTDLG_HXX ***
//#define _SFX_TEMPLDLG_HXX ***
//#define _SFXNEW_HXX ***
#define _SFXDOCMAN_HXX
//#define _SFXDOCKWIN_HXX

//sfxitems.hxx
#define _SFX_WHMAP_HXX
#define _ARGS_HXX
//#define _SFXPOOLITEM_HXX
//#define _SFXINTITEM_HXX
//#define _SFXENUMITEM_HXX
#define _SFXFLAGITEM_HXX
//#define _SFXSTRITEM_HXX
#define _SFXPTITEM_HXX
#define _SFXRECTITEM_HXX
//#define _SFXITEMPOOL_HXX
//#define _SFXITEMSET_HXX
#define _SFXITEMITER_HXX
#define _SFX_WHITER_HXX
#define _SFXPOOLCACH_HXX
//#define _AEITEM_HXX
#define _SFXRNGITEM_HXX
//#define _SFXSLSTITM_HXX
//#define _SFXSTYLE_HXX

//xout.hxx
//#define _XENUM_HXX
//#define _XPOLY_HXX
//#define _XATTR_HXX
//#define _XOUTX_HXX
//#define _XPOOL_HXX
//#define _XTABLE_HXX

//svdraw.hxx
#define _SDR_NOITEMS
#define _SDR_NOTOUCH
#define _SDR_NOTRANSFORM
//#define _SDR_NOOBJECTS
//#define _SDR_NOVIEWS

#define _SFXBASIC_HXX
#define _SFX_DOCFILE_HXX
#define _SFX_DOCFILT_HXX
#define _SFX_DOCINF_HXX
#define _SFX_DOCSH_HXX
#define _SFX_TEMPLDLG_HXX
#define _SFXSTBMGR_HXX
#define _SFXTBXMGR_HXX
#define _SFXIMGMGR_HXX
#define _SFXMNUITEM_HXX
#define _SFXMNUMGR_HXX
#define _SFXSTBITEM_HXX
#define _SFXTBXCTRL_HXX
#define _SFXFILEDLG_HXX
#define _SFXREQUEST_HXX
#define _SFXOBJFACE_HXX
#define _SFXMSGPOOL_HXX
#define _SFXMSGDESCR_HXX
#define _SFXMSG_HXX
#define _SFX_PRNMON_HXX

//si
#define _SI_NOSBXCONTROLS
#define _SI_NOCONTROL
//#define SI_NOITEMS
//#define SI_NODRW
//#define SI_NOOTHERFORMS
#define _SIDLL_HXX
//#define _VCSBX_HXX
//#define _VCBRW_HXX

//#define _SVDATTR_HXX      <--- der wars
#define _SVDXOUT_HXX
#define _SVDEC_HXX
//#define _SVDIO_HXX
//#define _SVDLAYER_HXX
//#define _SVDRAG_HXX
#define _SVINCVW_HXX
#define _SV_MULTISEL_HXX
#define _SVRTV_HXX
#define _SVTABBX_HXX

#define _SVX_DAILDLL_HXX
#define _SVX_HYPHEN_HXX
#define _SVX_IMPGRF_HXX
#define _SVX_OPTITEMS_HXX
#define _SVX_OPTGERL_HXX
#define _SVX_OPTSAVE_HXX
#define _SVX_OPTSPELL_HXX
#define _SVX_OPTPATH_HXX
#define _SVX_OPTLINGU_HXX
#define _SVX_RULER_HXX
#define _SVX_RULRITEM_HXX
#define _SVX_SPLWRAP_HXX
#define _SVX_SPLDLG_HXX
#define _SVX_THESDLG_HXX

// INCLUDE ---------------------------------------------------------------

#include <sfx2/childwin.hxx>
#include <sfx2/objsh.hxx>

#include "document.hxx"
#include "viewdata.hxx"
#include "drawview.hxx"
#include "drawpage.hxx"
#include "drwlayer.hxx"

// STATIC DATA -----------------------------------------------------------

// -----------------------------------------------------------------------

void ActivateOlk( ScViewData* pViewData )
{
    // Browser fuer Virtual Controls fuellen
    //  VC's und den Browser dazu gibts nicht mehr...

    //  GetSbxForm gibt's nicht mehr, muss auch nichts mehr angemeldet werden
}

void DeActivateOlk( ScViewData* pViewData )
{
    // Browser fuer Virtual Controls fuellen
    //  VC's und den Browser dazu gibts nicht mehr...

    //  GetSbxForm gibt's nicht mehr, muss auch nichts mehr angemeldet werden
}

<commit_msg>del: old stuff<commit_after>/*************************************************************************
 *
 *  $RCSfile: olkact.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: mh $ $Date: 2002-01-16 11:26:47 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "ui_pch.hxx"
#endif

#pragma hdrstop

// INCLUDE ---------------------------------------------------------------

class ScViewData;

// -----------------------------------------------------------------------

void ActivateOlk( ScViewData* pViewData )
{
    // Browser fuer Virtual Controls fuellen
    //  VC's und den Browser dazu gibts nicht mehr...

    //  GetSbxForm gibt's nicht mehr, muss auch nichts mehr angemeldet werden
}

void DeActivateOlk( ScViewData* pViewData )
{
    // Browser fuer Virtual Controls fuellen
    //  VC's und den Browser dazu gibts nicht mehr...

    //  GetSbxForm gibt's nicht mehr, muss auch nichts mehr angemeldet werden
}

<|endoftext|>


<commit_before>// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "lid_space_compaction_job_take2.h"
#include "i_document_scan_iterator.h"
#include "i_lid_space_compaction_handler.h"
#include "i_operation_storer.h"
#include <vespa/searchcore/proton/feedoperation/moveoperation.h>
#include <vespa/searchcorespi/index/i_thread_service.h>
#include <vespa/persistence/spi/bucket_tasks.h>
#include <vespa/document/fieldvalue/document.h>
#include <vespa/vespalib/util/destructor_callbacks.h>
#include <vespa/vespalib/util/lambdatask.h>
#include <cassert>
#include <thread>

using search::DocumentMetaData;
using search::LidUsageStats;
using storage::spi::makeBucketTask;
using storage::spi::Bucket;
using vespalib::makeLambdaTask;

namespace proton::lidspace {

namespace {

class IncOnDestruct {
public:
    IncOnDestruct(std::atomic<size_t> & count) : _count(count) {}
    ~IncOnDestruct() {
        _count.fetch_add(1, std::memory_order_relaxed);
    }
private:
    std::atomic<size_t> & _count;
};

bool
isSameDocument(const search::DocumentMetaData & a, const search::DocumentMetaData & b) {
    return (a.lid == b.lid) &&
           (a.bucketId == b.bucketId) &&
           (a.gid == b.gid) &&
           (a.timestamp == b.timestamp); // Timestamp check can be removed once logic has proved itself in large scale.
}

}

void
CompactionJob::failOperation() {
    IncOnDestruct countGuard(_executedCount);
    _master.execute(makeLambdaTask([this] { _scanItr.reset(); }
}

bool
CompactionJob::scanDocuments(const LidUsageStats &stats)
{
    if (_scanItr->valid()) {
        DocumentMetaData document = getNextDocument(stats, false);
        if (document.valid()) {
            Bucket metaBucket(document::Bucket(_bucketSpace, document.bucketId));
            IDestructorCallback::SP context = getLimiter().beginOperation();
            auto bucketTask = makeBucketTask([this, meta=document, opsTracker=std::move(context)]
            (const Bucket & bucket, std::shared_ptr<IDestructorCallback> onDone) {
                assert(bucket.getBucketId() == meta.bucketId);
                using DoneContext = vespalib::KeepAlive<std::pair<IDestructorCallback::SP, IDestructorCallback::SP>>;
                moveDocument(meta, std::make_shared<DoneContext>(std::make_pair(std::move(opsTracker), std::move(onDone))));
            }, [this](const Bucket &) { failOperation(); });

            _startedCount.fetch_add(1, std::memory_order_relaxed);
            _bucketExecutor.execute(metaBucket, std::move(bucketTask));
            if (isBlocked(BlockedReason::OUTSTANDING_OPS)) {
                return true;
            }
        }
    }
    return false;
}

void
CompactionJob::moveDocument(const search::DocumentMetaData & metaThen, std::shared_ptr<IDestructorCallback> context) {
    IncOnDestruct countGuard(_executedCount);
    if (_stopped.load(std::memory_order_relaxed)) return;
    // The real lid must be sampled in the master thread.
    //TODO remove target lid from createMoveOperation interface
    auto op = _handler->createMoveOperation(metaThen, 0);
    if (!op || !op->getDocument()) return;
    // Early detection and force md5 calculation outside of master thread
    if (metaThen.gid != op->getDocument()->getId().getGlobalId()) return;

    _master.execute(makeLambdaTask([this, meta=metaThen, moveOp=std::move(op), onDone=std::move(context)]() mutable {
        if (_stopped.load(std::memory_order_relaxed)) return;
        completeMove(meta, std::move(moveOp), std::move(onDone));
    }));
}

void
CompactionJob::completeMove(const search::DocumentMetaData & metaThen, std::unique_ptr<MoveOperation> moveOp,
                            std::shared_ptr<IDestructorCallback> onDone)
{
    // Reread meta data as document might have been altered after move was initiated
    // If so it will fail the timestamp sanity check later on.
    search::DocumentMetaData metaNow = _handler->getMetaData(metaThen.lid);
    // This should be impossible and should probably be an assert
    if ( ! isSameDocument(metaThen, metaNow)) return;
    if (metaNow.gid != moveOp->getDocument()->getId().getGlobalId()) return;

    uint32_t lowestLid = _handler->getLidStatus().getLowestFreeLid();
    if (lowestLid >= metaNow.lid) return;
    moveOp->setTargetLid(lowestLid);
    _opStorer.appendOperation(*moveOp, onDone);
    _handler->handleMove(*moveOp, std::move(onDone));
}

CompactionJob::CompactionJob(const DocumentDBLidSpaceCompactionConfig &config,
                             std::shared_ptr<ILidSpaceCompactionHandler> handler,
                             IOperationStorer &opStorer,
                             IThreadService & master,
                             BucketExecutor & bucketExecutor,
                             IDiskMemUsageNotifier &diskMemUsageNotifier,
                             const BlockableMaintenanceJobConfig &blockableConfig,
                             IClusterStateChangedNotifier &clusterStateChangedNotifier,
                             bool nodeRetired,
                             document::BucketSpace bucketSpace)
    : LidSpaceCompactionJobBase(config, std::move(handler), opStorer, diskMemUsageNotifier,
                                blockableConfig, clusterStateChangedNotifier, nodeRetired),
      _master(master),
      _bucketExecutor(bucketExecutor),
      _bucketSpace(bucketSpace),
      _stopped(false),
      _startedCount(0),
      _executedCount(0)
{ }

CompactionJob::~CompactionJob() = default;

bool
CompactionJob::inSync() const {
    return _executedCount == _startedCount;
}

void
CompactionJob::onStop() {
    _stopped = true;
    while ( ! inSync() ) {
        std::this_thread::sleep_for(1ms);
    }
}

} // namespace proton
<commit_msg>Fix typo.<commit_after>// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "lid_space_compaction_job_take2.h"
#include "i_document_scan_iterator.h"
#include "i_lid_space_compaction_handler.h"
#include "i_operation_storer.h"
#include <vespa/searchcore/proton/feedoperation/moveoperation.h>
#include <vespa/searchcorespi/index/i_thread_service.h>
#include <vespa/persistence/spi/bucket_tasks.h>
#include <vespa/document/fieldvalue/document.h>
#include <vespa/vespalib/util/destructor_callbacks.h>
#include <vespa/vespalib/util/lambdatask.h>
#include <cassert>
#include <thread>

using search::DocumentMetaData;
using search::LidUsageStats;
using storage::spi::makeBucketTask;
using storage::spi::Bucket;
using vespalib::makeLambdaTask;

namespace proton::lidspace {

namespace {

class IncOnDestruct {
public:
    IncOnDestruct(std::atomic<size_t> & count) : _count(count) {}
    ~IncOnDestruct() {
        _count.fetch_add(1, std::memory_order_relaxed);
    }
private:
    std::atomic<size_t> & _count;
};

bool
isSameDocument(const search::DocumentMetaData & a, const search::DocumentMetaData & b) {
    return (a.lid == b.lid) &&
           (a.bucketId == b.bucketId) &&
           (a.gid == b.gid) &&
           (a.timestamp == b.timestamp); // Timestamp check can be removed once logic has proved itself in large scale.
}

}

void
CompactionJob::failOperation() {
    IncOnDestruct countGuard(_executedCount);
    _master.execute(makeLambdaTask([this] { _scanItr.reset(); }));
}

bool
CompactionJob::scanDocuments(const LidUsageStats &stats)
{
    if (_scanItr->valid()) {
        DocumentMetaData document = getNextDocument(stats, false);
        if (document.valid()) {
            Bucket metaBucket(document::Bucket(_bucketSpace, document.bucketId));
            IDestructorCallback::SP context = getLimiter().beginOperation();
            auto bucketTask = makeBucketTask([this, meta=document, opsTracker=std::move(context)]
            (const Bucket & bucket, std::shared_ptr<IDestructorCallback> onDone) {
                assert(bucket.getBucketId() == meta.bucketId);
                using DoneContext = vespalib::KeepAlive<std::pair<IDestructorCallback::SP, IDestructorCallback::SP>>;
                moveDocument(meta, std::make_shared<DoneContext>(std::make_pair(std::move(opsTracker), std::move(onDone))));
            }, [this](const Bucket &) { failOperation(); });

            _startedCount.fetch_add(1, std::memory_order_relaxed);
            _bucketExecutor.execute(metaBucket, std::move(bucketTask));
            if (isBlocked(BlockedReason::OUTSTANDING_OPS)) {
                return true;
            }
        }
    }
    return false;
}

void
CompactionJob::moveDocument(const search::DocumentMetaData & metaThen, std::shared_ptr<IDestructorCallback> context) {
    IncOnDestruct countGuard(_executedCount);
    if (_stopped.load(std::memory_order_relaxed)) return;
    // The real lid must be sampled in the master thread.
    //TODO remove target lid from createMoveOperation interface
    auto op = _handler->createMoveOperation(metaThen, 0);
    if (!op || !op->getDocument()) return;
    // Early detection and force md5 calculation outside of master thread
    if (metaThen.gid != op->getDocument()->getId().getGlobalId()) return;

    _master.execute(makeLambdaTask([this, meta=metaThen, moveOp=std::move(op), onDone=std::move(context)]() mutable {
        if (_stopped.load(std::memory_order_relaxed)) return;
        completeMove(meta, std::move(moveOp), std::move(onDone));
    }));
}

void
CompactionJob::completeMove(const search::DocumentMetaData & metaThen, std::unique_ptr<MoveOperation> moveOp,
                            std::shared_ptr<IDestructorCallback> onDone)
{
    // Reread meta data as document might have been altered after move was initiated
    // If so it will fail the timestamp sanity check later on.
    search::DocumentMetaData metaNow = _handler->getMetaData(metaThen.lid);
    // This should be impossible and should probably be an assert
    if ( ! isSameDocument(metaThen, metaNow)) return;
    if (metaNow.gid != moveOp->getDocument()->getId().getGlobalId()) return;

    uint32_t lowestLid = _handler->getLidStatus().getLowestFreeLid();
    if (lowestLid >= metaNow.lid) return;
    moveOp->setTargetLid(lowestLid);
    _opStorer.appendOperation(*moveOp, onDone);
    _handler->handleMove(*moveOp, std::move(onDone));
}

CompactionJob::CompactionJob(const DocumentDBLidSpaceCompactionConfig &config,
                             std::shared_ptr<ILidSpaceCompactionHandler> handler,
                             IOperationStorer &opStorer,
                             IThreadService & master,
                             BucketExecutor & bucketExecutor,
                             IDiskMemUsageNotifier &diskMemUsageNotifier,
                             const BlockableMaintenanceJobConfig &blockableConfig,
                             IClusterStateChangedNotifier &clusterStateChangedNotifier,
                             bool nodeRetired,
                             document::BucketSpace bucketSpace)
    : LidSpaceCompactionJobBase(config, std::move(handler), opStorer, diskMemUsageNotifier,
                                blockableConfig, clusterStateChangedNotifier, nodeRetired),
      _master(master),
      _bucketExecutor(bucketExecutor),
      _bucketSpace(bucketSpace),
      _stopped(false),
      _startedCount(0),
      _executedCount(0)
{ }

CompactionJob::~CompactionJob() = default;

bool
CompactionJob::inSync() const {
    return _executedCount == _startedCount;
}

void
CompactionJob::onStop() {
    _stopped = true;
    while ( ! inSync() ) {
        std::this_thread::sleep_for(1ms);
    }
}

} // namespace proton
<|endoftext|>