<commit_before>// Copyright 2017 The Ray Authors.
//
// 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 "ray/util/event.h"
#include <boost/filesystem.hpp>

namespace ray {
///
/// LogEventReporter
///
LogEventReporter::LogEventReporter(rpc::Event_SourceType source_type,
                                   const std::string &log_dir, bool force_flush,
                                   int rotate_max_file_size, int rotate_max_file_num)
    : log_dir_(log_dir),
      force_flush_(force_flush),
      rotate_max_file_size_(rotate_max_file_size),
      rotate_max_file_num_(rotate_max_file_num) {
  RAY_CHECK(log_dir_ != "");
  if (log_dir_.back() != '/') {
    log_dir_ += '/';
  }

  // generate file name, if the soucrce type is RAYLET or GCS, the file name would like
  // event_GCS.log, event_RAYLET.log other condition would like
  // event_CORE_WOREKER_{pid}.log
  file_name_ = "event_" + Event_SourceType_Name(source_type);
  if (source_type == rpc::Event_SourceType::Event_SourceType_CORE_WORKER ||
      source_type == rpc::Event_SourceType::Event_SourceType_COMMON) {
    file_name_ += "_" + std::to_string(getpid());
  }
  file_name_ += ".log";

  std::string log_sink_key = GetReporterKey() + log_dir_ + file_name_;
  log_sink_ = spdlog::get(log_sink_key);
  // If the file size is over {rotate_max_file_size_} MB, this file would be renamed
  // for example event_GCS.0.log, event_GCS.1.log, event_GCS.2.log ...
  // We alow to rotate for {rotate_max_file_num_} times.
  if (log_sink_ == nullptr) {
    log_sink_ =
        spdlog::rotating_logger_mt(log_sink_key, log_dir_ + file_name_,
                                   1048576 * rotate_max_file_size_, rotate_max_file_num_);
  }
  log_sink_->set_pattern("%v");
}

LogEventReporter::~LogEventReporter() { Flush(); }

void LogEventReporter::Flush() { log_sink_->flush(); }

std::string LogEventReporter::replaceLineFeed(std::string message) {
  std::stringstream ss;
  // If the message has \n or \r, we will replace with \\n
  for (int i = 0, len = message.size(); i < len; ++i) {
    if (message[i] == '\n' || message[i] == '\r') {
      ss << "\\n";
    } else {
      ss << message[i];
    }
  }
  return ss.str();
}

std::string LogEventReporter::EventToString(const rpc::Event &event,
                                            const json &custom_fields) {
  json j;

  auto time_stamp = event.timestamp();
  std::stringstream time_stamp_buffer;
  char time_buffer[30];
  time_t epoch_time_as_time_t = time_stamp / 1000000;

  struct tm *dt = localtime(&epoch_time_as_time_t);
  strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%d %H:%M:%S.", dt);

  time_stamp_buffer << std::string(time_buffer) << std::setw(6) << std::setfill('0')
                    << time_stamp % 1000000;

  j["time_stamp"] = time_stamp_buffer.str();
  j["severity"] = Event_Severity_Name(event.severity());
  j["label"] = event.label();
  j["event_id"] = event.event_id();
  j["source_type"] = Event_SourceType_Name(event.source_type());
  j["host_name"] = event.source_hostname();
  j["pid"] = std::to_string(event.source_pid());
  // Make sure the serialized json is one line in the event log.
  j["message"] = replaceLineFeed(event.message());
  j["custom_fields"] = custom_fields;

  // the final string is like:
  // {"time_stamp":"2020-08-29 14:18:15.998084","severity":"INFO","label":"label
  // 1","event_id":"de150792ceb151c815d359d4b675fcc6266a","source_type":"CORE_WORKER","host_name":"Macbool.local","pid":"20830","message":"send
  // message 1","custom_fields":{"task_id":"task 1","job_id":"job 1","node_id":"node 1"}}

  return j.dump();
}

void LogEventReporter::Report(const rpc::Event &event, const json &custom_fields) {
  RAY_CHECK(Event_SourceType_IsValid(event.source_type()));
  RAY_CHECK(Event_Severity_IsValid(event.severity()));
  std::string result = EventToString(event, custom_fields);

  log_sink_->info(result);
  if (force_flush_) {
    Flush();
  }
}

///
/// EventManager
///
EventManager::EventManager() {
  RayLog::AddFatalLogCallbacks({[](const std::string &label, const std::string &content) {
    RayEvent::ReportEvent("FATAL", label, content);
  }});
}

EventManager &EventManager::Instance() {
  static EventManager instance_;
  return instance_;
}

bool EventManager::IsEmpty() { return reporter_map_.empty(); }

void EventManager::Publish(const rpc::Event &event, const json &custom_fields) {
  for (const auto &element : reporter_map_) {
    (element.second)->Report(event, custom_fields);
  }
}

void EventManager::AddReporter(std::shared_ptr<BaseEventReporter> reporter) {
  reporter_map_.emplace(reporter->GetReporterKey(), reporter);
}

void EventManager::ClearReporters() { reporter_map_.clear(); }
///
/// RayEventContext
///
thread_local std::unique_ptr<RayEventContext> RayEventContext::context_ = nullptr;

RayEventContext &RayEventContext::Instance() {
  if (context_ == nullptr) {
    context_ = std::unique_ptr<RayEventContext>(new RayEventContext());
  }
  return *context_;
}

void RayEventContext::SetEventContext(
    rpc::Event_SourceType source_type,
    const std::unordered_map<std::string, std::string> &custom_fields) {
  source_type_ = source_type;
  custom_fields_ = custom_fields;
}

void RayEventContext::ResetEventContext() {
  source_type_ = rpc::Event_SourceType::Event_SourceType_COMMON;
  custom_fields_.clear();
}

void RayEventContext::SetCustomFields(const std::string &key, const std::string &value) {
  custom_fields_[key] = value;
}

void RayEventContext::SetCustomFields(
    const std::unordered_map<std::string, std::string> &custom_fields) {
  custom_fields_ = custom_fields;
}
///
/// RayEvent
///
void RayEvent::ReportEvent(const std::string &severity, const std::string &label,
                           const std::string &message) {
  rpc::Event_Severity severity_ele =
      rpc::Event_Severity::Event_Severity_Event_Severity_INT_MIN_SENTINEL_DO_NOT_USE_;
  RAY_CHECK(rpc::Event_Severity_Parse(severity, &severity_ele));
  RayEvent(severity_ele, label) << message;
}

RayEvent::~RayEvent() { SendMessage(osstream_.str()); }

void RayEvent::SendMessage(const std::string &message) {
  RAY_CHECK(rpc::Event_SourceType_IsValid(RayEventContext::Instance().GetSourceType()));
  RAY_CHECK(rpc::Event_Severity_IsValid(severity_));

  if (EventManager::Instance().IsEmpty()) {
    return;
  }

  rpc::Event event;

  std::string event_id_buffer = std::string(18, ' ');
  FillRandom(&event_id_buffer);
  event.set_event_id(StringToHex(event_id_buffer));

  event.set_source_type(RayEventContext::Instance().GetSourceType());
  event.set_source_hostname(RayEventContext::Instance().GetSourceHostname());
  event.set_source_pid(RayEventContext::Instance().GetSourcePid());

  event.set_severity(severity_);
  event.set_label(label_);
  event.set_message(message);
  event.set_timestamp(current_sys_time_us());

  auto mp = RayEventContext::Instance().GetCustomFields();
  for (const auto &pair : mp) {
    custom_fields_[pair.first] = pair.second;
  }
  event.mutable_custom_fields()->insert(mp.begin(), mp.end());

  EventManager::Instance().Publish(event, custom_fields_);
}

void RayEventInit(rpc::Event_SourceType source_type,
                  const std::unordered_map<std::string, std::string> &custom_fields,
                  const std::string &log_dir) {
  RayEventContext::Instance().SetEventContext(source_type, custom_fields);
  auto event_dir = boost::filesystem::path(log_dir) / boost::filesystem::path("event");
  ray::EventManager::Instance().AddReporter(
      std::make_shared<ray::LogEventReporter>(source_type, event_dir.string()));
  RAY_LOG(INFO) << "Ray Event initialized for " << Event_SourceType_Name(source_type);
}

}  // namespace ray
<commit_msg>[Core] fix event race condition  (#17947)<commit_after>// Copyright 2017 The Ray Authors.
//
// 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 "ray/util/event.h"
#include <boost/filesystem.hpp>

#include "absl/time/time.h"

namespace ray {
///
/// LogEventReporter
///
LogEventReporter::LogEventReporter(rpc::Event_SourceType source_type,
                                   const std::string &log_dir, bool force_flush,
                                   int rotate_max_file_size, int rotate_max_file_num)
    : log_dir_(log_dir),
      force_flush_(force_flush),
      rotate_max_file_size_(rotate_max_file_size),
      rotate_max_file_num_(rotate_max_file_num) {
  RAY_CHECK(log_dir_ != "");
  if (log_dir_.back() != '/') {
    log_dir_ += '/';
  }

  // generate file name, if the soucrce type is RAYLET or GCS, the file name would like
  // event_GCS.log, event_RAYLET.log other condition would like
  // event_CORE_WOREKER_{pid}.log
  file_name_ = "event_" + Event_SourceType_Name(source_type);
  if (source_type == rpc::Event_SourceType::Event_SourceType_CORE_WORKER ||
      source_type == rpc::Event_SourceType::Event_SourceType_COMMON) {
    file_name_ += "_" + std::to_string(getpid());
  }
  file_name_ += ".log";

  std::string log_sink_key = GetReporterKey() + log_dir_ + file_name_;
  log_sink_ = spdlog::get(log_sink_key);
  // If the file size is over {rotate_max_file_size_} MB, this file would be renamed
  // for example event_GCS.0.log, event_GCS.1.log, event_GCS.2.log ...
  // We alow to rotate for {rotate_max_file_num_} times.
  if (log_sink_ == nullptr) {
    log_sink_ =
        spdlog::rotating_logger_mt(log_sink_key, log_dir_ + file_name_,
                                   1048576 * rotate_max_file_size_, rotate_max_file_num_);
  }
  log_sink_->set_pattern("%v");
}

LogEventReporter::~LogEventReporter() { Flush(); }

void LogEventReporter::Flush() { log_sink_->flush(); }

std::string LogEventReporter::replaceLineFeed(std::string message) {
  std::stringstream ss;
  // If the message has \n or \r, we will replace with \\n
  for (int i = 0, len = message.size(); i < len; ++i) {
    if (message[i] == '\n' || message[i] == '\r') {
      ss << "\\n";
    } else {
      ss << message[i];
    }
  }
  return ss.str();
}

std::string LogEventReporter::EventToString(const rpc::Event &event,
                                            const json &custom_fields) {
  json j;

  auto time_stamp = event.timestamp();
  time_t epoch_time_as_time_t = time_stamp / 1000000;

  absl::Time absl_time = absl::FromTimeT(epoch_time_as_time_t);
  std::stringstream time_stamp_buffer;
  time_stamp_buffer << absl::FormatTime("%Y-%m-%d %H:%M:%S.", absl_time,
                                        absl::LocalTimeZone())
                    << std::setw(6) << std::setfill('0') << time_stamp % 1000000;

  j["time_stamp"] = time_stamp_buffer.str();
  j["severity"] = Event_Severity_Name(event.severity());
  j["label"] = event.label();
  j["event_id"] = event.event_id();
  j["source_type"] = Event_SourceType_Name(event.source_type());
  j["host_name"] = event.source_hostname();
  j["pid"] = std::to_string(event.source_pid());
  // Make sure the serialized json is one line in the event log.
  j["message"] = replaceLineFeed(event.message());
  j["custom_fields"] = custom_fields;

  // the final string is like:
  // {"time_stamp":"2020-08-29 14:18:15.998084","severity":"INFO","label":"label
  // 1","event_id":"de150792ceb151c815d359d4b675fcc6266a","source_type":"CORE_WORKER","host_name":"Macbool.local","pid":"20830","message":"send
  // message 1","custom_fields":{"task_id":"task 1","job_id":"job 1","node_id":"node 1"}}

  return j.dump();
}

void LogEventReporter::Report(const rpc::Event &event, const json &custom_fields) {
  RAY_CHECK(Event_SourceType_IsValid(event.source_type()));
  RAY_CHECK(Event_Severity_IsValid(event.severity()));
  std::string result = EventToString(event, custom_fields);

  log_sink_->info(result);
  if (force_flush_) {
    Flush();
  }
}

///
/// EventManager
///
EventManager::EventManager() {
  RayLog::AddFatalLogCallbacks({[](const std::string &label, const std::string &content) {
    RayEvent::ReportEvent("FATAL", label, content);
  }});
}

EventManager &EventManager::Instance() {
  static EventManager instance_;
  return instance_;
}

bool EventManager::IsEmpty() { return reporter_map_.empty(); }

void EventManager::Publish(const rpc::Event &event, const json &custom_fields) {
  for (const auto &element : reporter_map_) {
    (element.second)->Report(event, custom_fields);
  }
}

void EventManager::AddReporter(std::shared_ptr<BaseEventReporter> reporter) {
  reporter_map_.emplace(reporter->GetReporterKey(), reporter);
}

void EventManager::ClearReporters() { reporter_map_.clear(); }
///
/// RayEventContext
///
thread_local std::unique_ptr<RayEventContext> RayEventContext::context_ = nullptr;

RayEventContext &RayEventContext::Instance() {
  if (context_ == nullptr) {
    context_ = std::unique_ptr<RayEventContext>(new RayEventContext());
  }
  return *context_;
}

void RayEventContext::SetEventContext(
    rpc::Event_SourceType source_type,
    const std::unordered_map<std::string, std::string> &custom_fields) {
  source_type_ = source_type;
  custom_fields_ = custom_fields;
}

void RayEventContext::ResetEventContext() {
  source_type_ = rpc::Event_SourceType::Event_SourceType_COMMON;
  custom_fields_.clear();
}

void RayEventContext::SetCustomFields(const std::string &key, const std::string &value) {
  custom_fields_[key] = value;
}

void RayEventContext::SetCustomFields(
    const std::unordered_map<std::string, std::string> &custom_fields) {
  custom_fields_ = custom_fields;
}
///
/// RayEvent
///
void RayEvent::ReportEvent(const std::string &severity, const std::string &label,
                           const std::string &message) {
  rpc::Event_Severity severity_ele =
      rpc::Event_Severity::Event_Severity_Event_Severity_INT_MIN_SENTINEL_DO_NOT_USE_;
  RAY_CHECK(rpc::Event_Severity_Parse(severity, &severity_ele));
  RayEvent(severity_ele, label) << message;
}

RayEvent::~RayEvent() { SendMessage(osstream_.str()); }

void RayEvent::SendMessage(const std::string &message) {
  RAY_CHECK(rpc::Event_SourceType_IsValid(RayEventContext::Instance().GetSourceType()));
  RAY_CHECK(rpc::Event_Severity_IsValid(severity_));

  if (EventManager::Instance().IsEmpty()) {
    return;
  }

  rpc::Event event;

  std::string event_id_buffer = std::string(18, ' ');
  FillRandom(&event_id_buffer);
  event.set_event_id(StringToHex(event_id_buffer));

  event.set_source_type(RayEventContext::Instance().GetSourceType());
  event.set_source_hostname(RayEventContext::Instance().GetSourceHostname());
  event.set_source_pid(RayEventContext::Instance().GetSourcePid());

  event.set_severity(severity_);
  event.set_label(label_);
  event.set_message(message);
  event.set_timestamp(current_sys_time_us());

  auto mp = RayEventContext::Instance().GetCustomFields();
  for (const auto &pair : mp) {
    custom_fields_[pair.first] = pair.second;
  }
  event.mutable_custom_fields()->insert(mp.begin(), mp.end());

  EventManager::Instance().Publish(event, custom_fields_);
}

void RayEventInit(rpc::Event_SourceType source_type,
                  const std::unordered_map<std::string, std::string> &custom_fields,
                  const std::string &log_dir) {
  RayEventContext::Instance().SetEventContext(source_type, custom_fields);
  auto event_dir = boost::filesystem::path(log_dir) / boost::filesystem::path("event");
  ray::EventManager::Instance().AddReporter(
      std::make_shared<ray::LogEventReporter>(source_type, event_dir.string()));
  RAY_LOG(INFO) << "Ray Event initialized for " << Event_SourceType_Name(source_type);
}

}  // namespace ray
<|endoftext|>


<commit_before>//===-- shm.cpp -----------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Save/restore via shared memory to survive exec*()
//
//===----------------------------------------------------------------------===//

#include "shm.h"

#include "ipcreg_internal.h"
#include "magic_socket_nums.h"
#include "real.h"
#include "rename_fd.h"

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define UC(ret, msg) \
  unixCheck(ret, msg, __FILE__, __LINE__, __PRETTY_FUNCTION__);

void unixCheck(int ret, const char *msg, const char *file, unsigned line,
               const char *func, int err = errno) {
  if (ret == -1) {
    ipclog("Unix call failed in %s at %s:%u: %s - %s\n", func, file, line, msg,
           strerror(err));
    abort();
  }
}

static char buf[100];
const char *getShmName() {
  sprintf(buf, "/ipcd.%d\n", getpid());
  return buf;
}

int get_shm(int flags, mode_t mode) {
  int fd = shm_open(getShmName(), flags, mode);
  UC(fd, "shm_open");
  UC(fchmod(fd, mode), "fchmod on shared memory segment");
  return fd;
}

void shm_state_save() {
  // Create shared memory segment
  int fd = get_shm(O_RDWR | O_CREAT | O_EXCL, 0600);
  UC(fd, "get_shm");

  bool success = rename_fd(fd, MAGIC_SHM_FD, /* cloexec */ false);
  assert(success && "Failed to rename SHM fd!");

  // Do *not* close on exec! :)
  int flags = __real_fcntl(MAGIC_SHM_FD, F_GETFD, /* kludge */ 0);
  assert(flags >= 0);
  flags &= ~FD_CLOEXEC;
  int ret = __real_fcntl_int(MAGIC_SHM_FD, F_SETFD, flags);
  UC(ret, "fcntl CLOEXEC on shared memory segment");

  // Size the memory segment:
  ret = ftruncate(MAGIC_SHM_FD, sizeof(libipc_state));
  UC(ret, "ftruncate on shm");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                  MAP_SHARED, MAGIC_SHM_FD, 0);
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  *(libipc_state*)stateptr = state;

  // Unmap, but don't unlink the shared memory
  ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  ipclog("State saved!\n");
}

