<commit_before>// Copyright 2015 Charles D. Aylward
//
// 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.
//
// A (possibly updated) copy of of this software is available at
// https://github.com/cdaylward/nosecone

#include <cerrno>
#include <csignal>
#include <cstdlib>
#include <vector>

#include <dirent.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/mount.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
// TODO decide on term attrs
#include <termios.h>
#include <unistd.h>

#include "appc/image/image.h"
#include "appc/os/mkdir.h"
#include "appc/util/status.h"
#include "appc/util/option.h"

#include "nosecone/errno.h"
#include "nosecone/executor/container/linux.h"

#ifdef __linux__
#include <sys/prctl.h>

namespace nosecone {
namespace executor {
namespace container {
namespace linux {

inline char** c_env_array(const std::map<std::string, std::string>& environment) {
  const size_t env_size = environment.size() + 1;
  char** environment_array = static_cast<char**>(calloc(env_size, sizeof(char*)));
  off_t i = 0;
  for (const auto& pair : environment) {
    const auto assignment = pair.first + "=" + pair.second;
    environment_array[i++] = strdup(const_cast<char*>(assignment.c_str()));
  }
  environment_array[i] = NULL;
  return environment_array;
}

inline char** c_array(const std::vector<std::string>& strings) {
  const size_t array_size = strings.size() + 1;
  char** array = static_cast<char**>(calloc(array_size, sizeof(char*)));
  off_t i = 0;
  for (const auto& str : strings) {
    array[i++] = strdup(const_cast<char*>(str.c_str()));
  }
  array[i] = NULL;
  return array;
}

inline char** c_array(const appc::schema::Exec& exec) {
  std::vector<std::string> strings{};
  for (const auto& arg : exec) {
    strings.push_back(arg.value);
  }
  return c_array(strings);
}

Status Container::Impl::create_rootfs() {
  const auto made_container_root = appc::os::mkdir(rootfs_path, 0755, true);
  if (!made_container_root) {
    std::string where{"Could not create directory for container: "};
    return Error(where + made_container_root.message);
  }

  for (auto& image : images) {
    auto extracted = image.archive.extract_rootfs_to(rootfs_path);
    if (!extracted) {
      std::string where{"Could not create root file system for container: "};
      return Error(where + extracted.message);
    }
  }

  std::cerr << "Created root file system: " << rootfs_path << std::endl;

  return Success();
}

std::string Container::Impl::id() const {
  return uuid;
}

pid_t Container::Impl::pid() const {
  return clone_pid;
}

bool Container::Impl::has_pty() const {
  return pty_created;
}

int Container::Impl::pty_fd() const {
  return pty_master_fd;
}

Status await(const Container& container) {
  const pid_t pid = container.pid();
  if (pid == 0) {
    return Error("Cannot call wait from within container.");
  }
  if (waitpid(pid, NULL, __WALL) == -1) {
    return Errno("Could not wait on container", errno);
  }

  return Success();
}

bool parent_of(const Container& container) {
  return container.pid() > 0;
}

Status Container::Impl::create_pty() {
  pty_master_fd = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC);
  if (pty_master_fd < 0) {
    Errno("Could not create pseudoterminal for container", errno);
  }

  char slave_buff[100];
  if (ptsname_r(pty_master_fd, slave_buff, sizeof(slave_buff) - 1 ) != 0) {
    Errno("Failed to determine tty name", errno);
  }
  pty_slave_name = std::string{slave_buff};

  if (grantpt(pty_master_fd) != 0) {
    Errno("Failed to change tty owner", errno);
  }

  if (unlockpt(pty_master_fd) != 0) {
    Errno("Failed to unlock tty", errno);
  }

  pty_created = true;

  return Success();
}

Status Container::Impl::start() {
  auto app_image = images[0];
  if (!app_image.manifest.app) {
    return Error("Image is not startable, no app specified.");
  }
  auto app = from_some(app_image.manifest.app);

  auto clone_flags = CLONE_NEWIPC |
                     CLONE_NEWPID |
                     CLONE_NEWUTS |
                     CLONE_NEWNS;
  // CLONE_NEWNET? O_o
  // No signal is sent to parent.
  clone_pid = syscall(__NR_clone, clone_flags, NULL);
  if (clone_pid == -1) {
    return Errno("Failed to clone", errno);
  }
  if (clone_pid > 0) return Success("parent");

  if (pty_created) {
    close(pty_master_fd);
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    auto pty_slave_fd = open(pty_slave_name.c_str(), O_RDWR);
    if (pty_slave_fd == -1) {
      return Errno("Could not open terminal", errno);
    }
    if (pty_slave_fd != 0) {
      return Errno("Extraneous file handles open when creating terminal", errno);
    }
    dup2(STDIN_FILENO, STDOUT_FILENO);
    dup2(STDIN_FILENO, STDERR_FILENO);
    if (pty_slave_fd > STDERR_FILENO) {
      close(pty_slave_fd);
    }
  }

  if (setsid() == -1) {
    return Errno("Failed to create new session", errno);
  }

  // TODO test
  ioctl(0, TIOCSCTTY, 1);

  // TODO Set PDEATHSIG?

  // Remount / as slave (so we don't pollute mounts but receive host's)
  if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) != 0) {
    return Errno("Failed to mount / as slave", errno);
  }
  if (mount(rootfs_path.c_str(), rootfs_path.c_str(), "bind", MS_BIND|MS_REC, NULL) != 0) {
    return Errno("Failed to bind mount rootfs", errno);
  }

  auto proc_dir = pathname::join(rootfs_path, "proc");
  appc::os::mkdir(proc_dir, 0755, true);
  if (mount("proc", proc_dir.c_str(), "proc",  MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0) {
    return Errno("Failed to mount /proc", errno);
  }

  auto proc_sys_dir = pathname::join(rootfs_path, "proc", "sys");
  appc::os::mkdir(proc_sys_dir, 0755, true);
  if (mount("/proc/sys", proc_sys_dir.c_str(), NULL, MS_BIND, NULL)) {
    return Errno("Failed to bind mount /proc/sys", errno);
  }
  if (mount(NULL, proc_sys_dir.c_str(), NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL)) {
    return Errno("Failed to remount /proc/sys read-only", errno);
  }

  auto sys_dir = pathname::join(rootfs_path, "sys");
  appc::os::mkdir(sys_dir, 0755, true);
  if (mount("sysfs", sys_dir.c_str(), "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL)) {
    return Errno("Failed to mount sysfs /sys", errno);
  }

  auto dev_dir = pathname::join(rootfs_path, "dev");
  appc::os::mkdir(dev_dir, 0755, true);
  if (mount("tmpfs", dev_dir.c_str(), "tmpfs", MS_NOSUID|MS_STRICTATIME, "mode=755")) {
    return Errno("Failed to mount tmpfs /dev", errno);
  }

  auto pts_dir = pathname::join(rootfs_path, "dev", "pts");
  appc::os::mkdir(pts_dir, 0755, true);
  if (mount("devpts", pts_dir.c_str(), "devpts", MS_NOSUID|MS_NOEXEC, NULL)) {
    return Errno("Failed to mount devpts /dev/pts", errno);
  }

  auto new_stdin = pathname::join(rootfs_path, "dev", "stdin");
  auto new_stdout = pathname::join(rootfs_path, "dev", "stdout");
  auto new_stderr = pathname::join(rootfs_path, "dev", "stderr");
  // TODO Test status
  symlink("/proc/self/fd/0", new_stdin.c_str());
  symlink("/proc/self/fd/1", new_stdout.c_str());
  symlink("/proc/self/fd/2", new_stderr.c_str());

  // copy dev nodes
  // set seccomp
  // mknod dev/console
  // add kmsg?
  // locale?
  // timezone?
  // set resolv.conf
  // bind mounts RW
  // bind mounts RO
  // mount tmpfs

  // Signal parent to enforce cgroups

  if (chdir(rootfs_path.c_str()) != 0) {
    return Errno("Failed to chdir to rootfs", errno);
  }

  if (mount(rootfs_path.c_str(), "/", NULL, MS_MOVE, NULL) != 0) {
    return Errno("Failed to move mount /", errno);
  }

  if (chroot(".") != 0) {
    return Errno("chroot failed", errno);
  }

  if (chdir("/") != 0) {
    return Errno("chdir failed", errno);
  }

  // Set up network
  if (sethostname(uuid.c_str(), uuid.length()) != 0) {
    return Errno("Could not set hostname", errno);
  }
  // Drop Capabilities
  // Set SE Linux context

  umask(0022);

  gid_t gid = stoi(app.group.value);
  if (setgid(gid) != 0) {
    return Errno("setgid failed", errno);
  }
  uid_t uid = stoi(app.user.value);
  if (setuid(uid) != 0) {
    return Errno("setuid failed", errno);
  }

  std::map<std::string, std::string> environment{};
  environment["HOME"] = "/"; // TODO
  environment["LOGNAME"] = app.user.value; // TODO
  environment["PATH"] = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
  environment["SHELL"] = "/bin/bash"; // TODO
  environment["USER"] = app.user.value;
  char* term_type = getenv("TERM");
  if (term_type != NULL) {
    environment["TERM"] = term_type;
  }
  if (app.environment) {
    for (const auto& pair : from_some(app.environment)) {
      environment[pair.name] = pair.value;
    }
  }
  char** environment_array = c_env_array(environment);

  // Enmapen schema array types.
  char** pre_start_arguments_array = NULL;
  if (app.event_handlers) {
    const auto handlers = from_some(app.event_handlers);
    for (const auto& handler : handlers) {
      if (handler.name.value == "pre-start") {
        pre_start_arguments_array = c_array(handler.exec);
        break;
      }
    }
  }
  if (pre_start_arguments_array) {
    auto prestart_pid = fork();
    if (prestart_pid) {
      waitpid(prestart_pid, NULL, 0);
    } else {
      if (execvpe(pre_start_arguments_array[0],
                  pre_start_arguments_array,
                  environment_array) == -1) {
        return Errno("execvpe failed: ", errno);
      }
    }
  }

  char** exec_arguments_array = c_array(app.exec);
  // REM free allocated arrays if exec isn't called.
  // REM update container PID code
  auto app_pid = fork();
  if (app_pid) {
    waitpid(app_pid, NULL, 0);
  } else {
    if (execvpe(exec_arguments_array[0], exec_arguments_array, environment_array) == -1) {
      return Errno("execvpe failed: ", errno);
    }
  }

  char** post_stop_arguments_array = NULL;
  if (app.event_handlers) {
    const auto handlers = from_some(app.event_handlers);
    for (const auto& handler : handlers) {
      if (handler.name.value == "post-stop") {
        post_stop_arguments_array = c_array(handler.exec);
        break;
      }
    }
  }
  if (post_stop_arguments_array) {
    auto poststart_pid = fork();
    if (poststart_pid) {
      waitpid(poststart_pid, NULL, 0);
    } else {
      if (execvpe(post_stop_arguments_array[0],
                  post_stop_arguments_array,
                  environment_array) == -1) {
        return Errno("execvpe failed: ", errno);
      }
    }
  }

  return Success("child");
}

} // namespace linux
} // namespace container
} // namespace executor
} // namespace nosecone

#endif
<commit_msg>container: Added some TODO notes.<commit_after>// Copyright 2015 Charles D. Aylward
//
// 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.
//
// A (possibly updated) copy of of this software is available at
// https://github.com/cdaylward/nosecone

#include <cerrno>
#include <csignal>
#include <cstdlib>
#include <vector>

#include <dirent.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/mount.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
// TODO decide on term attrs
#include <termios.h>
#include <unistd.h>

#include "appc/image/image.h"
#include "appc/os/mkdir.h"
#include "appc/util/status.h"
#include "appc/util/option.h"

#include "nosecone/errno.h"
#include "nosecone/executor/container/linux.h"

#ifdef __linux__
#include <sys/prctl.h>

namespace nosecone {
namespace executor {
namespace container {
namespace linux {

inline char** c_env_array(const std::map<std::string, std::string>& environment) {
  const size_t env_size = environment.size() + 1;
  char** environment_array = static_cast<char**>(calloc(env_size, sizeof(char*)));
  off_t i = 0;
  for (const auto& pair : environment) {
    const auto assignment = pair.first + "=" + pair.second;
    environment_array[i++] = strdup(const_cast<char*>(assignment.c_str()));
  }
  environment_array[i] = NULL;
  return environment_array;
}

inline char** c_array(const std::vector<std::string>& strings) {
  const size_t array_size = strings.size() + 1;
  char** array = static_cast<char**>(calloc(array_size, sizeof(char*)));
  off_t i = 0;
  for (const auto& str : strings) {
    array[i++] = strdup(const_cast<char*>(str.c_str()));
  }
  array[i] = NULL;
  return array;
}

inline char** c_array(const appc::schema::Exec& exec) {
  std::vector<std::string> strings{};
  for (const auto& arg : exec) {
    strings.push_back(arg.value);
  }
  return c_array(strings);
}

Status Container::Impl::create_rootfs() {
  const auto made_container_root = appc::os::mkdir(rootfs_path, 0755, true);
  if (!made_container_root) {
    std::string where{"Could not create directory for container: "};
    return Error(where + made_container_root.message);
  }

  for (auto& image : images) {
    auto extracted = image.archive.extract_rootfs_to(rootfs_path);
    if (!extracted) {
      std::string where{"Could not create root file system for container: "};
      return Error(where + extracted.message);
    }
  }

  std::cerr << "Created root file system: " << rootfs_path << std::endl;

  return Success();
}

std::string Container::Impl::id() const {
  return uuid;
}

pid_t Container::Impl::pid() const {
  return clone_pid;
}

bool Container::Impl::has_pty() const {
  return pty_created;
}

int Container::Impl::pty_fd() const {
  return pty_master_fd;
}

Status await(const Container& container) {
  const pid_t pid = container.pid();
  if (pid == 0) {
    return Error("Cannot call wait from within container.");
  }
  if (waitpid(pid, NULL, __WALL) == -1) {
    return Errno("Could not wait on container", errno);
  }

  return Success();
}

bool parent_of(const Container& container) {
  return container.pid() > 0;
}

Status Container::Impl::create_pty() {
  pty_master_fd = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC);
  if (pty_master_fd < 0) {
    Errno("Could not create pseudoterminal for container", errno);
  }

  char slave_buff[100];
  if (ptsname_r(pty_master_fd, slave_buff, sizeof(slave_buff) - 1 ) != 0) {
    Errno("Failed to determine tty name", errno);
  }
  pty_slave_name = std::string{slave_buff};

  if (grantpt(pty_master_fd) != 0) {
    Errno("Failed to change tty owner", errno);
  }

  if (unlockpt(pty_master_fd) != 0) {
    Errno("Failed to unlock tty", errno);
  }

  pty_created = true;

  return Success();
}

Status Container::Impl::start() {
  auto app_image = images[0];
  if (!app_image.manifest.app) {
    return Error("Image is not startable, no app specified.");
  }
  auto app = from_some(app_image.manifest.app);

  auto clone_flags = CLONE_NEWIPC |
                     CLONE_NEWPID |
                     CLONE_NEWUTS |
                     CLONE_NEWNS;
  // CLONE_NEWNET? O_o
  // No signal is sent to parent.
  clone_pid = syscall(__NR_clone, clone_flags, NULL);
  if (clone_pid == -1) {
    return Errno("Failed to clone", errno);
  }
  if (clone_pid > 0) return Success("parent");

  if (pty_created) {
    close(pty_master_fd);
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    auto pty_slave_fd = open(pty_slave_name.c_str(), O_RDWR);
    if (pty_slave_fd == -1) {
      return Errno("Could not open terminal", errno);
    }
    if (pty_slave_fd != 0) {
      return Errno("Extraneous file handles open when creating terminal", errno);
    }
    dup2(STDIN_FILENO, STDOUT_FILENO);
    dup2(STDIN_FILENO, STDERR_FILENO);
    if (pty_slave_fd > STDERR_FILENO) {
      close(pty_slave_fd);
    }
  }

  if (setsid() == -1) {
    return Errno("Failed to create new session", errno);
  }

  // TODO test
  ioctl(0, TIOCSCTTY, 1);

  // TODO Set PDEATHSIG?

  // Remount / as slave (so we don't pollute mounts but receive host's)
  if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) != 0) {
    return Errno("Failed to mount / as slave", errno);
  }
  if (mount(rootfs_path.c_str(), rootfs_path.c_str(), "bind", MS_BIND|MS_REC, NULL) != 0) {
    return Errno("Failed to bind mount rootfs", errno);
  }

  auto proc_dir = pathname::join(rootfs_path, "proc");
  appc::os::mkdir(proc_dir, 0755, true);
  if (mount("proc", proc_dir.c_str(), "proc",  MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0) {
    return Errno("Failed to mount /proc", errno);
  }

  auto proc_sys_dir = pathname::join(rootfs_path, "proc", "sys");
  appc::os::mkdir(proc_sys_dir, 0755, true);
  if (mount("/proc/sys", proc_sys_dir.c_str(), NULL, MS_BIND, NULL)) {
    return Errno("Failed to bind mount /proc/sys", errno);
  }
  if (mount(NULL, proc_sys_dir.c_str(), NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL)) {
    return Errno("Failed to remount /proc/sys read-only", errno);
  }

  auto sys_dir = pathname::join(rootfs_path, "sys");
  appc::os::mkdir(sys_dir, 0755, true);
  if (mount("sysfs", sys_dir.c_str(), "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL)) {
    return Errno("Failed to mount sysfs /sys", errno);
  }

  auto dev_dir = pathname::join(rootfs_path, "dev");
  appc::os::mkdir(dev_dir, 0755, true);
  if (mount("tmpfs", dev_dir.c_str(), "tmpfs", MS_NOSUID|MS_STRICTATIME, "mode=755")) {
    return Errno("Failed to mount tmpfs /dev", errno);
  }

  auto pts_dir = pathname::join(rootfs_path, "dev", "pts");
  appc::os::mkdir(pts_dir, 0755, true);
  if (mount("devpts", pts_dir.c_str(), "devpts", MS_NOSUID|MS_NOEXEC, NULL)) {
    return Errno("Failed to mount devpts /dev/pts", errno);
  }

  auto new_stdin = pathname::join(rootfs_path, "dev", "stdin");
  auto new_stdout = pathname::join(rootfs_path, "dev", "stdout");
  auto new_stderr = pathname::join(rootfs_path, "dev", "stderr");
  // TODO Test status
  symlink("/proc/self/fd/0", new_stdin.c_str());
  symlink("/proc/self/fd/1", new_stdout.c_str());
  symlink("/proc/self/fd/2", new_stderr.c_str());

  // copy dev nodes
  // set seccomp
  // mknod dev/console
  // add kmsg?
  // locale?
  // timezone?
  // set resolv.conf
  // bind mounts RW
  // bind mounts RO
  // mount tmpfs

  // Signal parent to enforce cgroups

  if (chdir(rootfs_path.c_str()) != 0) {
    return Errno("Failed to chdir to rootfs", errno);
  }

  if (mount(rootfs_path.c_str(), "/", NULL, MS_MOVE, NULL) != 0) {
    return Errno("Failed to move mount /", errno);
  }

  if (chroot(".") != 0) {
    return Errno("chroot failed", errno);
  }

  if (chdir("/") != 0) {
    return Errno("chdir failed", errno);
  }

  // Set up network
  if (sethostname(uuid.c_str(), uuid.length()) != 0) {
    return Errno("Could not set hostname", errno);
  }
  // Drop Capabilities
  // Set SE Linux context

  umask(0022);

  gid_t gid = stoi(app.group.value);
  if (setgid(gid) != 0) {
    return Errno("setgid failed", errno);
  }
  uid_t uid = stoi(app.user.value);
  if (setuid(uid) != 0) {
    return Errno("setuid failed", errno);
  }

  std::map<std::string, std::string> environment{};
  environment["HOME"] = "/"; // TODO
  environment["LOGNAME"] = app.user.value; // TODO
  environment["PATH"] = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
  environment["SHELL"] = "/bin/bash"; // TODO
  environment["USER"] = app.user.value;
  char* term_type = getenv("TERM");
  if (term_type != NULL) {
    environment["TERM"] = term_type;
  }
  if (app.environment) {
    for (const auto& pair : from_some(app.environment)) {
      environment[pair.name] = pair.value;
    }
  }
  char** environment_array = c_env_array(environment);

  // TODO clean ALL of this up!
  // Enmapen schema map types.
  // REM free allocated arrays if exec isn't called.
  // REM update container PID code?
  char** pre_start_arguments_array = NULL;
  if (app.event_handlers) {
    const auto handlers = from_some(app.event_handlers);
    for (const auto& handler : handlers) {
      if (handler.name.value == "pre-start") {
        pre_start_arguments_array = c_array(handler.exec);
        break;
      }
    }
  }
  if (pre_start_arguments_array) {
    auto prestart_pid = fork();
    if (prestart_pid) {
      // TODO these need to check status
      waitpid(prestart_pid, NULL, 0);
    } else {
      if (execvpe(pre_start_arguments_array[0],
                  pre_start_arguments_array,
                  environment_array) == -1) {
        return Errno("execvpe failed: ", errno);
      }
    }
  }

  char** exec_arguments_array = c_array(app.exec);
  auto app_pid = fork();
  if (app_pid) {
    waitpid(app_pid, NULL, 0);
  } else {
    if (execvpe(exec_arguments_array[0], exec_arguments_array, environment_array) == -1) {
      return Errno("execvpe failed: ", errno);
    }
  }

  char** post_stop_arguments_array = NULL;
  if (app.event_handlers) {
    const auto handlers = from_some(app.event_handlers);
    for (const auto& handler : handlers) {
      if (handler.name.value == "post-stop") {
        post_stop_arguments_array = c_array(handler.exec);
        break;
      }
    }
  }
  if (post_stop_arguments_array) {
    auto poststart_pid = fork();
    if (poststart_pid) {
      waitpid(poststart_pid, NULL, 0);
    } else {
      if (execvpe(post_stop_arguments_array[0],
                  post_stop_arguments_array,
                  environment_array) == -1) {
        return Errno("execvpe failed: ", errno);
      }
    }
  }

  return Success("child");
}

} // namespace linux
} // namespace container
} // namespace executor
} // namespace nosecone

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 by Michael Berlin, Zuse Institute Berlin
 *
 * Licensed under the BSD License, see LICENSE file for details.
 *
 */

#include <boost/scoped_ptr.hpp>
#include <iostream>
#include <string>
#include <unistd.h>

#include "libxtreemfs/client.h"
#include "libxtreemfs/file_handle.h"
#include "libxtreemfs/helper.h"
#include "libxtreemfs/user_mapping.h"
#include "libxtreemfs/volume.h"
#include "libxtreemfs/xtreemfs_exception.h"
#include "lsfs.xtreemfs/lsfs_options.h"
#include "util/logging.h"
#include "xtreemfs/MRC.pb.h"

using namespace std;
using namespace xtreemfs;
using namespace xtreemfs::pbrpc;
using namespace xtreemfs::util;

int main(int argc, char* argv[]) {
  // Parse command line options.
  LsfsOptions options;
  bool invalid_commandline_parameters = false;
  try {
    options.ParseCommandLine(argc, argv);
  } catch(const XtreemFSException& e) {
    cout << "Invalid parameters found, error: " << e.what() << endl << endl;
    invalid_commandline_parameters = true;
  }
  // Display help if needed.
  if (options.empty_arguments_list || invalid_commandline_parameters) {
    cout << options.ShowCommandLineUsage() << endl;
    return 1;
  }
  if (options.show_help) {
    cout << options.ShowCommandLineHelp() << endl;
    return 1;
  }
  // Show only the version.
  if (options.show_version) {
    cout << options.ShowVersion("lsfs.xtreemfs") << endl;
    return 1;
  }

  // Set user_credentials.
  UserCredentials user_credentials;
  user_credentials.set_username("xtreemfs");
  user_credentials.add_groups("xtreemfs");

  Auth auth;
  if (options.admin_password.empty()) {
    auth.set_auth_type(AUTH_NONE);
  } else {
    auth.set_auth_type(AUTH_PASSWORD);
    auth.mutable_auth_passwd()->set_password(options.admin_password);
  }

  // Create a new client and start it.
  boost::scoped_ptr<Client> client(Client::CreateClient(
      ServiceAddresses(1, "DIR-host-not-required-for-lsfs"),  // Using a bogus value as DIR address.  // NOLINT
      user_credentials,
      options.GenerateSSLOptions(),
      options));
  client->Start();

  // Create the volume.
  cout << "Listing all volumes of the MRC: " << options.xtreemfs_url << endl;

  bool success = true;
  boost::scoped_ptr<xtreemfs::pbrpc::Volumes> volumes(NULL);
  try {
    volumes.reset(client->ListVolumes(options.mrc_service_address, auth));
  } catch (const XtreemFSException& e) {
    success = false;
    cout << "Failed to list the volumes, error:\n"
         << "\t" << e.what() << endl;
  }

  // Cleanup.
  client->Shutdown();

  if (success) {
    cout << "Volumes on " << options.mrc_service_address
         << " (Format: volume name -> volume UUID):" << endl;
    for (int i = 0; i < volumes->volumes_size(); i++) {
      const xtreemfs::pbrpc::Volume& volume = volumes->volumes(i);
      cout << "\t" << volume.name() << "\t->\t" << volume.id() << endl;
    }
    cout << "End of List." << endl;
    return 0;
  } else {
    return 1;
  }
}
<commit_msg>client: lsfs.xtreemfs: Removed unnecessary includes.<commit_after>/*
 * Copyright (c) 2011-2012 by Michael Berlin, Zuse Institute Berlin
 *
 * Licensed under the BSD License, see LICENSE file for details.
 *
 */