bool is_valid_fd(int fd) {
  return __real_fcntl(fd, F_GETFD, /* kludge */ 0) >= 0;
}

void shm_state_restore() {
  // If we have memory to restore, it'll be in our magic FD!
  if (!is_valid_fd(MAGIC_SHM_FD))
    return;

  ipclog("Inherited ipc state FD, starting state restoration...\n");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                        MAP_SHARED, MAGIC_SHM_FD, 0);
  // If our FD is still open, the memory better still be there!
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  // Copy state from shared memory segment
  state = *(libipc_state*)stateptr;

  int ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  // Done with the shared segment, thank you!
  ret = __real_close(MAGIC_SHM_FD);
  UC(ret, "close shm");
  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink after close");

  ipclog("State restored!\n");
}

void shm_state_destroy() {
  // If we have memory to restore, it'll be in our magic FD!
  assert(is_valid_fd(MAGIC_SHM_FD));

  int ret = __real_close(MAGIC_SHM_FD);
  assert(ret == 0);

  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink");

  ipclog("Destroyed saved state!\n");
}
<commit_msg>libipc: Attempt to handle already-existing shm case.<commit_after>//===-- shm.cpp -----------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Save/restore via shared memory to survive exec*()
//
//===----------------------------------------------------------------------===//

#include "shm.h"

#include "ipcreg_internal.h"
#include "magic_socket_nums.h"
#include "real.h"
#include "rename_fd.h"

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define UC(ret, msg) \
  unixCheck(ret, msg, __FILE__, __LINE__, __PRETTY_FUNCTION__);

void unixCheck(int ret, const char *msg, const char *file, unsigned line,
               const char *func, int err = errno) {
  if (ret == -1) {
    ipclog("Unix call failed in %s at %s:%u: %s - %s\n", func, file, line, msg,
           strerror(err));
    abort();
  }
}

static char buf[100];
const char *getShmName() {
  sprintf(buf, "/ipcd.%d\n", getpid());
  return buf;
}

int get_shm(int flags, mode_t mode) {
  int fd = shm_open(getShmName(), flags, mode);
  if (fd == EEXIST) {
    ipclog("Shared memory segment exists, attempting to remove it...\n");
    int ret = shm_unlink(getShmName());
    UC(ret, "Closing existing shm");

    // Okay, let's try this again
    fd = shm_open(getShmName(), flags, mode);
  }
  UC(fd, "shm_open");
  UC(fchmod(fd, mode), "fchmod on shared memory segment");
  return fd;
}

void shm_state_save() {
  // Create shared memory segment
  int fd = get_shm(O_RDWR | O_CREAT | O_EXCL, 0600);
  UC(fd, "get_shm");

  bool success = rename_fd(fd, MAGIC_SHM_FD, /* cloexec */ false);
  assert(success && "Failed to rename SHM fd!");

  // Do *not* close on exec! :)
  int flags = __real_fcntl(MAGIC_SHM_FD, F_GETFD, /* kludge */ 0);
  assert(flags >= 0);
  flags &= ~FD_CLOEXEC;
  int ret = __real_fcntl_int(MAGIC_SHM_FD, F_SETFD, flags);
  UC(ret, "fcntl CLOEXEC on shared memory segment");

  // Size the memory segment:
  ret = ftruncate(MAGIC_SHM_FD, sizeof(libipc_state));
  UC(ret, "ftruncate on shm");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                  MAP_SHARED, MAGIC_SHM_FD, 0);
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  *(libipc_state*)stateptr = state;

  // Unmap, but don't unlink the shared memory
  ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  ipclog("State saved!\n");
}

bool is_valid_fd(int fd) {
  return __real_fcntl(fd, F_GETFD, /* kludge */ 0) >= 0;
}

void shm_state_restore() {
  // If we have memory to restore, it'll be in our magic FD!
  if (!is_valid_fd(MAGIC_SHM_FD))
    return;

  ipclog("Inherited ipc state FD, starting state restoration...\n");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                        MAP_SHARED, MAGIC_SHM_FD, 0);
  // If our FD is still open, the memory better still be there!
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  // Copy state from shared memory segment
  state = *(libipc_state*)stateptr;

  int ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  // Done with the shared segment, thank you!
  ret = __real_close(MAGIC_SHM_FD);
  UC(ret, "close shm");
  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink after close");

  ipclog("State restored!\n");
}