#include <boost/scoped_ptr.hpp>
#include <iostream>
#include <string>

#include "libxtreemfs/client.h"
#include "libxtreemfs/file_handle.h"
#include "libxtreemfs/helper.h"
#include "libxtreemfs/volume.h"
#include "libxtreemfs/xtreemfs_exception.h"
#include "lsfs.xtreemfs/lsfs_options.h"
#include "util/logging.h"
#include "xtreemfs/MRC.pb.h"

using namespace std;
using namespace xtreemfs;
using namespace xtreemfs::pbrpc;
using namespace xtreemfs::util;

int main(int argc, char* argv[]) {
  // Parse command line options.
  LsfsOptions options;
  bool invalid_commandline_parameters = false;
  try {
    options.ParseCommandLine(argc, argv);
  } catch(const XtreemFSException& e) {
    cout << "Invalid parameters found, error: " << e.what() << endl << endl;
    invalid_commandline_parameters = true;
  }
  // Display help if needed.
  if (options.empty_arguments_list || invalid_commandline_parameters) {
    cout << options.ShowCommandLineUsage() << endl;
    return 1;
  }
  if (options.show_help) {
    cout << options.ShowCommandLineHelp() << endl;
    return 1;
  }
  // Show only the version.
  if (options.show_version) {
    cout << options.ShowVersion("lsfs.xtreemfs") << endl;
    return 1;
  }

  // Set user_credentials.
  UserCredentials user_credentials;
  user_credentials.set_username("xtreemfs");
  user_credentials.add_groups("xtreemfs");

  Auth auth;
  if (options.admin_password.empty()) {
    auth.set_auth_type(AUTH_NONE);
  } else {
    auth.set_auth_type(AUTH_PASSWORD);
    auth.mutable_auth_passwd()->set_password(options.admin_password);
  }

  // Create a new client and start it.
  boost::scoped_ptr<Client> client(Client::CreateClient(
      ServiceAddresses(1, "DIR-host-not-required-for-lsfs"),  // Using a bogus value as DIR address.  // NOLINT
      user_credentials,
      options.GenerateSSLOptions(),
      options));
  client->Start();

  // Create the volume.
  cout << "Listing all volumes of the MRC: " << options.xtreemfs_url << endl;

  bool success = true;
  boost::scoped_ptr<xtreemfs::pbrpc::Volumes> volumes(NULL);
  try {
    volumes.reset(client->ListVolumes(options.mrc_service_address, auth));
  } catch (const XtreemFSException& e) {
    success = false;
    cout << "Failed to list the volumes, error:\n"
         << "\t" << e.what() << endl;
  }

  // Cleanup.
  client->Shutdown();

  if (success) {
    cout << "Volumes on " << options.mrc_service_address
         << " (Format: volume name -> volume UUID):" << endl;
    for (int i = 0; i < volumes->volumes_size(); i++) {
      const xtreemfs::pbrpc::Volume& volume = volumes->volumes(i);
      cout << "\t" << volume.name() << "\t->\t" << volume.id() << endl;
    }
    cout << "End of List." << endl;
    return 0;
  } else {
    return 1;
  }
}
<|endoftext|>


<commit_before>/*
 * File:   rigResection.cpp
 * Author: sgaspari
 *
 * Created on January 2, 2016, 5:51 PM
 */

#include "rigResection.hpp"

#if HAVE_OPENGV
#include <Eigen/Eigen>
#include <opengv/absolute_pose/methods.hpp>
#include <opengv/absolute_pose/NoncentralAbsoluteAdapter.hpp>
#include <opengv/sac/Ransac.hpp>
#include <opengv/sac_problems/absolute_pose/AbsolutePoseSacProblem.hpp>
#endif

#include <stdio.h>
#include <iostream>
#include <vector>
#include <chrono>

namespace openMVG{
namespace localization{

#if HAVE_OPENGV

bool rigResection(const std::vector<Mat> &pts2d,
                  const std::vector<Mat> &pts3d,
                  const std::vector<cameras::Pinhole_Intrinsic_Radial_K3 > &vec_queryIntrinsics,
                  const std::vector<geometry::Pose3 > &vec_subPoses,
                  geometry::Pose3 &rigPose,
                  std::vector<std::vector<std::size_t> > &inliers,
                  double threshold /*= 1e-6*/,
                  size_t maxIterations /*= 100*/,
                  bool verbosity /*= true*/)
{
  const std::size_t numCameras = pts2d.size();

  assert(pts3d.size() == numCameras);
  assert(vec_queryIntrinsics.size() == numCameras);
  // the subposes are always wrt the main camera
  assert(vec_subPoses.size() == numCameras-1);

  // Copy the subposes into separate vectors for rotations and centers
  opengv::translations_t camOffsets(numCameras); //centers
  opengv::rotations_t camRotations(numCameras);

  // the first is the identity (the main camera)
  camOffsets[0] = Vec3::Zero();
  camRotations[0] = Mat3::Identity();
  // now copy the others
  for(std::size_t i = 1; i < numCameras; ++i)
  {
    camOffsets[i] = vec_subPoses[i-1].center();
    // it takes as input a real pose, ie the rotation wrt the world frame
    camRotations[i] = vec_subPoses[i-1].rotation().inverse();
  }

  // count the total number of associations
  std::size_t numTotalPoints = 0;
  for(std::size_t i = 0; i < numCameras; ++i)
  {
    const std::size_t numPts = pts2d[i].cols();
    assert(pts3d[i].cols() == numPts);
    assert(pts3d[i].rows() == 3);
    assert(pts2d[i].rows() == 2);
    numTotalPoints += numPts;
  }
  // transform the points into bearingVectors
  opengv::bearingVectors_t bearingVectors;  // this contains the bearing vector associated to each image feature
  opengv::points_t points;                  // this contains the 3d points
  points.reserve(numTotalPoints);
  std::vector<int> camCorrespondences;      // this is to keep track, for each bearing vector, whose camera it belongs

  // this map is used to remap the indices of the flatten structure containing
  // the points (points, bearingvector) to the original local index of each pts2d/pts3d:
  // eg
  // localIdx = absoluteToLocal[absoluteID]; such that
  // pts3d[localIdx.first].col(localIdx.second) == points[absoluteID];
  std::map<std::size_t, std::pair<std::size_t,std::size_t>> absoluteToLocal;

  for(std::size_t cam = 0; cam < numCameras; ++cam)
  {
    const std::size_t numPts = pts2d[cam].cols();
    const cameras::Pinhole_Intrinsic_Radial_K3 &currCamera = vec_queryIntrinsics[cam];

    for(std::size_t i = 0; i < numPts; ++i)
    {
      // store the 3D point
      points.push_back(pts3d[cam].col(i));

      // we first remove the distortion and then we transform the undistorted point in
      // normalized camera coordinates (inv(K)*undistortedPoint)
      auto pt = currCamera.ima2cam(currCamera.remove_disto(pts2d[cam].col(i)));

      opengv::bearingVector_t bearing(pt(0), pt(1), 1.0);

      // normalize the bearing-vector to 1
      bearing = bearing / bearing.norm();

      bearingVectors.push_back(bearing);

      camCorrespondences.push_back(cam);

      // fill the indices map
      absoluteToLocal[points.size()-1] = std::make_pair(cam, i);
    }
  }

  assert(points.size() == numTotalPoints);
  assert(bearingVectors.size() == numTotalPoints);
  assert(camCorrespondences.size() == numTotalPoints);

  using namespace opengv;
  //create a non-central absolute adapter
  absolute_pose::NoncentralAbsoluteAdapter adapter(bearingVectors,
                                                   camCorrespondences,
                                                   points,
                                                   camOffsets,
                                                   camRotations);

  //Create a AbsolutePoseSacProblem and Ransac
  //The method is set to GP3P
  sac::Ransac<sac_problems::absolute_pose::AbsolutePoseSacProblem> ransac;
  std::shared_ptr<
          sac_problems::absolute_pose::AbsolutePoseSacProblem> absposeproblem_ptr(
              new sac_problems::absolute_pose::AbsolutePoseSacProblem(
                  adapter,
                  sac_problems::absolute_pose::AbsolutePoseSacProblem::GP3P));
  ransac.sac_model_ = absposeproblem_ptr;
  ransac.threshold_ = threshold;
  ransac.max_iterations_ = maxIterations;

  auto detect_start = std::chrono::steady_clock::now();
  const bool success = ransac.computeModel();
  auto detect_end = std::chrono::steady_clock::now();
  const auto detect_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(detect_end - detect_start);

  if(!success)
  {
    if(verbosity)
      std::cout << "Resection Failed" << std::endl;

    return false;
  }

  const auto &sol = ransac.model_coefficients_;
  // again, the output is a real pose, with the center and the rotation expressed
  // wrt the world frame, ie we need to take the transpose/inverse of the rotation
  rigPose = geometry::Pose3(sol.block<3,3>(0,0).transpose(), sol.col(3));

  // copy the inliers
  const std::size_t numInliers = ransac.inliers_.size();
  inliers.clear();
  inliers.resize(numCameras);

  if(verbosity)
  {
    std::cout << "\n"
    << "-------------------------------" << "\n"
    << "-- Robust Resection " << "\n"
    << "-- Resection status: " << success << "\n"
    << "-- #Points used for Resection: " << numTotalPoints << "\n"
    << "-- #Points validated by robust Resection: " << numInliers << "\n"
    << "-- #Iterations needed: " << ransac.iterations_ << "\n"
    << "-- #Thresehold used: " << ransac.threshold_ << "\n"
    << "-- Time spent in ransac [ms]: " << detect_elapsed.count() << "\n"
    << "-------------------------------" << std::endl;
  }

  // remap the inliers
  for(std::size_t i = 0; i < numInliers; i++)
  {
    const auto idx = absoluteToLocal.at(ransac.inliers_[i]);
    inliers[idx.first].emplace_back(idx.second);
  }

//  for(size_t i = 0; i < ransac.inliers_.size(); i++)
//    std::cout << ransac.inliers_[i] << " ";
//  std::cout << std::endl;
//
//  for(size_t i = 0; i < inliers.size(); ++i)
//  {
//    std::cout << "Inliers cam " << i << ": ";
//    for(size_t j = 0; j < inliers[i].size(); ++j)
//      std::cout << inliers[i][j] << " ";
//    std::cout << std::endl;
//  }

  return success;
}

#endif // #if HAVE_OPENGV

}
}<commit_msg>[localization] bugfix for undistortion in rigResection<commit_after>/*
 * File:   rigResection.cpp
 * Author: sgaspari
 *
 * Created on January 2, 2016, 5:51 PM
 */

#include "rigResection.hpp"

#if HAVE_OPENGV
#include <Eigen/Eigen>
#include <opengv/absolute_pose/methods.hpp>
#include <opengv/absolute_pose/NoncentralAbsoluteAdapter.hpp>
#include <opengv/sac/Ransac.hpp>
#include <opengv/sac_problems/absolute_pose/AbsolutePoseSacProblem.hpp>
#endif

#include <stdio.h>
#include <iostream>
#include <vector>
#include <chrono>

namespace openMVG{
namespace localization{

#if HAVE_OPENGV

bool rigResection(const std::vector<Mat> &pts2d,
                  const std::vector<Mat> &pts3d,
                  const std::vector<cameras::Pinhole_Intrinsic_Radial_K3 > &vec_queryIntrinsics,
                  const std::vector<geometry::Pose3 > &vec_subPoses,
                  geometry::Pose3 &rigPose,
                  std::vector<std::vector<std::size_t> > &inliers,
                  double threshold /*= 1e-6*/,
                  size_t maxIterations /*= 100*/,
                  bool verbosity /*= true*/)
{
  const std::size_t numCameras = pts2d.size();

  assert(pts3d.size() == numCameras);
  assert(vec_queryIntrinsics.size() == numCameras);
  // the subposes are always wrt the main camera
  assert(vec_subPoses.size() == numCameras-1);

  // Copy the subposes into separate vectors for rotations and centers
  opengv::translations_t camOffsets(numCameras); //centers
  opengv::rotations_t camRotations(numCameras);

  // the first is the identity (the main camera)
  camOffsets[0] = Vec3::Zero();
  camRotations[0] = Mat3::Identity();
  // now copy the others
  for(std::size_t i = 1; i < numCameras; ++i)
  {
    camOffsets[i] = vec_subPoses[i-1].center();
    // it takes as input a real pose, ie the rotation wrt the world frame
    camRotations[i] = vec_subPoses[i-1].rotation().inverse();
  }

  // count the total number of associations
  std::size_t numTotalPoints = 0;
  for(std::size_t i = 0; i < numCameras; ++i)
  {
    const std::size_t numPts = pts2d[i].cols();
    assert(pts3d[i].cols() == numPts);
    assert(pts3d[i].rows() == 3);
    assert(pts2d[i].rows() == 2);
    numTotalPoints += numPts;
  }
  // transform the points into bearingVectors
  opengv::bearingVectors_t bearingVectors;  // this contains the bearing vector associated to each image feature
  opengv::points_t points;                  // this contains the 3d points
  points.reserve(numTotalPoints);
  std::vector<int> camCorrespondences;      // this is to keep track, for each bearing vector, whose camera it belongs

  // this map is used to remap the indices of the flatten structure containing
  // the points (points, bearingvector) to the original local index of each pts2d/pts3d:
  // eg
  // localIdx = absoluteToLocal[absoluteID]; such that
  // pts3d[localIdx.first].col(localIdx.second) == points[absoluteID];
  std::map<std::size_t, std::pair<std::size_t,std::size_t>> absoluteToLocal;

  for(std::size_t cam = 0; cam < numCameras; ++cam)
  {
    const std::size_t numPts = pts2d[cam].cols();
    const cameras::Pinhole_Intrinsic_Radial_K3 &currCamera = vec_queryIntrinsics[cam];

    for(std::size_t i = 0; i < numPts; ++i)
    {
      // store the 3D point
      points.push_back(pts3d[cam].col(i));

      // we first remove the distortion and then we transform the undistorted point in
      // normalized camera coordinates (inv(K)*undistortedPoint)
      auto pt = currCamera.ima2cam(currCamera.get_ud_pixel(pts2d[cam].col(i)));

      opengv::bearingVector_t bearing(pt(0), pt(1), 1.0);

      // normalize the bearing-vector to 1
      bearing = bearing / bearing.norm();

      bearingVectors.push_back(bearing);

      camCorrespondences.push_back(cam);

      // fill the indices map
      absoluteToLocal[points.size()-1] = std::make_pair(cam, i);
    }
  }

  assert(points.size() == numTotalPoints);
  assert(bearingVectors.size() == numTotalPoints);
  assert(camCorrespondences.size() == numTotalPoints);

  using namespace opengv;
  //create a non-central absolute adapter
  absolute_pose::NoncentralAbsoluteAdapter adapter(bearingVectors,
                                                   camCorrespondences,
                                                   points,
                                                   camOffsets,
                                                   camRotations);

  //Create a AbsolutePoseSacProblem and Ransac
  //The method is set to GP3P
  sac::Ransac<sac_problems::absolute_pose::AbsolutePoseSacProblem> ransac;
  std::shared_ptr<
          sac_problems::absolute_pose::AbsolutePoseSacProblem> absposeproblem_ptr(
              new sac_problems::absolute_pose::AbsolutePoseSacProblem(
                  adapter,
                  sac_problems::absolute_pose::AbsolutePoseSacProblem::GP3P));
  ransac.sac_model_ = absposeproblem_ptr;
  ransac.threshold_ = threshold;
  ransac.max_iterations_ = maxIterations;

  auto detect_start = std::chrono::steady_clock::now();
  const bool success = ransac.computeModel();
  auto detect_end = std::chrono::steady_clock::now();
  const auto detect_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(detect_end - detect_start);

  if(!success)
  {
    if(verbosity)
      std::cout << "Resection Failed" << std::endl;

    return false;
  }

  const auto &sol = ransac.model_coefficients_;
  // again, the output is a real pose, with the center and the rotation expressed
  // wrt the world frame, ie we need to take the transpose/inverse of the rotation
  rigPose = geometry::Pose3(sol.block<3,3>(0,0).transpose(), sol.col(3));

  // copy the inliers
  const std::size_t numInliers = ransac.inliers_.size();
  inliers.clear();
  inliers.resize(numCameras);

  if(verbosity)
  {
    std::cout << "\n"
    << "-------------------------------" << "\n"
    << "-- Robust Resection " << "\n"
    << "-- Resection status: " << success << "\n"
    << "-- #Points used for Resection: " << numTotalPoints << "\n"
    << "-- #Points validated by robust Resection: " << numInliers << "\n"
    << "-- #Iterations needed: " << ransac.iterations_ << "\n"
    << "-- #Thresehold used: " << ransac.threshold_ << "\n"
    << "-- Time spent in ransac [ms]: " << detect_elapsed.count() << "\n"
    << "-------------------------------" << std::endl;
  }

  // remap the inliers
  for(std::size_t i = 0; i < numInliers; i++)
  {
    const auto idx = absoluteToLocal.at(ransac.inliers_[i]);
    inliers[idx.first].emplace_back(idx.second);
  }

//  for(size_t i = 0; i < ransac.inliers_.size(); i++)
//    std::cout << ransac.inliers_[i] << " ";
//  std::cout << std::endl;
//
//  for(size_t i = 0; i < inliers.size(); ++i)
//  {
//    std::cout << "Inliers cam " << i << ": ";
//    for(size_t j = 0; j < inliers[i].size(); ++j)
//      std::cout << inliers[i][j] << " ";
//    std::cout << std::endl;
//  }

  return success;
}

#endif // #if HAVE_OPENGV

}
}<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "cql3/statements/drop_table_statement.hh"

#include "service/migration_manager.hh"

namespace cql3 {

namespace statements {

drop_table_statement::drop_table_statement(::shared_ptr<cf_name> cf_name, bool if_exists)
    : schema_altering_statement{std::move(cf_name)}
    , _if_exists{if_exists}
{
}

void drop_table_statement::check_access(const service::client_state& state)
{
    warn(unimplemented::cause::AUTH);
#if 0
    try
    {
        state.hasColumnFamilyAccess(keyspace(), columnFamily(), Permission.DROP);
    }
    catch (InvalidRequestException e)
    {
        if (!ifExists)
            throw e;
    }
#endif
    }

void drop_table_statement::validate(distributed<service::storage_proxy>&, const service::client_state& state)
{
    // validated in announce_migration()
}

future<bool> drop_table_statement::announce_migration(distributed<service::storage_proxy>& proxy, bool is_local_only)
{
    return make_ready_future<>().then([&] {
        return service::get_local_migration_manager().announce_column_family_drop(keyspace(), column_family(), is_local_only);
    }).then_wrapped([this] (auto&& f) {
        try {
            f.get();
            return true;
        } catch (const exceptions::configuration_exception& e) {
            if (_if_exists) {
                return false;
            }
            throw e;
        }
    });
}

shared_ptr<transport::event::schema_change> drop_table_statement::change_event()
{
    using namespace transport;

    return make_shared<event::schema_change>(event::schema_change::change_type::DROPPED,
                                             event::schema_change::target_type::TABLE,
                                             keyspace(),
                                             column_family());
}

}

}
<commit_msg>cql3: Fix capture-by-reference in drop_table_statement<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "cql3/statements/drop_table_statement.hh"

#include "service/migration_manager.hh"

namespace cql3 {

namespace statements {

drop_table_statement::drop_table_statement(::shared_ptr<cf_name> cf_name, bool if_exists)
    : schema_altering_statement{std::move(cf_name)}
    , _if_exists{if_exists}
{
}

void drop_table_statement::check_access(const service::client_state& state)
{
    warn(unimplemented::cause::AUTH);
#if 0
    try
    {
        state.hasColumnFamilyAccess(keyspace(), columnFamily(), Permission.DROP);
    }
    catch (InvalidRequestException e)
    {
        if (!ifExists)
            throw e;
    }
#endif
    }

void drop_table_statement::validate(distributed<service::storage_proxy>&, const service::client_state& state)
{
    // validated in announce_migration()
}

future<bool> drop_table_statement::announce_migration(distributed<service::storage_proxy>& proxy, bool is_local_only)
{
    return make_ready_future<>().then([this, is_local_only] {
        return service::get_local_migration_manager().announce_column_family_drop(keyspace(), column_family(), is_local_only);
    }).then_wrapped([this] (auto&& f) {
        try {
            f.get();
            return true;
        } catch (const exceptions::configuration_exception& e) {
            if (_if_exists) {
                return false;
            }
            throw e;
        }
    });
}

shared_ptr<transport::event::schema_change> drop_table_statement::change_event()
{
    using namespace transport;

    return make_shared<event::schema_change>(event::schema_change::change_type::DROPPED,
                                             event::schema_change::target_type::TABLE,
                                             keyspace(),
                                             column_family());
}

}

}
<|endoftext|>


<commit_before>#include <QWindow>
#include <QtDeclarative>
#include <QQuickView>

int main( int argc, char** argv )
{
    QGuiApplication app( argc, argv );

    QWindow *window = 0;
    int exitCode = 0;

    QQuickView* view = new QQuickView();
    view->setResizeMode( QQuickView::SizeRootObjectToView );
    view->setSource( QUrl( "app/native/qml/main.qml" ) );

    QDeclarativeEngine* engine = view->engine();
    QObject::connect( engine, SIGNAL(quit()),
                      QCoreApplication::instance(), SLOT(quit()) );
    window = view;
    window->showMaximized();

    exitCode = app.exec();

    delete window;
    return exitCode;
}
<commit_msg>QNX: Fixed compilation for BlackBerry QtQuick2 template<commit_after>#include <QGuiApplication>
#include <QQuickView>
#include <QQmlEngine>