void shm_state_destroy() {
  // If we have memory to restore, it'll be in our magic FD!
  assert(is_valid_fd(MAGIC_SHM_FD));

  int ret = __real_close(MAGIC_SHM_FD);
  assert(ret == 0);

  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink");

  ipclog("Destroyed saved state!\n");
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Monteverdi
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdMultiResolutionPyramidWidget.h"
#include "ui_mvdMultiResolutionPyramidWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)
#include <cassert>
#include <cmath>

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdGui.h"

namespace mvd
{

/*
  TRANSLATOR mvd::MultiResolutionPyramidWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

char const * const
GDAL_RESAMPLING_NAMES[ otb::GDAL_RESAMPLING_COUNT ] =
{
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "None" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Nearest" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Gauss" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Cubic" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Average" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Mode" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Average Mag/Phase" ),
};

char const * const
GDAL_COMPRESSION_NAMES[ otb::GDAL_COMPRESSION_COUNT ] =
{
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "None" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "JPEG" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "LZW" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "PACKBITS" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "DEFLATE" ),
};

char const * const
GDAL_FORMAT_NAMES[ otb::GDAL_FORMAT_COUNT ] =
{
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "ERDAS" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "GeoTIFF" ),
};

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */
/*****************************************************************************/
MultiResolutionPyramidWidget
::MultiResolutionPyramidWidget( QWidget * parent, Qt::WindowFlags flags ) :
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::MultiResolutionPyramidWidget() )
{
  m_UI->setupUi( this );

  {
  QItemSelectionModel * ism = m_UI->resolutionsListView->selectionModel();

  m_UI->resolutionsListView->setModel(
    new QStandardItemModel( m_UI->resolutionsListView )
  );

  delete ism;
  ism = NULL;
  }

  AddItemsInto(
    m_UI->formatComboBox,
    "mvd::MultiResolutionPyramidWidget",
    GDAL_FORMAT_NAMES,
    otb::GDAL_FORMAT_COUNT
  );

  AddItemsInto(
    m_UI->algorithmComboBox,
    "mvd::MultiResolutionPyramidWidget",
    GDAL_RESAMPLING_NAMES,
    otb::GDAL_RESAMPLING_COUNT
  );

  AddItemsInto(
    m_UI->compressionComboBox,
    "mvd::MultiResolutionPyramidWidget",
    GDAL_COMPRESSION_NAMES,
    otb::GDAL_COMPRESSION_COUNT
  );

  m_UI->baseSpinBox->setValue( 2 );

  m_UI->levelsSpinBox->setValue( 1 );

  m_UI->sizeSpinBox->setValue( 2 );
}

/*****************************************************************************/
MultiResolutionPyramidWidget
::~MultiResolutionPyramidWidget()
{
  delete m_UI;
  m_UI = NULL;
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::ClearResolutions()
{
  QStandardItemModel * itemModel =
    qobject_cast< QStandardItemModel * >( m_UI->resolutionsListView->model() );

  assert( itemModel!=NULL );

  itemModel->clear();
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::SetBuilder( const otb::GDALOverviewsBuilder::Pointer & p )
{
  m_UI->formatComboBox->setCurrentIndex( otb::GDAL_FORMAT_GEOTIFF );
  m_UI->algorithmComboBox->setCurrentIndex( otb::GDAL_RESAMPLING_AVERAGE );
  m_UI->compressionComboBox->setCurrentIndex( otb::GDAL_COMPRESSION_NONE );

  {
  bool signalsBlocked = m_UI->baseSpinBox->blockSignals( true );

  m_UI->baseSpinBox->setValue( 2 );

  m_UI->baseSpinBox->blockSignals( signalsBlocked );
  }

  {
  bool signalsBlocked = m_UI->levelsSpinBox->blockSignals( true );

  m_UI->levelsSpinBox->setValue( 1 );

  m_UI->levelsSpinBox->blockSignals( signalsBlocked );
  }

  {
  bool signalsBlocked = m_UI->sizeSpinBox->blockSignals( true );

  m_UI->sizeSpinBox->setRange( 1, std::numeric_limits< int >::max() );
  m_UI->sizeSpinBox->setValue( 1 );

  m_UI->sizeSpinBox->blockSignals( signalsBlocked );
  }

  ClearResolutions();

  m_GDALOverviewsBuilder = p;

  if( p.IsNull() )
    return;

  assert( !m_GDALOverviewsBuilder.IsNull() );

  m_UI->formatComboBox->setCurrentIndex(
    m_GDALOverviewsBuilder->GetFormat()
  );

  m_UI->algorithmComboBox->setCurrentIndex(
    m_GDALOverviewsBuilder->GetResamplingMethod()
  );

  m_UI->compressionComboBox->setCurrentIndex(
    m_GDALOverviewsBuilder->GetCompressionMethod()
  );

  unsigned int size =
    std::min(
      m_GDALOverviewsBuilder->GetWidth(),
      m_GDALOverviewsBuilder->GetHeight()
    );

  {
  bool signalsBlocked = m_UI->baseSpinBox->blockSignals( true );

  m_UI->baseSpinBox->setRange( 2, size );
  m_UI->baseSpinBox->setValue( m_GDALOverviewsBuilder->GetResolutionFactor() );

  m_UI->baseSpinBox->blockSignals( signalsBlocked );
  }

  {
  bool signalsBlocked = m_UI->levelsSpinBox->blockSignals( true );

  m_UI->levelsSpinBox->setRange( 0, m_GDALOverviewsBuilder->CountResolutions() );
  m_UI->levelsSpinBox->setValue( m_GDALOverviewsBuilder->GetNbResolutions() );

  m_UI->levelsSpinBox->blockSignals( signalsBlocked );
  }

  {
  bool signalsBlocked = m_UI->sizeSpinBox->blockSignals( true );

  m_UI->sizeSpinBox->setRange( 1, size );

  assert(m_GDALOverviewsBuilder->CountResolutions() >= m_GDALOverviewsBuilder->GetNbResolutions() );

  // Force C++ implicit cast by declaring local variables to force compiler
  // to find correct std::pow() signature.
  //
  // It fixes compile-time:
  // error: call of pow(unsigned int, unsigned int) is ambiguous
  double rf = m_GDALOverviewsBuilder->GetResolutionFactor();

  int m =
    m_GDALOverviewsBuilder->CountResolutions() -
    m_GDALOverviewsBuilder->GetNbResolutions();

  m_UI->sizeSpinBox->setValue(
    static_cast< int >(
      std::pow( rf, m )
    )
  );

  m_UI->sizeSpinBox->blockSignals( signalsBlocked );
  }

  UpdateResolutions();
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::UpdateResolutions()
{
  assert( !m_GDALOverviewsBuilder.IsNull() );

  QStandardItemModel * itemModel =
    qobject_cast< QStandardItemModel * >( m_UI->resolutionsListView->model() );

  assert( itemModel!=NULL );

  otb::GDALOverviewsBuilder::SizeVector resolutions;

  m_GDALOverviewsBuilder->ListResolutions( resolutions );

  for( otb::GDALOverviewsBuilder::SizeVector::const_iterator it(
	 resolutions.begin()
       );
       it!=resolutions.end();
       ++ it )
    itemModel->appendRow(
      new QStandardItem(
	QString( "%1x%2" )
	.arg( ( *it )[ 0 ] )
	.arg( ( *it )[ 1 ] )
      )
    );
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::UpdateSize()
{
  assert( !m_GDALOverviewsBuilder.IsNull() );

  bool signalsBlocked = m_UI->sizeSpinBox->blockSignals( true );

  unsigned int count = m_GDALOverviewsBuilder->CountResolutions();

  // Force C++ implicit cast by declaring local variables to force compiler
  // to find correct std::pow() signature.
  //
  // It fixes compile-time:
  // error: call of pow(unsigned int, unsigned int) is ambiguous
  double rf = m_GDALOverviewsBuilder->GetResolutionFactor();
  int m     = count -
    std::min(
      m_GDALOverviewsBuilder->GetNbResolutions(),
      count
	  );

    m_UI->sizeSpinBox->setValue(
    static_cast< int >(
      std::pow( rf, m )
    )
  );

  m_UI->sizeSpinBox->blockSignals( signalsBlocked );
}

/*****************************************************************************/
/* SLOTS                                                                     */
/*****************************************************************************/
void
MultiResolutionPyramidWidget
::on_baseSpinBox_valueChanged( int value )
{
  // qDebug() << this << "::on_baseSpinBox_valueChanged(" << value << ")";

  ClearResolutions();

  if( m_GDALOverviewsBuilder.IsNull() )
    return;

  m_GDALOverviewsBuilder->SetResolutionFactor( value );

  m_UI->levelsSpinBox->setRange(
    0,
    m_GDALOverviewsBuilder->CountResolutions()
  );

  UpdateResolutions();

  UpdateSize();

  emit BaseValueChanged( value );
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::on_levelsSpinBox_valueChanged( int value )
{
  // qDebug() << this << "::on_levelsSpinBox_valueChanged(" << value << ")";

  ClearResolutions();

  if( m_GDALOverviewsBuilder.IsNull() )
    return;

  m_GDALOverviewsBuilder->SetNbResolutions( value );

  UpdateResolutions();

  UpdateSize();

  emit LevelsValueChanged( value );
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::on_sizeSpinBox_valueChanged( int value )
{
  // qDebug() << this << "::on_sizeSpinBox_valueChanged(" << value << ")";

  if( m_GDALOverviewsBuilder.IsNull() )
    return;

  unsigned int count =
    m_GDALOverviewsBuilder->CountResolutions(
      m_GDALOverviewsBuilder->GetResolutionFactor(),
      value
    );

  if( static_cast< unsigned int >( m_UI->levelsSpinBox->value() )<=count )
    return;

  {
  bool signalsBlocked = m_UI->levelsSpinBox->blockSignals( true );

  m_UI->levelsSpinBox->setValue( count );
  m_GDALOverviewsBuilder->SetNbResolutions( count );

  m_UI->levelsSpinBox->blockSignals( signalsBlocked );
  }

  ClearResolutions();

  UpdateResolutions();

  emit SizeValueChanged( value );
}

} // end namespace 'mvd'
<commit_msg>REFAC: Indented code.<commit_after>/*=========================================================================

  Program:   Monteverdi
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "mvdMultiResolutionPyramidWidget.h"
#include "ui_mvdMultiResolutionPyramidWidget.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)
#include <cassert>
#include <cmath>

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdGui.h"

namespace mvd
{

/*
  TRANSLATOR mvd::MultiResolutionPyramidWidget

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

char const * const
GDAL_RESAMPLING_NAMES[ otb::GDAL_RESAMPLING_COUNT ] =
{
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "None" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Nearest" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Gauss" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Cubic" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Average" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Mode" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "Average Mag/Phase" ),
};

char const * const
GDAL_COMPRESSION_NAMES[ otb::GDAL_COMPRESSION_COUNT ] =
{
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "None" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "JPEG" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "LZW" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "PACKBITS" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "DEFLATE" ),
};

char const * const
GDAL_FORMAT_NAMES[ otb::GDAL_FORMAT_COUNT ] =
{
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "ERDAS" ),
  QT_TRANSLATE_NOOP( "mvd::MultiResolutionPyramidWidget", "GeoTIFF" ),
};

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */
/*****************************************************************************/
MultiResolutionPyramidWidget
::MultiResolutionPyramidWidget( QWidget * parent, Qt::WindowFlags flags ) :
  QWidget( parent, flags ),
  m_UI( new mvd::Ui::MultiResolutionPyramidWidget() )
{
  m_UI->setupUi( this );

  {
  QItemSelectionModel * ism = m_UI->resolutionsListView->selectionModel();

  m_UI->resolutionsListView->setModel(
    new QStandardItemModel( m_UI->resolutionsListView )
  );

  delete ism;
  ism = NULL;
  }

  AddItemsInto(
    m_UI->formatComboBox,
    "mvd::MultiResolutionPyramidWidget",
    GDAL_FORMAT_NAMES,
    otb::GDAL_FORMAT_COUNT
  );

  AddItemsInto(
    m_UI->algorithmComboBox,
    "mvd::MultiResolutionPyramidWidget",
    GDAL_RESAMPLING_NAMES,
    otb::GDAL_RESAMPLING_COUNT
  );

  AddItemsInto(
    m_UI->compressionComboBox,
    "mvd::MultiResolutionPyramidWidget",
    GDAL_COMPRESSION_NAMES,
    otb::GDAL_COMPRESSION_COUNT
  );

  m_UI->baseSpinBox->setValue( 2 );

  m_UI->levelsSpinBox->setValue( 1 );

  m_UI->sizeSpinBox->setValue( 2 );
}

/*****************************************************************************/
MultiResolutionPyramidWidget
::~MultiResolutionPyramidWidget()
{
  delete m_UI;
  m_UI = NULL;
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::ClearResolutions()
{
  QStandardItemModel * itemModel =
    qobject_cast< QStandardItemModel * >( m_UI->resolutionsListView->model() );

  assert( itemModel!=NULL );

  itemModel->clear();
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::SetBuilder( const otb::GDALOverviewsBuilder::Pointer & p )
{
  m_UI->formatComboBox->setCurrentIndex( otb::GDAL_FORMAT_GEOTIFF );
  m_UI->algorithmComboBox->setCurrentIndex( otb::GDAL_RESAMPLING_AVERAGE );
  m_UI->compressionComboBox->setCurrentIndex( otb::GDAL_COMPRESSION_NONE );

  {
  bool signalsBlocked = m_UI->baseSpinBox->blockSignals( true );

  m_UI->baseSpinBox->setValue( 2 );

  m_UI->baseSpinBox->blockSignals( signalsBlocked );
  }

  {
  bool signalsBlocked = m_UI->levelsSpinBox->blockSignals( true );

  m_UI->levelsSpinBox->setValue( 1 );

  m_UI->levelsSpinBox->blockSignals( signalsBlocked );
  }

  {
  bool signalsBlocked = m_UI->sizeSpinBox->blockSignals( true );

  m_UI->sizeSpinBox->setRange( 1, std::numeric_limits< int >::max() );
  m_UI->sizeSpinBox->setValue( 1 );

  m_UI->sizeSpinBox->blockSignals( signalsBlocked );
  }

  ClearResolutions();

  m_GDALOverviewsBuilder = p;

  if( p.IsNull() )
    return;

  assert( !m_GDALOverviewsBuilder.IsNull() );

  m_UI->formatComboBox->setCurrentIndex(
    m_GDALOverviewsBuilder->GetFormat()
  );

  m_UI->algorithmComboBox->setCurrentIndex(
    m_GDALOverviewsBuilder->GetResamplingMethod()
  );

  m_UI->compressionComboBox->setCurrentIndex(
    m_GDALOverviewsBuilder->GetCompressionMethod()
  );

  unsigned int size =
    std::min(
      m_GDALOverviewsBuilder->GetWidth(),
      m_GDALOverviewsBuilder->GetHeight()
    );

  {
  bool signalsBlocked = m_UI->baseSpinBox->blockSignals( true );

  m_UI->baseSpinBox->setRange( 2, size );
  m_UI->baseSpinBox->setValue( m_GDALOverviewsBuilder->GetResolutionFactor() );

  m_UI->baseSpinBox->blockSignals( signalsBlocked );
  }

  {
  bool signalsBlocked = m_UI->levelsSpinBox->blockSignals( true );

  m_UI->levelsSpinBox->setRange( 0, m_GDALOverviewsBuilder->CountResolutions() );
  m_UI->levelsSpinBox->setValue( m_GDALOverviewsBuilder->GetNbResolutions() );

  m_UI->levelsSpinBox->blockSignals( signalsBlocked );
  }

  {
  bool signalsBlocked = m_UI->sizeSpinBox->blockSignals( true );

  m_UI->sizeSpinBox->setRange( 1, size );

  assert(m_GDALOverviewsBuilder->CountResolutions() >= m_GDALOverviewsBuilder->GetNbResolutions() );

  // Force C++ implicit cast by declaring local variables to force compiler
  // to find correct std::pow() signature.
  //
  // It fixes compile-time:
  // error: call of pow(unsigned int, unsigned int) is ambiguous
  double rf = m_GDALOverviewsBuilder->GetResolutionFactor();

  int m =
    m_GDALOverviewsBuilder->CountResolutions() -
    m_GDALOverviewsBuilder->GetNbResolutions();

  m_UI->sizeSpinBox->setValue(
    static_cast< int >(
      std::pow( rf, m )
    )
  );

  m_UI->sizeSpinBox->blockSignals( signalsBlocked );
  }

  UpdateResolutions();
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::UpdateResolutions()
{
  assert( !m_GDALOverviewsBuilder.IsNull() );

  QStandardItemModel * itemModel =
    qobject_cast< QStandardItemModel * >( m_UI->resolutionsListView->model() );

  assert( itemModel!=NULL );

  otb::GDALOverviewsBuilder::SizeVector resolutions;

  m_GDALOverviewsBuilder->ListResolutions( resolutions );

  for( otb::GDALOverviewsBuilder::SizeVector::const_iterator it(
	 resolutions.begin()
       );
       it!=resolutions.end();
       ++ it )
    itemModel->appendRow(
      new QStandardItem(
	QString( "%1x%2" )
	.arg( ( *it )[ 0 ] )
	.arg( ( *it )[ 1 ] )
      )
    );
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::UpdateSize()
{
  assert( !m_GDALOverviewsBuilder.IsNull() );

  bool signalsBlocked = m_UI->sizeSpinBox->blockSignals( true );

  unsigned int count = m_GDALOverviewsBuilder->CountResolutions();

  // Force C++ implicit cast by declaring local variables to force compiler
  // to find correct std::pow() signature.
  //
  // It fixes compile-time:
  // error: call of pow(unsigned int, unsigned int) is ambiguous
  double rf = m_GDALOverviewsBuilder->GetResolutionFactor();

  int m =
    count -
    std::min(
      m_GDALOverviewsBuilder->GetNbResolutions(),
      count
    );

  m_UI->sizeSpinBox->setValue(
    static_cast< int >(
      std::pow( rf, m )
    )
  );

  m_UI->sizeSpinBox->blockSignals( signalsBlocked );
}

/*****************************************************************************/
/* SLOTS                                                                     */
/*****************************************************************************/
void
MultiResolutionPyramidWidget
::on_baseSpinBox_valueChanged( int value )
{
  // qDebug() << this << "::on_baseSpinBox_valueChanged(" << value << ")";

  ClearResolutions();

  if( m_GDALOverviewsBuilder.IsNull() )
    return;

  m_GDALOverviewsBuilder->SetResolutionFactor( value );

  m_UI->levelsSpinBox->setRange(
    0,
    m_GDALOverviewsBuilder->CountResolutions()
  );

  UpdateResolutions();

  UpdateSize();

  emit BaseValueChanged( value );
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::on_levelsSpinBox_valueChanged( int value )
{
  // qDebug() << this << "::on_levelsSpinBox_valueChanged(" << value << ")";

  ClearResolutions();

  if( m_GDALOverviewsBuilder.IsNull() )
    return;

  m_GDALOverviewsBuilder->SetNbResolutions( value );

  UpdateResolutions();

  UpdateSize();

  emit LevelsValueChanged( value );
}

/*****************************************************************************/
void
MultiResolutionPyramidWidget
::on_sizeSpinBox_valueChanged( int value )
{
  // qDebug() << this << "::on_sizeSpinBox_valueChanged(" << value << ")";

  if( m_GDALOverviewsBuilder.IsNull() )
    return;

  unsigned int count =
    m_GDALOverviewsBuilder->CountResolutions(
      m_GDALOverviewsBuilder->GetResolutionFactor(),
      value
    );

  if( static_cast< unsigned int >( m_UI->levelsSpinBox->value() )<=count )
    return;

  {
  bool signalsBlocked = m_UI->levelsSpinBox->blockSignals( true );

  m_UI->levelsSpinBox->setValue( count );
  m_GDALOverviewsBuilder->SetNbResolutions( count );

  m_UI->levelsSpinBox->blockSignals( signalsBlocked );
  }

  ClearResolutions();

  UpdateResolutions();

  emit SizeValueChanged( value );
}

} // end namespace 'mvd'
<|endoftext|>


<commit_before><commit_msg>cppcheck: unreadVariable<commit_after><|endoftext|>


<commit_before>#include <Scenes/BenchmarkScene.hpp>

BenchmarkScene::BenchmarkScene(std::weak_ptr<Engine> &&engine)
	: AScene(std::move(engine))
{
}

BenchmarkScene::~BenchmarkScene(void)
{
}

void BenchmarkScene::initRendering()
{
	// A NETTOYER !!!!
	_renderManager = getInstance<gl::RenderManager>();
	_renderThread = (AGE::RenderThread*)(getInstance<AGE::Threads::Render>());

	assert(_renderManager != NULL && "Warning: No manager set for the camerasystem");

	auto res = _renderThread->getCommandQueue().safePriorityFutureEmplace<AGE::TQC::BoolFunction, bool>([&](){
		// create the shader
		key.shader = _renderManager->addShader(VERTEX_SHADER, FRAG_SHADER);
		// get from the shader the information key
		key.global_state = _renderManager->addUniformBlock();
		_renderManager->addShaderInterfaceBlock(key.shader, "global_state", key.global_state);
		key.view_matrix = _renderManager->addShaderUniform(key.shader, "view_matrix", glm::mat4(1.f));
		// bind the key on drawable info (material-transformation)
		_renderManager->bindMaterialToShader<gl::Color_diffuse>(key.shader, _renderManager->addShaderUniform(key.shader, "diffuse_color", glm::vec4(1.0f)));
		_renderManager->bindMaterialToShader<gl::Ratio_diffuse>(key.shader, _renderManager->addShaderUniform(key.shader, "diffuse_ratio", 1.0f));
		_renderManager->bindTransformationToShader(key.shader, _renderManager->addShaderUniform(key.shader, "model_matrix", glm::mat4(1.f)));
		// create renderpass and set it
		key.renderPass = _renderManager->addRenderPass(key.shader, glm::ivec4(0, 0, 800, 600));
		_renderManager->pushSetTestTaskRenderPass(key.renderPass, false, false, true);
		_renderManager->pushSetClearValueTaskRenderPass(key.renderPass, glm::vec4(0.25f, 0.25f, 0.25f, 1.0f));
		_renderManager->pushClearTaskRenderPass(key.renderPass, true, true, false);
		_renderManager->pushTargetRenderPass(key.renderPass, GL_COLOR_ATTACHMENT0);
		_renderManager->pushTargetRenderPass(key.renderPass, GL_COLOR_ATTACHMENT1);
		_renderManager->createBufferSamplableRenderPass(key.renderPass, GL_COLOR_ATTACHMENT0, GL_RGBA8);
		_renderManager->createBufferSamplableRenderPass(key.renderPass, GL_COLOR_ATTACHMENT1, GL_RGBA8);
		_renderManager->createBufferSamplableRenderPass(key.renderPass, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
		_renderManager->pushSetBlendStateTaskRenderPass(key.renderPass, 0, false);
		_renderManager->pushSetBlendStateTaskRenderPass(key.renderPass, 1, false);
		_renderManager->pushDrawTaskRenderBuffer(key.renderPass);
		// create renderOnscreen and set it
		key.renderOnScreen = _renderManager->addRenderOnScreen(glm::ivec4(0, 0, 800, 600));
		_renderManager->pushClearTaskRenderOnScreen(key.renderOnScreen, true, true, false);
		_renderManager->pushSetTestTaskRenderOnScreen(key.renderOnScreen, false, false, true);
		_renderManager->pushSetClearValueTaskRenderOnScreen(key.renderOnScreen, glm::vec4(0.25f, 0.25f, 0.25f, 1.0f));
		// create the pipeline and set it with both render element add before
		key.pipeline = _renderManager->addPipeline();
		_renderManager->pushRenderPassPipeline(key.pipeline, key.renderPass);
		_renderManager->pushRenderOnScreenPipeline(key.pipeline, key.renderOnScreen);
		_renderManager->branch(key.renderPass, key.renderOnScreen);
		return true;
	});
	assert(res.get());
}

bool BenchmarkScene::userStart()
{
	std::weak_ptr<AScene> weakOnThis = std::static_pointer_cast<AScene>(shared_from_this());
	getInstance<AGE::Threads::Prepare>()->setScene(weakOnThis);

#ifdef PHYSIC_SIMULATION
	addSystem<BulletDynamicSystem>(0);
	//		addSystem<CollisionAdder>(1);
	//		addSystem<CollisionCleaner>(1000);
#endif //!PHYSIC

#ifdef RENDERING_ACTIVATED

	auto &camerasystem = addSystem<CameraSystem>(70); // UPDATE CAMERA AND RENDER TO SCREEN
	auto &m = *getInstance<gl::RenderManager>();
	initRendering();

#ifdef SIMPLE_RENDERING
	addSystem<SimpleMeshRenderer>(80);
#else
#endif
#endif

#ifdef LIFETIME_ACTIVATED
	addSystem<LifetimeSystem>(2);
#endif //!LIFETIME_ACTIVATED

	srand(42);

#ifdef LOG_FRAMERATE
	_logFile.open("LogFile.log", std::ios::app);
	_logFile << "\n\nNew test in ";
#ifdef _DEBUG
	_logFile << "DEBUG . With :";
#else
	_logFile << "RELEASE . With :";
#endif
#ifdef LIFETIME_ACTIVATED
	_logFile << " Lifetime, ";
#endif
#ifdef COMPLEX_MESH
	_logFile << " Complex mesh, ";
#elif defined RENDERING_ACTIVATED
	_logFile << " Rendering, ";
#endif
#ifdef PHYSIC_SIMULATION
	_logFile << " Physics, ";
#endif
	_logFile << "\n";

#endif

#ifdef RENDERING_ACTIVATED

	auto camera = createEntity();
	GLOBAL_CAMERA = camera;
	auto cam = addComponent<Component::CameraComponent>(camera);

	auto screenSize = getInstance<AGE::RenderThread>()->getCommandQueue().safePriorityFutureEmplace<RendCtxCommand::GetScreenSize, glm::uvec2>().get();

	auto camLink = getLink(camera);
	camLink->setPosition(glm::vec3(0, 0, -10));

	auto plane = createEntity();
	auto link = getLink(plane);
	link->setPosition(glm::vec3(0, -10, 0));
	link->setScale(glm::vec3(100, 1, 100));
	auto mesh = addComponent<Component::MeshRenderer>(plane, getInstance<AGE::AssetsManager>()->loadMesh("cube/cube.sage"));
	mesh->setMaterial(getInstance<AGE::AssetsManager>()->loadMaterial(File("cube/cube.mage")));
#ifdef PHYSIC_SIMULATION
	auto rigidBody = addComponent<Component::RigidBody>(plane, 0.0f);
	rigidBody->setCollisionShape(weakOnThis, plane, Component::RigidBody::BOX);
	rigidBody->getBody().setFriction(0.8f);
#endif //PHYSIC_SIMULATION
#endif
	auto light = createEntity();
	auto lightData = addComponent<Component::PointLight>(light);
	lightData->set(1.0f, 1.0f, glm::vec3(1.0f), glm::vec4(1.0f));
	return true;
}

bool BenchmarkScene::userUpdate(double time)
{
	++_frameCounter;
	++_chunkFrame;
	_timeCounter += time;
	_chunkCounter += time;

	getLink(GLOBAL_CAMERA)->setOrientation(glm::rotate(getLink(GLOBAL_CAMERA)->getOrientation(), 100.0f * (float)time, glm::vec3(0, 1, 0)));

	if (_chunkCounter >= _maxChunk)
	{
		std::weak_ptr<AScene> weakOnThis = std::static_pointer_cast<AScene>(shared_from_this());
		for (auto i = 0; i < 30; ++i)
		{
			auto e = createEntity();

#ifdef LIFETIME_ACTIVATED
			addComponent<Component::Lifetime>(e, 5.0f);
#endif
#ifdef RENDERING_ACTIVATED

#ifndef COMPLEX_MESH
			Component::MeshRenderer *mesh;
			if (i % 4 == 0)
			{
				mesh = addComponent<Component::MeshRenderer>(e, getInstance<AGE::AssetsManager>()->loadMesh("ball/ball.sage"));
				mesh->setMaterial(getInstance<AGE::AssetsManager>()->loadMaterial(File("ball/ball.mage")));
				for (size_t index = 0; index < mesh->getMaterial()->datas.size(); ++index)
				{
					gl::Key<gl::Material> mat = mesh->getMaterial()->datas[index];
					getInstance<gl::RenderManager>()->materialManager.setMaterial<gl::Color_diffuse>(mat, glm::vec4((float)(rand() % 100) / 100.0f, (float)(rand() % 100) / 100.0f, (float)(rand() % 100) / 100.0f, 1));
					getInstance<gl::RenderManager>()->materialManager.setMaterial<gl::Ratio_diffuse>(mat, 1.0f);
				}
			}
			else
			{
				mesh = addComponent<Component::MeshRenderer>(e, getInstance<AGE::AssetsManager>()->loadMesh("cube/cube.sage"));
				mesh->setMaterial(getInstance<AGE::AssetsManager>()->loadMaterial(File("cube/cube.mage")));
				for (size_t index = 0; index < mesh->getMaterial()->datas.size(); ++index)
				{
					gl::Key<gl::Material> mat = mesh->getMaterial()->datas[index];
					getInstance<gl::RenderManager>()->materialManager.setMaterial<gl::Color_diffuse>(mat, glm::vec4(0, 0.0f, 1.f, 0.f));
					getInstance<gl::RenderManager>()->materialManager.setMaterial<gl::Ratio_diffuse>(mat, (float)(rand() % 100) / 100.0f);
				}
			}
#else
			auto mesh = addComponent<Component::MeshRenderer>(e, getInstance<AssetsManager>()->get<ObjFile>("obj__galileo"));
			mesh->setShader("MaterialBasic");
#endif

#endif

			auto link = getLink(e);
			link->setPosition(glm::vec3((rand() % 100) - 50, (rand() % 20) - 5, (rand() % 100) - 50));
			link->setOrientation(glm::quat(glm::vec3(rand() % 360, rand() % 360, rand() % 360)));
			link->setScale(glm::vec3(3.0f));

#ifdef PHYSIC_SIMULATION
			auto rigidBody = addComponent<Component::RigidBody>(e, 1.0f);
			//				rigidBody->setTransformation(link->getTransform());
			if (i % 4 == 0)
				rigidBody->setCollisionShape(weakOnThis, e, Component::RigidBody::SPHERE);
			else
				rigidBody->setCollisionShape(weakOnThis, e, Component::RigidBody::BOX);
			rigidBody->getBody().setFriction(0.5f);
			rigidBody->getBody().setRestitution(0.5f);
#endif

		}
#ifdef LOG_FRAMERATE

		_logFile << _chunkFrame << ", ";
		_chunkCounter = 0.0;
		_chunkFrame = 0;
	}
	if (_timeCounter >= _maxTime)
	{
		_logFile << std::endl << "Total frames : " << _frameCounter << " -- Entity created : " << this->getNumberOfEntities() << std::endl << "----------------" << std::endl;
		_logFile.close();
		return false;
	}
#endif

	auto renderThread = getInstance<AGE::RenderThread>();
	renderThread->getCommandQueue().safeEmplace<RendCtxCommand::RefreshInputs>();

	auto octree = getInstance<AGE::Threads::Prepare>();
	auto renderManager = getInstance<gl::RenderManager>();

	octree->getCommandQueue().emplace<AGE::PRTC::PrepareDrawLists>([=](AGE::DrawableCollection collection)
	{
		renderManager->setUniformBlock(key.global_state, 0, collection.projection);
		renderManager->setShaderUniform(key.shader, key.view_matrix, collection.transformation);
		renderManager->updatePipeline(key.pipeline, collection.drawables);
		renderManager->drawPipelines();
	});

	octree->getCommandQueue().releaseReadability();
	return true;
}<commit_msg>get out light for test<commit_after>#include <Scenes/BenchmarkScene.hpp>

BenchmarkScene::BenchmarkScene(std::weak_ptr<Engine> &&engine)
	: AScene(std::move(engine))
{
}

BenchmarkScene::~BenchmarkScene(void)
{
}

void BenchmarkScene::initRendering()
{
	// A NETTOYER !!!!
	_renderManager = getInstance<gl::RenderManager>();
	_renderThread = (AGE::RenderThread*)(getInstance<AGE::Threads::Render>());

	assert(_renderManager != NULL && "Warning: No manager set for the camerasystem");

	auto res = _renderThread->getCommandQueue().safePriorityFutureEmplace<AGE::TQC::BoolFunction, bool>([&](){
		// create the shader
		key.shader = _renderManager->addShader(VERTEX_SHADER, FRAG_SHADER);
		// get from the shader the information key
		key.global_state = _renderManager->addUniformBlock();
		_renderManager->addShaderInterfaceBlock(key.shader, "global_state", key.global_state);
		key.view_matrix = _renderManager->addShaderUniform(key.shader, "view_matrix", glm::mat4(1.f));
		// bind the key on drawable info (material-transformation)
		_renderManager->bindMaterialToShader<gl::Color_diffuse>(key.shader, _renderManager->addShaderUniform(key.shader, "diffuse_color", glm::vec4(1.0f)));
		_renderManager->bindMaterialToShader<gl::Ratio_diffuse>(key.shader, _renderManager->addShaderUniform(key.shader, "diffuse_ratio", 1.0f));
		_renderManager->bindTransformationToShader(key.shader, _renderManager->addShaderUniform(key.shader, "model_matrix", glm::mat4(1.f)));
		// create renderpass and set it
		key.renderPass = _renderManager->addRenderPass(key.shader, glm::ivec4(0, 0, 800, 600));
		_renderManager->pushSetTestTaskRenderPass(key.renderPass, false, false, true);
		_renderManager->pushSetClearValueTaskRenderPass(key.renderPass, glm::vec4(0.25f, 0.25f, 0.25f, 1.0f));
		_renderManager->pushClearTaskRenderPass(key.renderPass, true, true, false);
		_renderManager->pushTargetRenderPass(key.renderPass, GL_COLOR_ATTACHMENT0);
		_renderManager->pushTargetRenderPass(key.renderPass, GL_COLOR_ATTACHMENT1);
		_renderManager->createBufferSamplableRenderPass(key.renderPass, GL_COLOR_ATTACHMENT0, GL_RGBA8);
		_renderManager->createBufferSamplableRenderPass(key.renderPass, GL_COLOR_ATTACHMENT1, GL_RGBA8);
		_renderManager->createBufferSamplableRenderPass(key.renderPass, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
		_renderManager->pushSetBlendStateTaskRenderPass(key.renderPass, 0, false);
		_renderManager->pushSetBlendStateTaskRenderPass(key.renderPass, 1, false);
		_renderManager->pushDrawTaskRenderBuffer(key.renderPass);
		// create renderOnscreen and set it
		key.renderOnScreen = _renderManager->addRenderOnScreen(glm::ivec4(0, 0, 800, 600));
		_renderManager->pushClearTaskRenderOnScreen(key.renderOnScreen, true, true, false);
		_renderManager->pushSetTestTaskRenderOnScreen(key.renderOnScreen, false, false, true);
		_renderManager->pushSetClearValueTaskRenderOnScreen(key.renderOnScreen, glm::vec4(0.25f, 0.25f, 0.25f, 1.0f));
		// create the pipeline and set it with both render element add before
		key.pipeline = _renderManager->addPipeline();
		_renderManager->pushRenderPassPipeline(key.pipeline, key.renderPass);
		_renderManager->pushRenderOnScreenPipeline(key.pipeline, key.renderOnScreen);
		_renderManager->branch(key.renderPass, key.renderOnScreen);
		return true;
	});
	assert(res.get());
}

bool BenchmarkScene::userStart()
{
	std::weak_ptr<AScene> weakOnThis = std::static_pointer_cast<AScene>(shared_from_this());
	getInstance<AGE::Threads::Prepare>()->setScene(weakOnThis);

#ifdef PHYSIC_SIMULATION
	addSystem<BulletDynamicSystem>(0);
	//		addSystem<CollisionAdder>(1);
	//		addSystem<CollisionCleaner>(1000);
#endif //!PHYSIC

#ifdef RENDERING_ACTIVATED

	auto &camerasystem = addSystem<CameraSystem>(70); // UPDATE CAMERA AND RENDER TO SCREEN
	auto &m = *getInstance<gl::RenderManager>();
	initRendering();

#ifdef SIMPLE_RENDERING
	addSystem<SimpleMeshRenderer>(80);
#else
#endif
#endif

#ifdef LIFETIME_ACTIVATED
	addSystem<LifetimeSystem>(2);
#endif //!LIFETIME_ACTIVATED

	srand(42);

#ifdef LOG_FRAMERATE
	_logFile.open("LogFile.log", std::ios::app);
	_logFile << "\n\nNew test in ";
#ifdef _DEBUG
	_logFile << "DEBUG . With :";
#else
	_logFile << "RELEASE . With :";
#endif
#ifdef LIFETIME_ACTIVATED
	_logFile << " Lifetime, ";
#endif
#ifdef COMPLEX_MESH
	_logFile << " Complex mesh, ";
#elif defined RENDERING_ACTIVATED
	_logFile << " Rendering, ";
#endif
#ifdef PHYSIC_SIMULATION
	_logFile << " Physics, ";
#endif
	_logFile << "\n";

#endif

#ifdef RENDERING_ACTIVATED

	auto camera = createEntity();
	GLOBAL_CAMERA = camera;
	auto cam = addComponent<Component::CameraComponent>(camera);

	auto screenSize = getInstance<AGE::RenderThread>()->getCommandQueue().safePriorityFutureEmplace<RendCtxCommand::GetScreenSize, glm::uvec2>().get();

	auto camLink = getLink(camera);
	camLink->setPosition(glm::vec3(0, 0, -10));

	auto plane = createEntity();
	auto link = getLink(plane);
	link->setPosition(glm::vec3(0, -10, 0));
	link->setScale(glm::vec3(100, 1, 100));
	auto mesh = addComponent<Component::MeshRenderer>(plane, getInstance<AGE::AssetsManager>()->loadMesh("cube/cube.sage"));
	mesh->setMaterial(getInstance<AGE::AssetsManager>()->loadMaterial(File("cube/cube.mage")));
#ifdef PHYSIC_SIMULATION
	auto rigidBody = addComponent<Component::RigidBody>(plane, 0.0f);
	rigidBody->setCollisionShape(weakOnThis, plane, Component::RigidBody::BOX);
	rigidBody->getBody().setFriction(0.8f);
#endif //PHYSIC_SIMULATION
#endif
	//auto light = createEntity();
	//auto lightData = addComponent<Component::PointLight>(light);
	//lightData->set(1.0f, 1.0f, glm::vec3(1.0f), glm::vec4(1.0f));
	return true;
}

bool BenchmarkScene::userUpdate(double time)
{
	++_frameCounter;
	++_chunkFrame;
	_timeCounter += time;
	_chunkCounter += time;

	getLink(GLOBAL_CAMERA)->setOrientation(glm::rotate(getLink(GLOBAL_CAMERA)->getOrientation(), 100.0f * (float)time, glm::vec3(0, 1, 0)));

	if (_chunkCounter >= _maxChunk)
	{
		std::weak_ptr<AScene> weakOnThis = std::static_pointer_cast<AScene>(shared_from_this());
		for (auto i = 0; i < 30; ++i)
		{
			auto e = createEntity();

#ifdef LIFETIME_ACTIVATED
			addComponent<Component::Lifetime>(e, 5.0f);
#endif
#ifdef RENDERING_ACTIVATED

#ifndef COMPLEX_MESH
			Component::MeshRenderer *mesh;
			if (i % 4 == 0)
			{
				mesh = addComponent<Component::MeshRenderer>(e, getInstance<AGE::AssetsManager>()->loadMesh("ball/ball.sage"));
				mesh->setMaterial(getInstance<AGE::AssetsManager>()->loadMaterial(File("ball/ball.mage")));
				for (size_t index = 0; index < mesh->getMaterial()->datas.size(); ++index)
				{
					gl::Key<gl::Material> mat = mesh->getMaterial()->datas[index];
					getInstance<gl::RenderManager>()->materialManager.setMaterial<gl::Color_diffuse>(mat, glm::vec4((float)(rand() % 100) / 100.0f, (float)(rand() % 100) / 100.0f, (float)(rand() % 100) / 100.0f, 1));
					getInstance<gl::RenderManager>()->materialManager.setMaterial<gl::Ratio_diffuse>(mat, 1.0f);
				}
			}
			else
			{
				mesh = addComponent<Component::MeshRenderer>(e, getInstance<AGE::AssetsManager>()->loadMesh("cube/cube.sage"));
				mesh->setMaterial(getInstance<AGE::AssetsManager>()->loadMaterial(File("cube/cube.mage")));
				for (size_t index = 0; index < mesh->getMaterial()->datas.size(); ++index)
				{
					gl::Key<gl::Material> mat = mesh->getMaterial()->datas[index];
					getInstance<gl::RenderManager>()->materialManager.setMaterial<gl::Color_diffuse>(mat, glm::vec4(0, 0.0f, 1.f, 0.f));
					getInstance<gl::RenderManager>()->materialManager.setMaterial<gl::Ratio_diffuse>(mat, (float)(rand() % 100) / 100.0f);
				}
			}
#else
			auto mesh = addComponent<Component::MeshRenderer>(e, getInstance<AssetsManager>()->get<ObjFile>("obj__galileo"));
			mesh->setShader("MaterialBasic");
#endif

#endif

			auto link = getLink(e);
			link->setPosition(glm::vec3((rand() % 100) - 50, (rand() % 20) - 5, (rand() % 100) - 50));
			link->setOrientation(glm::quat(glm::vec3(rand() % 360, rand() % 360, rand() % 360)));
			link->setScale(glm::vec3(3.0f));

#ifdef PHYSIC_SIMULATION
			auto rigidBody = addComponent<Component::RigidBody>(e, 1.0f);
			//				rigidBody->setTransformation(link->getTransform());
			if (i % 4 == 0)
				rigidBody->setCollisionShape(weakOnThis, e, Component::RigidBody::SPHERE);
			else
				rigidBody->setCollisionShape(weakOnThis, e, Component::RigidBody::BOX);
			rigidBody->getBody().setFriction(0.5f);
			rigidBody->getBody().setRestitution(0.5f);
#endif

		}
#ifdef LOG_FRAMERATE

		_logFile << _chunkFrame << ", ";
		_chunkCounter = 0.0;
		_chunkFrame = 0;
	}
	if (_timeCounter >= _maxTime)
	{
		_logFile << std::endl << "Total frames : " << _frameCounter << " -- Entity created : " << this->getNumberOfEntities() << std::endl << "----------------" << std::endl;
		_logFile.close();
		return false;
	}
#endif

	auto renderThread = getInstance<AGE::RenderThread>();
	renderThread->getCommandQueue().safeEmplace<RendCtxCommand::RefreshInputs>();

	auto octree = getInstance<AGE::Threads::Prepare>();
	auto renderManager = getInstance<gl::RenderManager>();

	octree->getCommandQueue().emplace<AGE::PRTC::PrepareDrawLists>([=](AGE::DrawableCollection collection)
	{
		renderManager->setUniformBlock(key.global_state, 0, collection.projection);
		renderManager->setShaderUniform(key.shader, key.view_matrix, collection.transformation);
		renderManager->updatePipeline(key.pipeline, collection.drawables);
		renderManager->drawPipelines();
	});

	octree->getCommandQueue().releaseReadability();
	return true;
}<|endoftext|>


<commit_before>#ifndef <<<headerguard>>>
#define <<<headerguard>>>

#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stddef.h>
#include <sstream>
#include <iostream>

#include "ComponentEssentials.h"
#include "ComponentUtilities.h"

#include "FMI/fmi_import_context.h"
#include "FMI1/fmi1_import.h"
#include "FMI2/fmi2_import.h"
#include "JM/jm_portability.h"

void localLogger(jm_callbacks *c, jm_string module, jm_log_level_enu_t log_level, jm_string message) { }

namespace hopsan {

class <<<className>>> : public ComponentQ
{

private:
    //Node data pointers
    <<<localvars>>>

    fmi2_callback_functions_t callBackFunctions;
    jm_callbacks callbacks;
    fmi_import_context_t* context;
    fmi_version_enu_t version;
    jm_status_enu_t status;
    fmi2_status_t fmistatus;
    int k;

    fmi2_import_t* fmu;

public:
    static Component *Creator()
    {
        return new <<<className>>>();
    }

    void configure()
    {
        //Add constants
        <<<addconstants>>>

        //Add input variables
        <<<addinputs>>>

        //Add output variables
        <<<addoutputs>>>

        //Add ports
        <<<addports>>>
    }

    void initialize()
    {
        <<<setnodedatapointers>>>

        addInfoMessage("Initializing FMU 2.0 import");

        const char* FMUPath = "<<<fmupath>>>";
        const char* tmpPath = "<<<temppath>>>";

        callbacks.malloc = malloc;
        callbacks.calloc = calloc;
        callbacks.realloc = realloc;
        callbacks.free = free;
        callbacks.logger = localLogger;
        callbacks.log_level = jm_log_level_debug;
        callbacks.context = 0;

        context = fmi_import_allocate_context(&callbacks);

        version = fmi_import_get_fmi_version(context, FMUPath, tmpPath);

        if(version != fmi_version_2_0_enu)
        {
            addErrorMessage("The code only supports version 2.0\n");
            stopSimulation();
            return;
        }

        fmu = fmi2_import_parse_xml(context, tmpPath, 0);

        if(!fmu)
        {
            addErrorMessage("Error parsing XML, exiting\n");
            stopSimulation();
            return;
        }

        if(fmi2_import_get_fmu_kind(fmu) == fmi2_fmu_kind_me)
        {
            addErrorMessage("Only CS 2.0 is supported by this code\n");
            stopSimulation();
             return;
        }

        callBackFunctions.logger = fmi2_log_forwarding;
        callBackFunctions.allocateMemory = calloc;
        callBackFunctions.freeMemory = free;
        callBackFunctions.componentEnvironment = fmu;

        status = fmi2_import_create_dllfmu(fmu, fmi2_fmu_kind_cs, &callBackFunctions);
        if (status == jm_status_error)
        {
            std::stringstream ss;
            ss << "Could not create the DLL loading mechanism(C-API) (error: " << fmi2_import_get_last_error(fmu) << ").";
            addErrorMessage(ss.str().c_str());
            stopSimulation();
            return;
        }

        //Instantiate FMU
        fmi2_string_t instanceName = "Test CS model instance";
        fmi2_string_t fmuLocation = "";
        fmi2_boolean_t visible = fmi2_false;
        jm_status_enu_t jmstatus = fmi2_import_instantiate(fmu, instanceName, fmi2_cosimulation, fmuLocation, visible);
        if (jmstatus == jm_status_error)
        {
            addErrorMessage("fmi2_import_instantiate() failed!");
            stopSimulation();
            return;
        }

        //Set parameters
        fmi2_value_reference_t vr;
  >>>setpars>>>        vr = <<<vr>>>;
          fmistatus = <<<setparfunction>>>(fmu, &vr, 1, <<<var>>>);
        <<<setpars<<<

        //Setup experiment
        fmi2_real_t relativeTol = 1e-4;
        fmistatus = fmi2_import_setup_experiment(fmu, fmi2_true, relativeTol, mTime, fmi2_false, 10);
        if(fmistatus != fmi2_status_ok)
        {
            addErrorMessage("fmi2_import_setup_experiment() failed!");
            stopSimulation();
            return;
        }

        //Enter initialization mode
        fmistatus = fmi2_import_enter_initialization_mode(fmu);
        if(fmistatus != fmi2_status_ok)
        {
            addErrorMessage("fmi2_import_enter_initialization_mode() failed!");
            stopSimulation();
            return;
        }

        //Exit initialization mode
        fmistatus = fmi2_import_exit_initialization_mode(fmu);
        if(fmistatus != fmi2_status_ok)
        {
            addErrorMessage("fmi2_import_exit_initialization_mode() failed!");
            stopSimulation();
            return;
        }
    }

    void simulateOneTimestep()
    {
        //Read inputs
        fmi2_value_reference_t vr;
        double value;
>>>readvars>>>        vr = <<<vr>>>;
        value = (*<<<var>>>);
        fmistatus = fmi2_import_set_real(fmu, &vr, 1, &value);
        <<<readvars<<<

        fmistatus = fmi2_import_do_step(fmu, mTime, mTimestep, true);
        if (fmistatus != fmi2_status_ok)
        {
            stopSimulation("fmi2_import_do_Step did NOT return status fmi2_Status_ok");
            return;
        }

        //Write outputs
>>>writevars>>>        vr = <<<vr>>>;
        fmistatus = fmi2_import_get_real(fmu, &vr, 1, &value);
        (*<<<var>>>) = value;
        <<<writevars<<<
    }

    void finalize()
    {
        fmistatus = fmi2_import_terminate(fmu);

        fmi2_import_free_instance(fmu);

        fmi2_import_destroy_dllfmu(fmu);

        fmi2_import_free(fmu);
        fmi_import_free_context(context);
    }
};
}

#endif
<commit_msg>Prevent crash if fmu finilize is called when init has not been called (using uninitialized pointers)<commit_after>#ifndef <<<headerguard>>>
#define <<<headerguard>>>

#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stddef.h>
#include <sstream>
#include <iostream>

#include "ComponentEssentials.h"
#include "ComponentUtilities.h"

#include "FMI/fmi_import_context.h"
#include "FMI1/fmi1_import.h"
#include "FMI2/fmi2_import.h"
#include "JM/jm_portability.h"

void localLogger(jm_callbacks *c, jm_string module, jm_log_level_enu_t log_level, jm_string message) { }

namespace hopsan {

class <<<className>>> : public ComponentQ
{

private:
    //Node data pointers
    <<<localvars>>>

    fmi2_callback_functions_t callBackFunctions;
    jm_callbacks callbacks;
    fmi_import_context_t* context;
    fmi_version_enu_t version;
    jm_status_enu_t status;
    fmi2_status_t fmistatus;
    int k;

    fmi2_import_t* fmu;

public:
    static Component *Creator()
    {
        return new <<<className>>>();
    }

    void configure()
    {
        //Add constants
        <<<addconstants>>>

        //Add input variables
        <<<addinputs>>>

        //Add output variables
        <<<addoutputs>>>

        //Add ports
        <<<addports>>>

        //Init fmu pointers
        context = 0;
        fmu = 0;
    }

    void initialize()
    {
        <<<setnodedatapointers>>>

        addInfoMessage("Initializing FMU 2.0 import");

        const char* FMUPath = "<<<fmupath>>>";
        const char* tmpPath = "<<<temppath>>>";

        callbacks.malloc = malloc;
        callbacks.calloc = calloc;
        callbacks.realloc = realloc;
        callbacks.free = free;
        callbacks.logger = localLogger;
        callbacks.log_level = jm_log_level_debug;
        callbacks.context = 0;

        context = fmi_import_allocate_context(&callbacks);

        version = fmi_import_get_fmi_version(context, FMUPath, tmpPath);

        if(version != fmi_version_2_0_enu)
        {
            addErrorMessage("The code only supports version 2.0\n");
            stopSimulation();
            return;
        }

        fmu = fmi2_import_parse_xml(context, tmpPath, 0);

        if(!fmu)
        {
            addErrorMessage("Error parsing XML, exiting\n");
            stopSimulation();
            return;
        }

        if(fmi2_import_get_fmu_kind(fmu) == fmi2_fmu_kind_me)
        {
            addErrorMessage("Only CS 2.0 is supported by this code\n");
            stopSimulation();
             return;
        }

        callBackFunctions.logger = fmi2_log_forwarding;
        callBackFunctions.allocateMemory = calloc;
        callBackFunctions.freeMemory = free;
        callBackFunctions.componentEnvironment = fmu;

        status = fmi2_import_create_dllfmu(fmu, fmi2_fmu_kind_cs, &callBackFunctions);
        if (status == jm_status_error)
        {
            std::stringstream ss;
            ss << "Could not create the DLL loading mechanism(C-API) (error: " << fmi2_import_get_last_error(fmu) << ").";
            addErrorMessage(ss.str().c_str());
            stopSimulation();
            return;
        }

        //Instantiate FMU
        fmi2_string_t instanceName = "Test CS model instance";
        fmi2_string_t fmuLocation = "";
        fmi2_boolean_t visible = fmi2_false;
        jm_status_enu_t jmstatus = fmi2_import_instantiate(fmu, instanceName, fmi2_cosimulation, fmuLocation, visible);
        if (jmstatus == jm_status_error)
        {
            addErrorMessage("fmi2_import_instantiate() failed!");
            stopSimulation();
            return;
        }

        //Set parameters
        fmi2_value_reference_t vr;
  >>>setpars>>>        vr = <<<vr>>>;
          fmistatus = <<<setparfunction>>>(fmu, &vr, 1, <<<var>>>);
        <<<setpars<<<

        //Setup experiment
        fmi2_real_t relativeTol = 1e-4;
        fmistatus = fmi2_import_setup_experiment(fmu, fmi2_true, relativeTol, mTime, fmi2_false, 10);
        if(fmistatus != fmi2_status_ok)
        {
            addErrorMessage("fmi2_import_setup_experiment() failed!");
            stopSimulation();
            return;
        }

        //Enter initialization mode
        fmistatus = fmi2_import_enter_initialization_mode(fmu);
        if(fmistatus != fmi2_status_ok)
        {
            addErrorMessage("fmi2_import_enter_initialization_mode() failed!");
            stopSimulation();
            return;
        }

        //Exit initialization mode
        fmistatus = fmi2_import_exit_initialization_mode(fmu);
        if(fmistatus != fmi2_status_ok)
        {
            addErrorMessage("fmi2_import_exit_initialization_mode() failed!");
            stopSimulation();
            return;
        }
    }

    void simulateOneTimestep()
    {
        //Read inputs
        fmi2_value_reference_t vr;
        double value;
>>>readvars>>>        vr = <<<vr>>>;
        value = (*<<<var>>>);
        fmistatus = fmi2_import_set_real(fmu, &vr, 1, &value);
        <<<readvars<<<

        fmistatus = fmi2_import_do_step(fmu, mTime, mTimestep, true);
        if (fmistatus != fmi2_status_ok)
        {
            stopSimulation("fmi2_import_do_Step did NOT return status fmi2_Status_ok");
            return;
        }

        //Write outputs
>>>writevars>>>        vr = <<<vr>>>;
        fmistatus = fmi2_import_get_real(fmu, &vr, 1, &value);
        (*<<<var>>>) = value;
        <<<writevars<<<
    }

    void finalize()
    {
        if (fmu)
        {
            fmistatus = fmi2_import_terminate(fmu);

            fmi2_import_free_instance(fmu);

            fmi2_import_destroy_dllfmu(fmu);

            fmi2_import_free(fmu);
            fmu = 0;
        }

        if (context)
        {
            fmi_import_free_context(context);
            context = 0;
        }
    }
};
}

#endif
<|endoftext|>


<commit_before>/**
 *  @copyright Copyright 2016 The J-PET Framework 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 find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetTaskChainExecutorTest.cpp
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetTaskChainExecutorTest
#include <boost/test/unit_test.hpp>
#include "../JPetTaskChainExecutor/JPetTaskChainExecutor.h"
#include "../JPetOptionsGenerator/JPetOptionsGenerator.h"
#include "../JPetOptionsGenerator/JPetOptionsGeneratorTools.h"
#include "../JPetTaskIO/JPetTaskIO.h"
#include "../JPetUserTask/JPetUserTask.h"
#include "../JPetLoggerInclude.h"

class TestTask: public JPetUserTask
{
public:
  TestTask(const char* name = ""): JPetUserTask(name) {}
  bool init() override
  {
    return true;
  }
  bool exec() override
  {
    fOutputEvents = dynamic_cast<JPetTimeWindow*>(fEvent);
    return true;
  }
  bool terminate() override
  {
    return true;
  }

};

BOOST_AUTO_TEST_SUITE(JPetTaskChainExecutorTestSuite)

BOOST_AUTO_TEST_CASE(test1)
{
  std::vector<jpet_options_tools::OptsStrAny> opts;
  auto opt = jpet_options_generator_tools::getDefaultOptions();
  opt["inputFile_std::string"] = std::string("unitTestData/JPetTaskChainExecutorTest/dabc_17025151847.unk.evt.root");
  opt["inputFileType_std::string"] = std::string("root");
  opt["outputFile_std::string"] = std::string("JPetTaskChainExecutorTest1.root");
  opts.push_back(opt);
  auto taskGenerator1 = []() {
    return new JPetTaskIO("test1");
  };
  TaskGeneratorChain* chain =  new TaskGeneratorChain;
  chain->push_back(taskGenerator1);

  JPetTaskChainExecutor taskExecutor(chain, 1, opts);
  BOOST_REQUIRE(taskExecutor.process());
  delete chain;
}

BOOST_AUTO_TEST_CASE(test2)
{
  std::vector<jpet_options_tools::OptsStrAny> opts;
  auto opt = jpet_options_generator_tools::getDefaultOptions();
  opt["firstEvent_int"] = 0;
  opt["lastEvent_int"] = 10;
  opt["inputFile_std::string"] = std::string("unitTestData/JPetTaskChainExecutorTest/dabc_17025151847.unk.evt.root");
  opt["inputFileType_std::string"] = std::string("root");
  opt["outputFile_std::string"] = std::string("JPetTaskChainExecutorTest2Chain1.root");
  opts.push_back(opt);
  opt["outputFile_std::string"] = std::string("JPetTaskChainExecutorTest2Chain2.root");
  opts.push_back(opt);

  auto taskGenerator1 = []() {
    auto taskIO =  new JPetTaskIO("TaskA");
    taskIO->addSubTask(std::unique_ptr<TestTask>(new TestTask("test2 TestTask1")));
    taskIO->addSubTask(std::unique_ptr<TestTask>(new TestTask("test2 TestTask2")));
    return taskIO;
  };
  auto taskGenerator2 = []() {
    auto taskIO =  new JPetTaskIO("TaskB");
    taskIO->addSubTask(std::unique_ptr<TestTask>(new TestTask("test2 TestTask3")));
    return taskIO;
  };
  TaskGeneratorChain* chain =  new TaskGeneratorChain;
  chain->push_back(taskGenerator1);
  chain->push_back(taskGenerator2);

  BOOST_REQUIRE_EQUAL(chain->size(), 2u);
  JPetTaskChainExecutor taskExecutor(chain, 1, opts);
  BOOST_REQUIRE(taskExecutor.process());
  delete chain;
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fix test TaskIO with no subtasks<commit_after>/**
 *  @copyright Copyright 2016 The J-PET Framework 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 find a copy of the License in the LICENCE file.
 *
 *  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.
 *
 *  @file JPetTaskChainExecutorTest.cpp
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetTaskChainExecutorTest
#include <boost/test/unit_test.hpp>
#include "../JPetTaskChainExecutor/JPetTaskChainExecutor.h"
#include "../JPetOptionsGenerator/JPetOptionsGenerator.h"
#include "../JPetOptionsGenerator/JPetOptionsGeneratorTools.h"
#include "../JPetTaskIO/JPetTaskIO.h"
#include "../JPetUserTask/JPetUserTask.h"
#include "../JPetLoggerInclude.h"

class TestTask: public JPetUserTask
{
public:
  TestTask(const char* name = ""): JPetUserTask(name) {}
  bool init() override
  {
    return true;
  }
  bool exec() override
  {
    fOutputEvents = dynamic_cast<JPetTimeWindow*>(fEvent);
    return true;
  }
  bool terminate() override
  {
    return true;
  }

};

BOOST_AUTO_TEST_SUITE(JPetTaskChainExecutorTestSuite)

BOOST_AUTO_TEST_CASE(test1)
{
  std::vector<jpet_options_tools::OptsStrAny> opts;
  auto opt = jpet_options_generator_tools::getDefaultOptions();
  opt["inputFile_std::string"] = std::string("unitTestData/JPetTaskChainExecutorTest/dabc_17025151847.unk.evt.root");
  opt["inputFileType_std::string"] = std::string("root");
  opt["outputFile_std::string"] = std::string("JPetTaskChainExecutorTest1.root");
  opts.push_back(opt);
  auto taskGenerator1 = []() {
    return new JPetTaskIO("test1");
  };
  TaskGeneratorChain* chain =  new TaskGeneratorChain;
  chain->push_back(taskGenerator1);

  JPetTaskChainExecutor taskExecutor(chain, 1, opts);
  BOOST_REQUIRE(!taskExecutor.process()); //TaskIO with no subtask is no allowed
  delete chain;
}

BOOST_AUTO_TEST_CASE(test2)
{
  std::vector<jpet_options_tools::OptsStrAny> opts;
  auto opt = jpet_options_generator_tools::getDefaultOptions();
  opt["firstEvent_int"] = 0;
  opt["lastEvent_int"] = 10;
  opt["inputFile_std::string"] = std::string("unitTestData/JPetTaskChainExecutorTest/dabc_17025151847.unk.evt.root");
  opt["inputFileType_std::string"] = std::string("root");
  opt["outputFile_std::string"] = std::string("JPetTaskChainExecutorTest2Chain1.root");
  opts.push_back(opt);
  opt["outputFile_std::string"] = std::string("JPetTaskChainExecutorTest2Chain2.root");
  opts.push_back(opt);

  auto taskGenerator1 = []() {
    auto taskIO =  new JPetTaskIO("TaskA");
    taskIO->addSubTask(std::unique_ptr<TestTask>(new TestTask("test2 TestTask1")));
    taskIO->addSubTask(std::unique_ptr<TestTask>(new TestTask("test2 TestTask2")));
    return taskIO;
  };
  auto taskGenerator2 = []() {
    auto taskIO =  new JPetTaskIO("TaskB");
    taskIO->addSubTask(std::unique_ptr<TestTask>(new TestTask("test2 TestTask3")));
    return taskIO;
  };
  TaskGeneratorChain* chain =  new TaskGeneratorChain;
  chain->push_back(taskGenerator1);
  chain->push_back(taskGenerator2);

  BOOST_REQUIRE_EQUAL(chain->size(), 2u);
  JPetTaskChainExecutor taskExecutor(chain, 1, opts);
  BOOST_REQUIRE(taskExecutor.process());
  delete chain;
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/**
 * @file mean_shift_main.cpp
 * @author Shangtong Zhang
 *
 * Executable for running Mean Shift
 */

#include <mlpack/core.hpp>
#include <mlpack/core/kernels/gaussian_kernel.hpp>
#include "mean_shift.hpp"

using namespace mlpack;
using namespace mlpack::meanshift;
using namespace mlpack::kernel;
using namespace std;

// Define parameters for the executable.
PROGRAM_INFO("Mean Shift Clustering", "This program performs mean shift clustering "
             "on the given dataset, storing the learned cluster assignments either as "
             "a column of labels in the file containing the input dataset or in a "
             "separate file. "
             "\n\n");

// Required options.
PARAM_STRING_REQ("inputFile", "Input dataset to perform clustering on.", "i");

// Output options.
PARAM_FLAG("in_place", "If specified, a column containing the learned cluster "
           "assignments will be added to the input dataset file.  In this case, "
           "--outputFile is overridden.", "P");
PARAM_STRING("output_file", "File to write output labels or labeled data to.",
             "o", "");
PARAM_STRING("centroid_file", "If specified, the centroids of each cluster will"
             " be written to the given file.", "C", "");

// Mean Shift configuration options.
PARAM_INT("max_iterations", "Maximum number of iterations before Mean Shift "
          "terminates.", "m", 1000);

PARAM_DOUBLE("bandwidth", "bandwidth of Gaussian kernel ", "b", 1.0);
PARAM_DOUBLE("radius", "If distance of two centroids is less than radius "
             "one will be removed. "
             "If it isn't positive, an estimation will be given. "
             "Points with distance to current centroid less than radius "
             "will be used to calculate new centroid. ", "r", 0);

int main(int argc, char** argv)
{
  CLI::ParseCommandLine(argc, argv);

  const string inputFile = CLI::GetParam<string>("inputFile");
  const double radius = CLI::GetParam<double>("radius");
  const double bandwidth = CLI::GetParam<double>("bandwidth");
  const int maxIterations = CLI::GetParam<int>("max_iterations");

  if (maxIterations < 0)
  {
    Log::Fatal << "Invalid value for maximum iterations (" << maxIterations <<
        ")! Must be greater than or equal to 0." << endl;
  }

  // Make sure we have an output file if we're not doing the work in-place.
  if (!CLI::HasParam("in_place") && !CLI::HasParam("output_file") &&
      !CLI::HasParam("centroid_file"))
  {
    Log::Warn << "--output_file, --in_place, and --centroid_file are not set; "
        << "no results will be saved." << endl;
  }

  arma::mat dataset;
  data::Load(inputFile, dataset, true); // Fatal upon failure.
  arma::mat centroids;
  arma::Col<size_t> assignments;

  GaussianKernel kernel(bandwidth);

  MeanShift<> meanShift(radius, maxIterations, kernel);

  Timer::Start("clustering");
  Log::Info << "Performing mean shift clustering..." << endl;
  meanShift.Cluster(dataset, assignments, centroids);
  Timer::Stop("clustering");

  Log::Info << "Found " << centroids.n_cols << " centroids." << endl;

  if (CLI::HasParam("in_place"))
  {
    // Add the column of assignments to the dataset; but we have to convert them
    // to type double first.
    arma::vec converted(assignments.n_elem);
    for (size_t i = 0; i < assignments.n_elem; i++)
      converted(i) = (double) assignments(i);

    dataset.insert_rows(dataset.n_rows, trans(converted));

    // Save the dataset.
    data::Save(inputFile, dataset);
  }
  else
  {
    // Convert the assignments to doubles.
    arma::vec converted(assignments.n_elem);
    for (size_t i = 0; i < assignments.n_elem; i++)
      converted(i) = (double) assignments(i);

    dataset.insert_rows(dataset.n_rows, trans(converted));

    // Now save, in the different file.
    string outputFile = CLI::GetParam<string>("output_file");
    data::Save(outputFile, dataset);
  }

  // Should we write the centroids to a file?
  if (CLI::HasParam("centroid_file"))
    data::Save(CLI::GetParam<std::string>("centroid_file"), centroids);
}
<commit_msg>delete obsolete paramater<commit_after>/**
 * @file mean_shift_main.cpp
 * @author Shangtong Zhang
 *
 * Executable for running Mean Shift
 */

#include <mlpack/core.hpp>
#include <mlpack/core/kernels/gaussian_kernel.hpp>
#include "mean_shift.hpp"

using namespace mlpack;
using namespace mlpack::meanshift;
using namespace mlpack::kernel;
using namespace std;

// Define parameters for the executable.
PROGRAM_INFO("Mean Shift Clustering", "This program performs mean shift clustering "
             "on the given dataset, storing the learned cluster assignments either as "
             "a column of labels in the file containing the input dataset or in a "
             "separate file. "
             "\n\n");

// Required options.
PARAM_STRING_REQ("inputFile", "Input dataset to perform clustering on.", "i");

// Output options.
PARAM_FLAG("in_place", "If specified, a column containing the learned cluster "
           "assignments will be added to the input dataset file.  In this case, "
           "--outputFile is overridden.", "P");
PARAM_STRING("output_file", "File to write output labels or labeled data to.",
             "o", "");
PARAM_STRING("centroid_file", "If specified, the centroids of each cluster will"
             " be written to the given file.", "C", "");

// Mean Shift configuration options.
PARAM_INT("max_iterations", "Maximum number of iterations before Mean Shift "
          "terminates.", "m", 1000);

PARAM_DOUBLE("bandwidth", "bandwidth of Gaussian kernel ", "b", 1.0);
PARAM_DOUBLE("radius", "If distance of two centroids is less than radius "
             "one will be removed. "
             "If it isn't positive, an estimation will be given. "
             "Points with distance to current centroid less than radius "
             "will be used to calculate new centroid. ", "r", 0);

int main(int argc, char** argv)
{
  CLI::ParseCommandLine(argc, argv);

  const string inputFile = CLI::GetParam<string>("inputFile");
  const double radius = CLI::GetParam<double>("radius");
  const int maxIterations = CLI::GetParam<int>("max_iterations");

  if (maxIterations < 0)
  {
    Log::Fatal << "Invalid value for maximum iterations (" << maxIterations <<
        ")! Must be greater than or equal to 0." << endl;
  }

  // Make sure we have an output file if we're not doing the work in-place.
  if (!CLI::HasParam("in_place") && !CLI::HasParam("output_file") &&
      !CLI::HasParam("centroid_file"))
  {
    Log::Warn << "--output_file, --in_place, and --centroid_file are not set; "
        << "no results will be saved." << endl;
  }

  arma::mat dataset;
  data::Load(inputFile, dataset, true); // Fatal upon failure.
  arma::mat centroids;
  arma::Col<size_t> assignments;

  GaussianKernel kernel(bandwidth);

  MeanShift<> meanShift(radius, maxIterations, kernel);

  Timer::Start("clustering");
  Log::Info << "Performing mean shift clustering..." << endl;
  meanShift.Cluster(dataset, assignments, centroids);
  Timer::Stop("clustering");

  Log::Info << "Found " << centroids.n_cols << " centroids." << endl;

  if (CLI::HasParam("in_place"))
  {
    // Add the column of assignments to the dataset; but we have to convert them
    // to type double first.
    arma::vec converted(assignments.n_elem);
    for (size_t i = 0; i < assignments.n_elem; i++)
      converted(i) = (double) assignments(i);

    dataset.insert_rows(dataset.n_rows, trans(converted));

    // Save the dataset.
    data::Save(inputFile, dataset);
  }
  else
  {
    // Convert the assignments to doubles.
    arma::vec converted(assignments.n_elem);
    for (size_t i = 0; i < assignments.n_elem; i++)
      converted(i) = (double) assignments(i);

    dataset.insert_rows(dataset.n_rows, trans(converted));

    // Now save, in the different file.
    string outputFile = CLI::GetParam<string>("output_file");
    data::Save(outputFile, dataset);
  }

  // Should we write the centroids to a file?
  if (CLI::HasParam("centroid_file"))
    data::Save(CLI::GetParam<std::string>("centroid_file"), centroids);
}
<|endoftext|>