int main( int argc, char** argv )
{
    QGuiApplication app( argc, argv );

    QQuickView view;
    view.setResizeMode( QQuickView::SizeRootObjectToView );
    view.setSource( QUrl( "app/native/qml/main.qml" ) );

    QObject::connect( view.engine(), SIGNAL( quit() ),
                      QCoreApplication::instance(), SLOT( quit() ) );
    view.show();

    return app.exec();
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/*
 * $Id$
 */

#if !defined(XERCESC_INCLUDE_GUARD_XERCES_AUTOCONFIG_CONFIG_HPP)
#define XERCESC_INCLUDE_GUARD_XERCES_AUTOCONFIG_CONFIG_HPP

//
// There are two primary xerces configuration header files:
//
//	Xerces_autoconf_config.hpp
//
//      For configuration of items that must be accessable
//	through public headers. This file has limited information
//	and carefully works to avoid collision of macro names, etc.
//
//	This file is included by XercesDefs.h.
//	This version of the file is specific for Borland C++
//	family of compilers
//
//	config.h
//
//      This file is not used with Borland C++; the macros
//	it would specify are instead hardcoded in the makefiles
//

#include <basetsd.h>

// ---------------------------------------------------------------------------
//  These defines have been hardcoded for the Borland C++ compilers
// ---------------------------------------------------------------------------
#undef XERCES_AUTOCONF
#undef XERCES_HAVE_SYS_TYPES_H
#undef XERCES_HAVE_INTTYPES_H

#define XERCES_S16BIT_INT   signed short
#define XERCES_U16BIT_INT   unsigned short
#define XERCES_S32BIT_INT   INT32
#define XERCES_U32BIT_INT   UINT32
#define XERCES_U64BIT_INT   INT64
#define XERCES_U64BIT_INT   UINT64

#define XERCES_SIZEOF_INT   4
#define XERCES_SIZEOF_LONG  4
#define XERCES_SIZEOF_INT64 8

#define XERCES_XMLCH_T      wchar_t

#define XERCES_SIZE_T       SIZE_T
#define XERCES_SSIZE_T      SSIZE_T

#define XERCES_HAS_CPP_NAMESPACE    1
#define XERCES_STD_NAMESPACE        1
#define XERCES_NEW_IOSTREAMS        1
#undef XERCES_NO_NATIVE_BOOL
#define XERCES_LSTRSUPPORT          1

#ifdef XERCES_STATIC_LIBRARY
#define XERCES_PLATFORM_EXPORT
#define XERCES_PLATFORM_IMPORT
#else
#define XERCES_PLATFORM_EXPORT __declspec(dllexport)
#define XERCES_PLATFORM_IMPORT __declspec(dllimport)
#define DLL_EXPORT
#endif

#define XERCES_NO_MATCHING_DELETE_OPERATOR
#define XERCES_NEED_XMEMORY_VIRTUAL_DESTRUCTOR

// ---------------------------------------------------------------------------
//  XMLSize_t is the unsigned integral type.
// ---------------------------------------------------------------------------
typedef XERCES_SIZE_T				XMLSize_t;
typedef XERCES_SSIZE_T				XMLSSize_t;

// ---------------------------------------------------------------------------
//  Define our version of the XML character
// ---------------------------------------------------------------------------
typedef XERCES_XMLCH_T				XMLCh;

// ---------------------------------------------------------------------------
//  Define unsigned 16, 32, and 64 bit integers
// ---------------------------------------------------------------------------
typedef XERCES_U16BIT_INT			XMLUInt16;
typedef XERCES_U32BIT_INT			XMLUInt32;
typedef XERCES_U64BIT_INT			XMLUInt64;

// ---------------------------------------------------------------------------
//  Define signed 16, 32, and 64 bit integers
// ---------------------------------------------------------------------------
typedef XERCES_S16BIT_INT			XMLInt16;
typedef XERCES_S32BIT_INT			XMLInt32;
typedef XERCES_S64BIT_INT			XMLInt64;

// ---------------------------------------------------------------------------
//  XMLFilePos is the type used to represent a file position.
// ---------------------------------------------------------------------------
typedef XMLUInt64			        XMLFilePos;

// ---------------------------------------------------------------------------
//  XMLFileLoc is the type used to represent a file location (line/column).
// ---------------------------------------------------------------------------
typedef XMLUInt64			        XMLFileLoc;

// ---------------------------------------------------------------------------
//  Force on the Xerces debug token if it is on in the build environment
// ---------------------------------------------------------------------------
#if defined(_DEBUG)
#define XERCES_DEBUG
#endif

#endif
<commit_msg>Fixed macro declaration<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/*
 * $Id$
 */

#if !defined(XERCESC_INCLUDE_GUARD_XERCES_AUTOCONFIG_CONFIG_HPP)
#define XERCESC_INCLUDE_GUARD_XERCES_AUTOCONFIG_CONFIG_HPP

//
// There are two primary xerces configuration header files:
//
//	Xerces_autoconf_config.hpp
//
//      For configuration of items that must be accessable
//	through public headers. This file has limited information
//	and carefully works to avoid collision of macro names, etc.
//
//	This file is included by XercesDefs.h.
//	This version of the file is specific for Borland C++
//	family of compilers
//
//	config.h
//
//      This file is not used with Borland C++; the macros
//	it would specify are instead hardcoded in the makefiles
//

#include <basetsd.h>

// ---------------------------------------------------------------------------
//  These defines have been hardcoded for the Borland C++ compilers
// ---------------------------------------------------------------------------
#undef XERCES_AUTOCONF
#undef XERCES_HAVE_SYS_TYPES_H
#undef XERCES_HAVE_INTTYPES_H

#define XERCES_S16BIT_INT   signed short
#define XERCES_U16BIT_INT   unsigned short
#define XERCES_S32BIT_INT   INT32
#define XERCES_U32BIT_INT   UINT32
#define XERCES_S64BIT_INT   INT64
#define XERCES_U64BIT_INT   UINT64

#define XERCES_SIZEOF_INT   4
#define XERCES_SIZEOF_LONG  4
#define XERCES_SIZEOF_INT64 8

#define XERCES_XMLCH_T      wchar_t

#define XERCES_SIZE_T       SIZE_T
#define XERCES_SSIZE_T      SSIZE_T

#define XERCES_HAS_CPP_NAMESPACE    1
#define XERCES_STD_NAMESPACE        1
#define XERCES_NEW_IOSTREAMS        1
#undef XERCES_NO_NATIVE_BOOL
#define XERCES_LSTRSUPPORT          1

#ifdef XERCES_STATIC_LIBRARY
#define XERCES_PLATFORM_EXPORT
#define XERCES_PLATFORM_IMPORT
#else
#define XERCES_PLATFORM_EXPORT __declspec(dllexport)
#define XERCES_PLATFORM_IMPORT __declspec(dllimport)
#define DLL_EXPORT
#endif

#define XERCES_NO_MATCHING_DELETE_OPERATOR
#define XERCES_NEED_XMEMORY_VIRTUAL_DESTRUCTOR

// ---------------------------------------------------------------------------
//  XMLSize_t is the unsigned integral type.
// ---------------------------------------------------------------------------
typedef XERCES_SIZE_T				XMLSize_t;
typedef XERCES_SSIZE_T				XMLSSize_t;

// ---------------------------------------------------------------------------
//  Define our version of the XML character
// ---------------------------------------------------------------------------
typedef XERCES_XMLCH_T				XMLCh;

// ---------------------------------------------------------------------------
//  Define unsigned 16, 32, and 64 bit integers
// ---------------------------------------------------------------------------
typedef XERCES_U16BIT_INT			XMLUInt16;
typedef XERCES_U32BIT_INT			XMLUInt32;
typedef XERCES_U64BIT_INT			XMLUInt64;

// ---------------------------------------------------------------------------
//  Define signed 16, 32, and 64 bit integers
// ---------------------------------------------------------------------------
typedef XERCES_S16BIT_INT			XMLInt16;
typedef XERCES_S32BIT_INT			XMLInt32;
typedef XERCES_S64BIT_INT			XMLInt64;

// ---------------------------------------------------------------------------
//  XMLFilePos is the type used to represent a file position.
// ---------------------------------------------------------------------------
typedef XMLUInt64			        XMLFilePos;

// ---------------------------------------------------------------------------
//  XMLFileLoc is the type used to represent a file location (line/column).
// ---------------------------------------------------------------------------
typedef XMLUInt64			        XMLFileLoc;

// ---------------------------------------------------------------------------
//  Force on the Xerces debug token if it is on in the build environment
// ---------------------------------------------------------------------------
#if defined(_DEBUG)
#define XERCES_DEBUG
#endif

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#ifndef ROSETTASTONE_TORCH_GAME_TO_VEC_HPP
#define ROSETTASTONE_TORCH_GAME_TO_VEC_HPP

#include <Rosetta/Games/Game.hpp>

#include <torch/torch.h>

namespace RosettaTorch
{
using namespace RosettaStone;

//!
//! \brief ActionEncoder struct.
//!
//! This struct generates torch tensor from Game context.
//!
class GameToVec
{
 public:
    //! Constructs the embedding tables.
    GameToVec();

    //! Constructs the embedding tables with given \p seed.
    //! \param seed The seed used when the embedding table is generated.
    explicit GameToVec(std::size_t seed);

    //! Default virtual destructor.
    virtual ~GameToVec() = default;

    //! Generates torch tensor from the effects.
    //! \param effects The card effects.
    //! \return The encoded torch tensor from \p effects.
    virtual torch::Tensor EffectsToTensor(std::vector<Effect> effects);

    //! Generates torch tensor from the tasks.
    //! \param tasks The card tasks.
    //! \return The encoded torch tensor from \p tasks.
    virtual torch::Tensor TasksToTensor(std::vector<ITask*> tasks);

    //! Generates torch tensor from the entity.
    //! \param entity The card context.
    //! \return The encoded torch tensor from \p entity.
    virtual torch::Tensor CardToTensor(Entity* entity);

    //! Generates torch tensor from game context.
    //! \param game The game context.
    //! \return The encoded torch tensor from \p game.
    virtual torch::Tensor GenerateTensor(const Game& game);

    //! Gets Effect Embedding Table.
    //! \return The embedding table torch tensor.
    torch::nn::Embedding GetEffectEmbeddingTable();

    //! Gets Entity Type Embedding Table.
    //! \return The embedding table torch tensor.
    torch::nn::Embedding GetEntityTypeEmbeddingTable();

    //! Gets Task Id Embedding Table.
    //! \return The embedding table torch tensor.
    torch::nn::Embedding GetTaskIdEmbeddingTable();

    /////////////////////////////////////////////
    static constexpr size_t CLIP_CARD_NORM = 64;
    static constexpr size_t CLIP_EFFECT_NORM = 8;

    /////////////////////////////////////////////
    std::vector<GameTag> EffectGameTag = {
        GameTag::INVALID,  GameTag::ATK,       GameTag::HEALTH,
        GameTag::TAUNT,    GameTag::POISONOUS, GameTag::DIVINE_SHIELD,
        GameTag::WINDFURY, GameTag::STEALTH
    };
    std::vector<EffectOperator> EffectOperatorTag = { EffectOperator::ADD,
                                                      EffectOperator::MUL,
                                                      EffectOperator::SET,
                                                      EffectOperator::SUB };
    static constexpr std::size_t EffectVectorSize = 4;
    static constexpr std::size_t EffectGameTagSize = 8;
    static constexpr std::size_t EffectOperationTagSize = 4;
    static constexpr std::size_t EffectIndexSize =
        EffectGameTagSize * EffectOperationTagSize;

    static constexpr std::size_t AuraVectorSize = 5;

    static constexpr std::size_t EnchantVectorSize = 4;

    static constexpr std::size_t EntityTypeVectorSize = 4;
    static constexpr std::size_t EntityTypeIndexSize = 16;
    static constexpr std::size_t TaskIdVectorSize = 4;
    static constexpr std::size_t TaskIdIndexSize = 27;
    static constexpr std::size_t TaskVectorSize =
        EntityTypeVectorSize + TaskIdVectorSize;

    /////////////////////////////////////////////
    static constexpr std::size_t CardMetaSize = 3;
    static constexpr std::size_t AbilityVectorSize =
        AuraVectorSize + EnchantVectorSize + TaskVectorSize + TaskVectorSize;
    static constexpr std::size_t CardVectorSize =
        CardMetaSize + AbilityVectorSize;

    /////////////////////////////////////////////
    static constexpr std::size_t PlayerMetaSize = 3;
    static constexpr std::size_t GameVectorSize =
        PlayerMetaSize + (CardVectorSize * (HAND_SIZE + 2 * FIELD_SIZE));

 private:
    std::size_t m_seed;

    //! embedding table for the card
    torch::nn::Embedding m_effectEmbeddingTable = nullptr;
    torch::nn::Embedding m_entityTypeEmbeddingTable = nullptr;
    torch::nn::Embedding m_taskIDEmbeddingTable = nullptr;
};
}  // namespace RosettaTorch

#endif<commit_msg>fix: Change to Capital letter<commit_after>// Copyright (c) 2018 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#ifndef ROSETTASTONE_TORCH_GAME_TO_VEC_HPP
#define ROSETTASTONE_TORCH_GAME_TO_VEC_HPP

#include <Rosetta/Games/Game.hpp>

#include <torch/torch.h>

namespace RosettaTorch
{
using namespace RosettaStone;

//!
//! \brief ActionEncoder struct.
//!
//! This struct generates torch tensor from Game context.
//!
class GameToVec
{
 public:
    //! Constructs the embedding tables.
    GameToVec();

    //! Constructs the embedding tables with given \p seed.
    //! \param seed The seed used when the embedding table is generated.
    explicit GameToVec(std::size_t seed);

    //! Default virtual destructor.
    virtual ~GameToVec() = default;

    //! Generates torch tensor from the effects.
    //! \param effects The card effects.
    //! \return The encoded torch tensor from \p effects.
    virtual torch::Tensor EffectsToTensor(std::vector<Effect> effects);

    //! Generates torch tensor from the tasks.
    //! \param tasks The card tasks.
    //! \return The encoded torch tensor from \p tasks.
    virtual torch::Tensor TasksToTensor(std::vector<ITask*> tasks);

    //! Generates torch tensor from the entity.
    //! \param entity The card context.
    //! \return The encoded torch tensor from \p entity.
    virtual torch::Tensor CardToTensor(Entity* entity);

    //! Generates torch tensor from game context.
    //! \param game The game context.
    //! \return The encoded torch tensor from \p game.
    virtual torch::Tensor GenerateTensor(const Game& game);

    //! Gets Effect Embedding Table.
    //! Returns entity type embedding table.
    torch::nn::Embedding GetEffectEmbeddingTable();

    //! Gets Entity Type Embedding Table.
    //! Returns task ID embedding table.
    torch::nn::Embedding GetEntityTypeEmbeddingTable();

    //! Gets Task Id Embedding Table.
    //! \return The embedding table torch tensor.
    torch::nn::Embedding GetTaskIdEmbeddingTable();

    /////////////////////////////////////////////
    static constexpr size_t CLIP_CARD_NORM = 64;
    static constexpr size_t CLIP_EFFECT_NORM = 8;

    /////////////////////////////////////////////
    std::vector<GameTag> EffectGameTag = {
        GameTag::INVALID,  GameTag::ATK,       GameTag::HEALTH,
        GameTag::TAUNT,    GameTag::POISONOUS, GameTag::DIVINE_SHIELD,
        GameTag::WINDFURY, GameTag::STEALTH
    };
    std::vector<EffectOperator> EffectOperatorTag = { EffectOperator::ADD,
                                                      EffectOperator::MUL,
                                                      EffectOperator::SET,
                                                      EffectOperator::SUB };
    static constexpr std::size_t EffectVectorSize = 4;
    static constexpr std::size_t EffectGameTagSize = 8;
    static constexpr std::size_t EffectOperationTagSize = 4;
    static constexpr std::size_t EffectIndexSize =
        EffectGameTagSize * EffectOperationTagSize;

    static constexpr std::size_t AuraVectorSize = 5;

    static constexpr std::size_t EnchantVectorSize = 4;

    static constexpr std::size_t EntityTypeVectorSize = 4;
    static constexpr std::size_t EntityTypeIndexSize = 16;
    static constexpr std::size_t TaskIdVectorSize = 4;
    static constexpr std::size_t TaskIdIndexSize = 27;
    static constexpr std::size_t TaskVectorSize =
        EntityTypeVectorSize + TaskIdVectorSize;

    /////////////////////////////////////////////
    static constexpr std::size_t CardMetaSize = 3;
    static constexpr std::size_t AbilityVectorSize =
        AuraVectorSize + EnchantVectorSize + TaskVectorSize + TaskVectorSize;
    static constexpr std::size_t CardVectorSize =
        CardMetaSize + AbilityVectorSize;

    /////////////////////////////////////////////
    static constexpr std::size_t PlayerMetaSize = 3;
    static constexpr std::size_t GameVectorSize =
        PlayerMetaSize + (CardVectorSize * (HAND_SIZE + 2 * FIELD_SIZE));

 private:
    std::size_t m_seed;

    //! Embedding table for the card
    torch::nn::Embedding m_effectEmbeddingTable = nullptr;
    torch::nn::Embedding m_entityTypeEmbeddingTable = nullptr;
    torch::nn::Embedding m_taskIDEmbeddingTable = nullptr;
};
}  // namespace RosettaTorch

#endif<|endoftext|>


<commit_before>#pragma once

#include <cstdint>
#include <stdexcept>
#include <type_traits>

#include "matrix_connected_components/MatrixUtils.hpp"
#include "utils/NotNull.hpp"
#include "utils/containers/Matrix.hpp"
#include "utils/containers/ValueTypeOf.hpp"

namespace matrix_connected_components {

template <IsNumericalMatrixLike TMatrix>
class MatrixSlice {
public:
  using ValueType = utils::containers::ValueTypeOf<TMatrix>;

  MatrixSlice(TMatrix &matrix, int64_t heightOffset, int64_t widthOffset, int64_t height, int64_t width)
    : m_heightOffset{heightOffset}
    , m_widthOffset{widthOffset}
    , m_height{height}
    , m_width{width}
    , m_matrix{&matrix} {
    if (m_height < 0) {
      throw std::invalid_argument{"The height of the slice cannot be negative!"};
    }
    if (m_width < 0) {
      throw std::invalid_argument{"The width of the slice cannot be negative!"};
    }
    if (m_heightOffset < 0) {
      throw std::invalid_argument{"The height offset of the slice cannot be negative!"};
    }
    if (m_widthOffset < 0) {
      throw std::invalid_argument{"The width offset of the slice cannot be negative!"};
    }
    if (m_heightOffset + m_height > m_matrix->height()) {
      throw std::invalid_argument{
          "The height plus the height offset is greater than the height of the underlying matrix!"};
    }
    if (m_widthOffset + m_width > m_matrix->width()) {
      throw std::invalid_argument{
          "The width plus the width offset is greater than the width of the underlying matrix!"};
    }
  }

  MatrixSlice(const MatrixSlice &) noexcept = default;
  MatrixSlice &operator=(const MatrixSlice &) noexcept = default;
  MatrixSlice(MatrixSlice &&) noexcept = default;
  MatrixSlice &operator=(MatrixSlice &&) noexcept = default;

  ~MatrixSlice() = default;

  [[nodiscard]] int64_t heightOffset() const noexcept {
    return m_heightOffset;
  }
  [[nodiscard]] int64_t widthOffset() const noexcept {
    return m_widthOffset;
  }
  [[nodiscard]] int64_t height() const noexcept {
    return m_height;
  }
  [[nodiscard]] int64_t width() const noexcept {
    return m_width;
  }

  [[nodiscard]] ValueType &get(const int64_t row, const int64_t column) {
    return m_matrix->get(m_heightOffset + row, m_widthOffset + column);
  }

  [[nodiscard]] const ValueType &get(const int64_t row, const int64_t column) const {
    return m_matrix->get(m_heightOffset + row, m_widthOffset + column);
  }

private:
  int64_t m_heightOffset{0};
  int64_t m_widthOffset{0};
  int64_t m_height{0};
  int64_t m_width{0};
  utils::NotNull<TMatrix *> m_matrix;
};

template <typename TMatrix>
MatrixSlice(TMatrix, int64_t, int64_t, int64_t, int64_t) -> MatrixSlice<TMatrix>;

static_assert(IsNumericalMatrixLike<MatrixSlice<utils::containers::Matrix<uint64_t>>>,
              "MatrixSlice has to satisfy IsNumericalMatrixLike, please check the requirements");
static_assert(IsNumericalMatrixLike<MatrixSlice<utils::containers::Matrix<int64_t>>>,
              "MatrixSlice has to satisfy IsNumericalMatrixLike, please check the requirements");

} // namespace matrix_connected_components
<commit_msg>Require simple MatrixSlice to be trivially copyable<commit_after>#pragma once

#include <cstdint>
#include <stdexcept>
#include <type_traits>

#include "matrix_connected_components/MatrixUtils.hpp"
#include "utils/NotNull.hpp"
#include "utils/containers/Matrix.hpp"
#include "utils/containers/ValueTypeOf.hpp"

namespace matrix_connected_components {

template <IsNumericalMatrixLike TMatrix>
class MatrixSlice {
public:
  using ValueType = utils::containers::ValueTypeOf<TMatrix>;

  MatrixSlice(TMatrix &matrix, int64_t heightOffset, int64_t widthOffset, int64_t height, int64_t width)
    : m_heightOffset{heightOffset}
    , m_widthOffset{widthOffset}
    , m_height{height}
    , m_width{width}
    , m_matrix{&matrix} {
    if (m_height < 0) {
      throw std::invalid_argument{"The height of the slice cannot be negative!"};
    }
    if (m_width < 0) {
      throw std::invalid_argument{"The width of the slice cannot be negative!"};
    }
    if (m_heightOffset < 0) {
      throw std::invalid_argument{"The height offset of the slice cannot be negative!"};
    }
    if (m_widthOffset < 0) {
      throw std::invalid_argument{"The width offset of the slice cannot be negative!"};
    }
    if (m_heightOffset + m_height > m_matrix->height()) {
      throw std::invalid_argument{
          "The height plus the height offset is greater than the height of the underlying matrix!"};
    }
    if (m_widthOffset + m_width > m_matrix->width()) {
      throw std::invalid_argument{
          "The width plus the width offset is greater than the width of the underlying matrix!"};
    }
  }

  MatrixSlice(const MatrixSlice &) noexcept = default;
  MatrixSlice &operator=(const MatrixSlice &) noexcept = default;
  MatrixSlice(MatrixSlice &&) noexcept = default;
  MatrixSlice &operator=(MatrixSlice &&) noexcept = default;

  ~MatrixSlice() = default;

  [[nodiscard]] int64_t heightOffset() const noexcept {
    return m_heightOffset;
  }
  [[nodiscard]] int64_t widthOffset() const noexcept {
    return m_widthOffset;
  }
  [[nodiscard]] int64_t height() const noexcept {
    return m_height;
  }
  [[nodiscard]] int64_t width() const noexcept {
    return m_width;
  }

  [[nodiscard]] ValueType &get(const int64_t row, const int64_t column) {
    return m_matrix->get(m_heightOffset + row, m_widthOffset + column);
  }

  [[nodiscard]] const ValueType &get(const int64_t row, const int64_t column) const {
    return m_matrix->get(m_heightOffset + row, m_widthOffset + column);
  }

private:
  int64_t m_heightOffset{0};
  int64_t m_widthOffset{0};
  int64_t m_height{0};
  int64_t m_width{0};
  utils::NotNull<TMatrix *> m_matrix;
};

template <typename TMatrix>
MatrixSlice(TMatrix, int64_t, int64_t, int64_t, int64_t) -> MatrixSlice<TMatrix>;

static_assert(IsNumericalMatrixLike<MatrixSlice<utils::containers::Matrix<uint64_t>>>,
              "MatrixSlice has to satisfy IsNumericalMatrixLike, please check the requirements");
static_assert(IsNumericalMatrixLike<MatrixSlice<utils::containers::Matrix<int64_t>>>,
              "MatrixSlice has to satisfy IsNumericalMatrixLike, please check the requirements");
static_assert(std::is_trivially_copyable_v<MatrixSlice<utils::containers::Matrix<int64_t>>>,
              "MatrixSlice meant to be trivially copyable!");

} // namespace matrix_connected_components
<|endoftext|>


<commit_before>/*******************************************************************************
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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
*
* "@(#) $Id: bulkDataNTSenderFlow.cpp,v 1.36 2012/01/26 11:11:54 bjeram Exp $"
*
* who       when      what
* --------  --------  ----------------------------------------------
* bjeram  2011-04-19  created
*/

static char *rcsId="@(#) $Id: bulkDataNTSenderFlow.cpp,v 1.36 2012/01/26 11:11:54 bjeram Exp $";
static void *use_rcsId = ((void)&use_rcsId,(void *) &rcsId);

#include "bulkDataNTSenderFlow.h"
#include <iostream>
#include "ACS_BD_Errors.h"

using namespace AcsBulkdata;
using namespace std;
using namespace ACS_DDS_Errors;
using namespace ACS_BD_Errors;

BulkDataNTSenderFlow::BulkDataNTSenderFlow(BulkDataNTSenderStream *senderStream,
    const char* flowName,
    const SenderFlowConfiguration &sndCfg/*, cb*/) :
    BulkDataNTFlow(flowName),
    senderStream_m(senderStream),
    senderFlowCfg_m(sndCfg),
    ddsPublisher_m(0), ddsTopic_m(0), writerReaderListener_m(0), ddsDataWriter_m(0), frame_m(0)
{
  AUTO_TRACE(__PRETTY_FUNCTION__);
  std::string streamName, topicName;
  streamName = senderStream_m->getName();
  ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__, (LM_DEBUG, "Going to create Sender Flow: %s @ stream: %s ...", flowName_m.c_str(), streamName.c_str()));

  senderStream->addDDSQoSProfile(sndCfg);

  // should be reactor to have just one object for communication !! DDSDataWriter or similar
  ddsPublisher_m = new BulkDataNTDDSPublisher(senderStream_m->getDDSParticipant(), sndCfg);

  topicName =  streamName + "#" + flowName_m;
  ddsTopic_m = ddsPublisher_m->createDDSTopic(topicName.c_str());

  writerReaderListener_m = new BulkDataNTWriterListener(topicName.c_str());
  ddsDataWriter_m= ddsPublisher_m->createDDSWriter(ddsTopic_m, writerReaderListener_m);

  //RTI probably is enough to create frame once
  frame_m = ACSBulkData::BulkDataNTFrameTypeSupport::create_data();
  if (frame_m == 0)
    {
      //TBD delete dw/topic/publisher
      DDSCreateDataProblemExImpl ex(__FILE__, __LINE__, __PRETTY_FUNCTION__);
      ex.setDataType("ACSBulkData::BulkDataNTFrameTypeSupport");
      throw ex;
    }//if

  setACKsTimeout(senderFlowCfg_m.getACKsTimeout());
  ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__, (LM_DEBUG, "Sender Flow: %s @ stream: %s has been created.", flowName_m.c_str(), streamName.c_str()));
}//BulkDataNTSenderFlow

BulkDataNTSenderFlow::~BulkDataNTSenderFlow()
{
	AUTO_TRACE(__PRETTY_FUNCTION__);
	DDS::ReturnCode_t ret;

	// no matter what happen we remove flow from the map
	senderStream_m->removeFlowFromMap(flowName_m.c_str());

	ret = ACSBulkData::BulkDataNTFrameTypeSupport::delete_data(frame_m);
	if (ret != DDS::RETCODE_OK) {
		ACS_LOG(LM_RUNTIME_CONTEXT, __PRETTY_FUNCTION__, (LM_ERROR, "BulkDataNTFrameTypeSupport::delete_data failed"));
	}//if

	// this part can go to BulkDataNTDDSPublisher, anyway we need to refactor
	DDS::DomainParticipant *participant = senderStream_m->getDDSParticipant();
	if (participant!=0)
	{
		ddsPublisher_m->destroyDDSWriter(ddsDataWriter_m);
		ddsDataWriter_m = 0;
		delete writerReaderListener_m;
		writerReaderListener_m = 0;
		ret = participant->delete_topic(ddsTopic_m);
		if (ret!=DDS::RETCODE_OK)
		{
			ACS_SHORT_LOG((LM_ERROR, "Problem deleting topic (%d)", ret));
		}
		ddsTopic_m=0;
	}
	else
	{
		ACS_LOG(LM_RUNTIME_CONTEXT, __PRETTY_FUNCTION__, (LM_ERROR, "Problem deleting data write and topic participant is NULL"));
	}
	delete ddsPublisher_m;
	ddsPublisher_m=0;
}//~BulkDataNTSenderFlow

unsigned int BulkDataNTSenderFlow::getNumberOfReceivers()
{
	AUTO_TRACE(__PRETTY_FUNCTION__);
	DDS::ReliableReaderActivityChangedStatus status;

	ddsDataWriter_m->get_reliable_reader_activity_changed_status(status);
	return status.active_count;
}//getNumberOfReceivers

void BulkDataNTSenderFlow::setACKsTimeout(double ACKsTimeout)
{
	DDS::Long ackTOSec = static_cast<DDS::Long>(ACKsTimeout);
	DDS::Long ackTONanosec = 1000000 * static_cast<DDS::Long>(ACKsTimeout - ackTOSec);

	ackTimeout_m.sec = ackTOSec;
	ackTimeout_m.nanosec = ackTONanosec;
	ACS_LOG(LM_RUNTIME_CONTEXT, __PRETTY_FUNCTION__, (LM_DEBUG, "ACKsTimeout set to: %d sec %d nanosec",
			ackTOSec, ackTONanosec));
}//setACKsTimeout

void BulkDataNTSenderFlow::startSend(ACE_Message_Block *param)
{
	startSend((unsigned char*)(param->rd_ptr()), param->length());
}

void BulkDataNTSenderFlow::startSend(const unsigned char *param, size_t len)
{
	try
	{
		writeFrame(ACSBulkData::BD_PARAM, param, len);
	}catch(const ACSErr::ACSbaseExImpl &ex)
	{
		StartSendErrorExImpl ssEx(ex, __FILE__, __LINE__, __FUNCTION__);
		ssEx.setSenderName(senderStream_m->getName().c_str()); ssEx.setFlowName(flowName_m.c_str());
		throw ssEx;
	}
}//startSend

void BulkDataNTSenderFlow::sendData(const unsigned char *buffer, size_t len)
{
	unsigned int iteration;
	unsigned int sizeOfFrame = ACSBulkData::FRAME_MAX_LEN;  //TBD: should be configurable ?

	unsigned int numOfFrames = len / sizeOfFrame; // how many frames of size sizeOfFrame do we have to send
	unsigned int restFrameSize = len % sizeOfFrame; // what is the rest

	if (DDSConfiguration::debugLevel>0)
	{
		// the message can cause perfomance penality for small data sizes
		ACS_SHORT_LOG((LM_DEBUG, "Going to send: %zd Bytes = %d*%d(=%d) + %d to flow: %s",
			len, numOfFrames, sizeOfFrame, numOfFrames*sizeOfFrame, restFrameSize, flowName_m.c_str()));
	}//if
	unsigned int numOfIter = (restFrameSize>0) ? numOfFrames+1 : numOfFrames;

	try{
		//	start_time = ACE_OS::gettimeofday();
		for(iteration=0; iteration<numOfIter; iteration++)
		{
			if (iteration==(numOfIter-1) && restFrameSize>0)
			{
				// last frame
				writeFrame(ACSBulkData::BD_DATA, (buffer+(iteration*sizeOfFrame)), restFrameSize, numOfIter-1-iteration);
			}else
			{
				writeFrame(ACSBulkData::BD_DATA, (buffer+(iteration*sizeOfFrame)), sizeOfFrame, numOfIter-1-iteration/*, (iteration%100==0)*/);
			}
		}//for
		// at this point we have sent all frames, we could wait for ACKs, but it is done in writeFrame
	}catch(const ACSErr::ACSbaseExImpl &ex)
	{
		SendDataErrorExImpl sfEx(ex, __FILE__, __LINE__, __FUNCTION__);
		sfEx.setSenderName(senderStream_m->getName().c_str()); sfEx.setFlowName(flowName_m.c_str());
		sfEx.setFrameCount(iteration); sfEx.setTotalFrameCount(numOfIter);
		throw sfEx;
	}//try-catch
}//sendData

void BulkDataNTSenderFlow::stopSend()
{
	try
	{
		writeFrame(ACSBulkData::BD_STOP);
	}catch(const ACSErr::ACSbaseExImpl &ex)
	{
		StopSendErrorExImpl ssEx(ex, __FILE__, __LINE__, __FUNCTION__);
		ssEx.setSenderName(senderStream_m->getName().c_str()); ssEx.setFlowName(flowName_m.c_str());
		throw ssEx;
	}
}//stopSend

void BulkDataNTSenderFlow::writeFrame(ACSBulkData::DataType dataType,  const unsigned char *param, size_t len, unsigned int restFrameCount, bool waitForACKs)
{
	DDS::ReturnCode_t ret;
	DDS::ReliableWriterCacheChangedStatus status; //RTI

	if (len>ACSBulkData::FRAME_MAX_LEN){
		FrameTooLongExImpl ftlEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
		ftlEx.setFrameLength(len);
		ftlEx.setMaxFrameLength(ACSBulkData::FRAME_MAX_LEN);
		throw ftlEx;
	}//if

	//frame
	frame_m->dataType = dataType;
	frame_m->data.length(len);
	frame_m->restDataLength = restFrameCount; //we need it just in some cases, but we can always set to 0
	if (param!=0 && len!=0)
		frame_m->data.from_array(param, len);

	ret = ddsDataWriter_m->write(*frame_m, DDS::HANDLE_NIL);

	if( ret != DDS::RETCODE_OK)
	{
		ddsDataWriter_m->get_reliable_writer_cache_changed_status(status); //RTI
		if (ret==DDS::RETCODE_TIMEOUT)
		{
			SendFrameTimeoutExImpl toEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
			toEx.setSenderName(senderStream_m->getName().c_str()); toEx.setFlowName(flowName_m.c_str());
			toEx.setTimeout(senderFlowCfg_m.getSendFrameTimeout());
			toEx.setFrameCount(restFrameCount);
			throw toEx;
		}else
		{
			SendFrameGenericErrorExImpl sfEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
			sfEx.setSenderName(senderStream_m->getName().c_str()); sfEx.setFlowName(flowName_m.c_str());
			sfEx.setFrameCount(restFrameCount);
			sfEx.setRetCode(ret);
			throw sfEx;
		}//if-else

		ddsDataWriter_m->get_reliable_writer_cache_changed_status(status); //RTI
		ACS_SHORT_LOG((LM_DEBUG, "unacknowledged_sample_count (%d) for flow: %s", status.unacknowledged_sample_count, flowName_m.c_str())); //RTI
		// RTI			cout << "\t\t Int unacknowledged_sample_count_peak: " << status.unacknowledged_sample_count_peak << endl;
		ret = ddsDataWriter_m->wait_for_acknowledgments(ackTimeout_m);
		if( ret != DDS::RETCODE_OK)
		{
			FrameAckTimeoutExImpl ackToEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
			ackToEx.setSenderName(senderStream_m->getName().c_str()); ackToEx.setFlowName(flowName_m.c_str());
			ackToEx.setTimeout(ackTimeout_m.sec + ackTimeout_m.nanosec/1000000.0);
			throw ackToEx; //	ackToEx.log(LM_WARNING);
		}//if

		ddsDataWriter_m->get_reliable_writer_cache_changed_status(status); //RTI
		ACS_SHORT_LOG((LM_DEBUG, "unacknowledged_sample_count after waiting: (%d)", status.unacknowledged_sample_count)); //RTI
		//cout << "\t\t Int1 unacknowledged_sample_count_peak: " << status.unacknowledged_sample_count_peak << endl;
	}//if (ret != DDS::RETCODE_OK)

	//we wait for ACKs if it is explecitly asked or if it was the last frame (only frame)
	if (waitForACKs || restFrameCount==0)
	{
		ddsDataWriter_m->get_reliable_writer_cache_changed_status(status); //RTI
		if (DDSConfiguration::debugLevel>0)
		{
			// the message can cause perfomance penality for small data sizes
			ACS_SHORT_LOG((LM_DEBUG, "unacknowledged_sample_count (%d) before waiting: %d", dataType, status.unacknowledged_sample_count)); //RTI
		}
		ret = ddsDataWriter_m->wait_for_acknowledgments(ackTimeout_m);
		if( ret != DDS::RETCODE_OK)
		{
			FrameAckTimeoutExImpl ackToEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
			ackToEx.setSenderName(senderStream_m->getName().c_str()); ackToEx.setFlowName(flowName_m.c_str());
			ackToEx.setTimeout(ackTimeout_m.sec + ackTimeout_m.nanosec/1000000.0);
			throw ackToEx; //	ackToEx.log(LM_WARNING);
		}//if
	}//if (waitForACKs || restFrameCount==0)
}//writeFrame

/*___oOo___*/
<commit_msg>using dataType2String where possilbe<commit_after>/*******************************************************************************
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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
*
* "@(#) $Id: bulkDataNTSenderFlow.cpp,v 1.37 2012/01/26 14:49:20 bjeram Exp $"
*
* who       when      what
* --------  --------  ----------------------------------------------
* bjeram  2011-04-19  created
*/

static char *rcsId="@(#) $Id: bulkDataNTSenderFlow.cpp,v 1.37 2012/01/26 14:49:20 bjeram Exp $";
static void *use_rcsId = ((void)&use_rcsId,(void *) &rcsId);

#include "bulkDataNTSenderFlow.h"
#include <iostream>
#include "ACS_BD_Errors.h"

using namespace AcsBulkdata;
using namespace std;
using namespace ACS_DDS_Errors;
using namespace ACS_BD_Errors;

BulkDataNTSenderFlow::BulkDataNTSenderFlow(BulkDataNTSenderStream *senderStream,
    const char* flowName,
    const SenderFlowConfiguration &sndCfg/*, cb*/) :
    BulkDataNTFlow(flowName),
    senderStream_m(senderStream),
    senderFlowCfg_m(sndCfg),
    ddsPublisher_m(0), ddsTopic_m(0), writerReaderListener_m(0), ddsDataWriter_m(0), frame_m(0)
{
  AUTO_TRACE(__PRETTY_FUNCTION__);
  std::string streamName, topicName;
  streamName = senderStream_m->getName();
  ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__, (LM_DEBUG, "Going to create Sender Flow: %s @ stream: %s ...", flowName_m.c_str(), streamName.c_str()));

  senderStream->addDDSQoSProfile(sndCfg);

  // should be reactor to have just one object for communication !! DDSDataWriter or similar
  ddsPublisher_m = new BulkDataNTDDSPublisher(senderStream_m->getDDSParticipant(), sndCfg);

  topicName =  streamName + "#" + flowName_m;
  ddsTopic_m = ddsPublisher_m->createDDSTopic(topicName.c_str());

  writerReaderListener_m = new BulkDataNTWriterListener(topicName.c_str());
  ddsDataWriter_m= ddsPublisher_m->createDDSWriter(ddsTopic_m, writerReaderListener_m);

  //RTI probably is enough to create frame once
  frame_m = ACSBulkData::BulkDataNTFrameTypeSupport::create_data();
  if (frame_m == 0)
    {
      //TBD delete dw/topic/publisher
      DDSCreateDataProblemExImpl ex(__FILE__, __LINE__, __PRETTY_FUNCTION__);
      ex.setDataType("ACSBulkData::BulkDataNTFrameTypeSupport");
      throw ex;
    }//if

  setACKsTimeout(senderFlowCfg_m.getACKsTimeout());
  ACS_LOG(LM_RUNTIME_CONTEXT, __FUNCTION__, (LM_DEBUG, "Sender Flow: %s @ stream: %s has been created.", flowName_m.c_str(), streamName.c_str()));
}//BulkDataNTSenderFlow

BulkDataNTSenderFlow::~BulkDataNTSenderFlow()
{
	AUTO_TRACE(__PRETTY_FUNCTION__);
	DDS::ReturnCode_t ret;

	// no matter what happen we remove flow from the map
	senderStream_m->removeFlowFromMap(flowName_m.c_str());

	ret = ACSBulkData::BulkDataNTFrameTypeSupport::delete_data(frame_m);
	if (ret != DDS::RETCODE_OK) {
		ACS_LOG(LM_RUNTIME_CONTEXT, __PRETTY_FUNCTION__, (LM_ERROR, "BulkDataNTFrameTypeSupport::delete_data failed"));
	}//if

	// this part can go to BulkDataNTDDSPublisher, anyway we need to refactor
	DDS::DomainParticipant *participant = senderStream_m->getDDSParticipant();
	if (participant!=0)
	{
		ddsPublisher_m->destroyDDSWriter(ddsDataWriter_m);
		ddsDataWriter_m = 0;
		delete writerReaderListener_m;
		writerReaderListener_m = 0;
		ret = participant->delete_topic(ddsTopic_m);
		if (ret!=DDS::RETCODE_OK)
		{
			ACS_SHORT_LOG((LM_ERROR, "Problem deleting topic (%d)", ret));
		}
		ddsTopic_m=0;
	}
	else
	{
		ACS_LOG(LM_RUNTIME_CONTEXT, __PRETTY_FUNCTION__, (LM_ERROR, "Problem deleting data write and topic participant is NULL"));
	}
	delete ddsPublisher_m;
	ddsPublisher_m=0;
}//~BulkDataNTSenderFlow

unsigned int BulkDataNTSenderFlow::getNumberOfReceivers()
{
	AUTO_TRACE(__PRETTY_FUNCTION__);
	DDS::ReliableReaderActivityChangedStatus status;

	ddsDataWriter_m->get_reliable_reader_activity_changed_status(status);
	return status.active_count;
}//getNumberOfReceivers

void BulkDataNTSenderFlow::setACKsTimeout(double ACKsTimeout)
{
	DDS::Long ackTOSec = static_cast<DDS::Long>(ACKsTimeout);
	DDS::Long ackTONanosec = 1000000 * static_cast<DDS::Long>(ACKsTimeout - ackTOSec);

	ackTimeout_m.sec = ackTOSec;
	ackTimeout_m.nanosec = ackTONanosec;
	ACS_LOG(LM_RUNTIME_CONTEXT, __PRETTY_FUNCTION__, (LM_DEBUG, "ACKsTimeout set to: %d sec %d nanosec",
			ackTOSec, ackTONanosec));
}//setACKsTimeout

void BulkDataNTSenderFlow::startSend(ACE_Message_Block *param)
{
	startSend((unsigned char*)(param->rd_ptr()), param->length());
}

void BulkDataNTSenderFlow::startSend(const unsigned char *param, size_t len)
{
	try
	{
		writeFrame(ACSBulkData::BD_PARAM, param, len);
	}catch(const ACSErr::ACSbaseExImpl &ex)
	{
		StartSendErrorExImpl ssEx(ex, __FILE__, __LINE__, __FUNCTION__);
		ssEx.setSenderName(senderStream_m->getName().c_str()); ssEx.setFlowName(flowName_m.c_str());
		throw ssEx;
	}
}//startSend

void BulkDataNTSenderFlow::sendData(const unsigned char *buffer, size_t len)
{
	unsigned int iteration;
	unsigned int sizeOfFrame = ACSBulkData::FRAME_MAX_LEN;  //TBD: should be configurable ?

	unsigned int numOfFrames = len / sizeOfFrame; // how many frames of size sizeOfFrame do we have to send
	unsigned int restFrameSize = len % sizeOfFrame; // what is the rest

	if (DDSConfiguration::debugLevel>0)
	{
		// the message can cause perfomance penality for small data sizes
		ACS_SHORT_LOG((LM_DEBUG, "Going to send: %zd Bytes = %d*%d(=%d) + %d to flow: %s",
			len, numOfFrames, sizeOfFrame, numOfFrames*sizeOfFrame, restFrameSize, flowName_m.c_str()));
	}//if
	unsigned int numOfIter = (restFrameSize>0) ? numOfFrames+1 : numOfFrames;

	try{
		//	start_time = ACE_OS::gettimeofday();
		for(iteration=0; iteration<numOfIter; iteration++)
		{
			if (iteration==(numOfIter-1) && restFrameSize>0)
			{
				// last frame
				writeFrame(ACSBulkData::BD_DATA, (buffer+(iteration*sizeOfFrame)), restFrameSize, numOfIter-1-iteration);
			}else
			{
				writeFrame(ACSBulkData::BD_DATA, (buffer+(iteration*sizeOfFrame)), sizeOfFrame, numOfIter-1-iteration/*, (iteration%100==0)*/);
			}
		}//for
		// at this point we have sent all frames, we could wait for ACKs, but it is done in writeFrame
	}catch(const ACSErr::ACSbaseExImpl &ex)
	{
		SendDataErrorExImpl sfEx(ex, __FILE__, __LINE__, __FUNCTION__);
		sfEx.setSenderName(senderStream_m->getName().c_str()); sfEx.setFlowName(flowName_m.c_str());
		sfEx.setFrameCount(iteration); sfEx.setTotalFrameCount(numOfIter);
		throw sfEx;
	}//try-catch
}//sendData

void BulkDataNTSenderFlow::stopSend()
{
	try
	{
		writeFrame(ACSBulkData::BD_STOP);
	}catch(const ACSErr::ACSbaseExImpl &ex)
	{
		StopSendErrorExImpl ssEx(ex, __FILE__, __LINE__, __FUNCTION__);
		ssEx.setSenderName(senderStream_m->getName().c_str()); ssEx.setFlowName(flowName_m.c_str());
		throw ssEx;
	}
}//stopSend

void BulkDataNTSenderFlow::writeFrame(ACSBulkData::DataType dataType,  const unsigned char *param, size_t len, unsigned int restFrameCount, bool waitForACKs)
{
	DDS::ReturnCode_t ret;
	DDS::ReliableWriterCacheChangedStatus status; //RTI

	if (len>ACSBulkData::FRAME_MAX_LEN){
		FrameTooLongExImpl ftlEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
		ftlEx.setFrameLength(len);
		ftlEx.setMaxFrameLength(ACSBulkData::FRAME_MAX_LEN);
		throw ftlEx;
	}//if

	//frame
	frame_m->dataType = dataType;
	frame_m->data.length(len);
	frame_m->restDataLength = restFrameCount; //we need it just in some cases, but we can always set to 0
	if (param!=0 && len!=0)
		frame_m->data.from_array(param, len);

	ret = ddsDataWriter_m->write(*frame_m, DDS::HANDLE_NIL);

	if( ret != DDS::RETCODE_OK)
	{
		ddsDataWriter_m->get_reliable_writer_cache_changed_status(status); //RTI
		if (ret==DDS::RETCODE_TIMEOUT)
		{
			SendFrameTimeoutExImpl toEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
			toEx.setSenderName(senderStream_m->getName().c_str()); toEx.setFlowName(flowName_m.c_str());
			toEx.setTimeout(senderFlowCfg_m.getSendFrameTimeout());
			toEx.setFrameCount(restFrameCount);
			throw toEx;
		}else
		{
			SendFrameGenericErrorExImpl sfEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
			sfEx.setSenderName(senderStream_m->getName().c_str()); sfEx.setFlowName(flowName_m.c_str());
			sfEx.setFrameCount(restFrameCount);
			sfEx.setRetCode(ret);
			throw sfEx;
		}//if-else

		ddsDataWriter_m->get_reliable_writer_cache_changed_status(status); //RTI
		ACS_SHORT_LOG((LM_DEBUG, "unacknowledged_sample_count (%s) %d for flow: %s", dataType2String[dataType], status.unacknowledged_sample_count, flowName_m.c_str())); //RTI
		// RTI			cout << "\t\t Int unacknowledged_sample_count_peak: " << status.unacknowledged_sample_count_peak << endl;
		ret = ddsDataWriter_m->wait_for_acknowledgments(ackTimeout_m);
		if( ret != DDS::RETCODE_OK)
		{
			FrameAckTimeoutExImpl ackToEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
			ackToEx.setSenderName(senderStream_m->getName().c_str()); ackToEx.setFlowName(flowName_m.c_str());
			ackToEx.setTimeout(ackTimeout_m.sec + ackTimeout_m.nanosec/1000000.0);
			throw ackToEx; //	ackToEx.log(LM_WARNING);
		}//if

		ddsDataWriter_m->get_reliable_writer_cache_changed_status(status); //RTI
		ACS_SHORT_LOG((LM_DEBUG, "unacknowledged_sample_count (%s) after waiting: %d", dataType2String[dataType], status.unacknowledged_sample_count)); //RTI
		//cout << "\t\t Int1 unacknowledged_sample_count_peak: " << status.unacknowledged_sample_count_peak << endl;
	}//if (ret != DDS::RETCODE_OK)

	//we wait for ACKs if it is explecitly asked or if it was the last frame (only frame)
	if (waitForACKs || restFrameCount==0)
	{
		ddsDataWriter_m->get_reliable_writer_cache_changed_status(status); //RTI
		if (DDSConfiguration::debugLevel>0)
		{
			// the message can cause perfomance penality for small data sizes
			ACS_SHORT_LOG((LM_DEBUG, "unacknowledged_sample_count (%s) before waiting: %d", dataType2String[dataType], status.unacknowledged_sample_count)); //RTI
		}
		ret = ddsDataWriter_m->wait_for_acknowledgments(ackTimeout_m);
		if( ret != DDS::RETCODE_OK)
		{
			FrameAckTimeoutExImpl ackToEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
			ackToEx.setSenderName(senderStream_m->getName().c_str()); ackToEx.setFlowName(flowName_m.c_str());
			ackToEx.setTimeout(ackTimeout_m.sec + ackTimeout_m.nanosec/1000000.0);
			throw ackToEx; //	ackToEx.log(LM_WARNING);
		}//if
	}//if (waitForACKs || restFrameCount==0)
}//writeFrame

/*___oOo___*/
<|endoftext|>